Commits

Stefan Saasen committed 28d5605

Update the initial example to show how to use Ruby objects in Java.

  • Participants
  • Parent commits 9c1e7f2

Comments (0)

Files changed (8)

File src/main/java/com/atlassian/plugins/polyglot/jrubyexample/bridge/ScriptingContainerProviderImpl.java

 import org.jruby.embed.LocalContextScope;
 import org.jruby.embed.LocalVariableBehavior;
 import org.jruby.embed.ScriptingContainer;
-import org.jruby.embed.osgi.OSGiScriptingContainer;
 import org.jruby.util.KCode;
-import org.osgi.framework.BundleContext;
 import org.springframework.beans.factory.DisposableBean;
-import org.springframework.osgi.context.BundleContextAware;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Nullable;

File src/main/java/com/atlassian/plugins/polyglot/jrubyexample/servlet/ExampleRubyServlet.java

 package com.atlassian.plugins.polyglot.jrubyexample.servlet;
 
 import com.atlassian.plugins.polyglot.jrubyexample.bridge.ScriptingContainerProvider;
+import com.atlassian.templaterenderer.TemplateRenderer;
+import org.apache.commons.lang.StringUtils;
+import org.jruby.embed.EvalFailedException;
+import org.jruby.embed.InvokeFailedException;
 import org.jruby.embed.PathType;
 import org.jruby.embed.ScriptingContainer;
+import org.jruby.exceptions.RaiseException;
 
-import javax.script.*;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.util.List;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Simple Servlet that shows how to execute a Ruby script.
 public class ExampleRubyServlet extends HttpServlet {
 
     private final ScriptingContainerProvider scriptingContainerProvider;
+    private final TemplateRenderer templateRenderer;
 
-    public ExampleRubyServlet(ScriptingContainerProvider scriptingContainerProvider) {
+    public ExampleRubyServlet(ScriptingContainerProvider scriptingContainerProvider, TemplateRenderer templateRenderer) {
         this.scriptingContainerProvider = scriptingContainerProvider;
+        this.templateRenderer = templateRenderer;
     }
 
 
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        resp.setContentType("text/plain");
-
-        final PrintWriter writer = resp.getWriter();
-        if (null == req.getParameter("url")) {
-            writer.write("Param 'url' is missing");
-            return;
+        resp.setContentType("text/html");
+
+        final String url = req.getParameter("url");
+
+        Map<String, Object> ctx = new HashMap<String, Object>();
+
+        if (StringUtils.isNotBlank(url)) {
+            try {
+                ScriptingContainer container = scriptingContainerProvider.getScriptingContainer();
+                container.runScriptlet("require 'rurl'");
+
+                Object rurl = container.runScriptlet("Rurl.new");
+                HttpResponseInformation responseInformation = (HttpResponseInformation) container.callMethod(rurl, "curl", url);
+                ctx.put("responseInformation", responseInformation);
+                ctx.put("url", url);
+            } catch (RaiseException re) {
+                ctx.put("error", re.getLocalizedMessage());
+            } catch (EvalFailedException efe) {
+                ctx.put("error", efe.getLocalizedMessage());
+            } catch (InvokeFailedException ife) {
+                ctx.put("error", ife.getLocalizedMessage());
+            }
         }
-
-        ScriptingContainer container = scriptingContainerProvider.getScriptingContainer();
-
-        container.put("@url", req.getParameter("url"));
-        container.setWriter(writer);
-        container.runScriptlet(PathType.CLASSPATH, "/do_http_request.rb");
+        templateRenderer.render("/templates/rurl.vm", ctx, resp.getWriter());
     }
 
 }

File src/main/java/com/atlassian/plugins/polyglot/jrubyexample/servlet/HttpResponseInformation.java

+package com.atlassian.plugins.polyglot.jrubyexample.servlet;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Define an interface to allow Ruby objects to be used in Java in a meaningful way.
+ *
+ * The Ruby class needs to "implement" the interface by including it as a module:
+ * <pre>
+ *     require 'java'
+ *
+ *     class RurlResponse
+ *       include Java::com.atlassian.plugins.polyglot.jrubyexample.servlet.HttpResponseInformation
+ *       ...
+ *     end
+ * </pre>
+ */
+public interface HttpResponseInformation {
+    Map<String,String> getHttpHeaders();
+    List<String> getBodyLines();
+}

File src/main/resources/atlassian-plugin.xml

 
     <web-resource key="jruby-plugin-resources" name="JRuby Example Resources">
         <resource type="download" name="underscore.js" location="/js/underscore-min.js"/>
-
         <resource type="download" name="bootstrap.css" location="/css/bootstrap.min.css"/>
     </web-resource>
 
         <url-pattern>/jruby</url-pattern>
     </servlet>
 
+    <component-import key="velocity-renderer" interface="com.atlassian.templaterenderer.TemplateRenderer"/>
 </atlassian-plugin>

File src/main/resources/templates/rurl.vm

+#* @vtlvariable name="webResourceManager" type="com.atlassian.plugin.webresource.WebResourceManager" *#
+#* @vtlvariable name="responseInformation" type="com.atlassian.plugins.polyglot.jrubyexample.servlet.HttpResponseInformation" *#
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="">
+    <meta name="author" content="">
+    <meta charset="utf-8">
+    #set($includesHtml = $webResourceManager.getResourceTags("com.atlassian.example.jrubyplugin:jruby-plugin-resources"))
+    $includesHtml
+
+    <style type="text/css">
+        body {
+            padding-top: 60px;
+            padding-bottom: 40px;
+        }
+    </style>
+</head>
+<body>
+
+<div class="navbar navbar-fixed-top">
+    <div class="navbar-inner">
+        <div class="container">
+            <a class="brand" href="#">JRuby Example</a>
+        </div>
+    </div>
+
+
+<div class="container">
+
+    #if($error)
+    <div class="alert alert-error">
+        $error
+    </div>
+    #end
+
+    #if(!$responseInformation)
+        <div class="hero-unit">
+            <h1>Make an HTTP Request</h1>
+            <p>
+                Make an HTTP request and view the response headers.
+            </p>
+        </div>
+    #end
+    <form action="?" class="well form-inline">
+        <input type="text" name="url" value="$!url" class="span9"/>
+        <button type="submit" class="btn">Submit</button>
+    </form>
+
+
+#if($responseInformation)
+
+        <h3>Response Headers</h3>
+<pre>
+#foreach($header in $responseInformation.httpHeaders.entrySet())
+$header.key: $header.value
+#end
+</pre>
+        <h3>Response Body</h3>
+<pre>
+#foreach($header in $responseInformation.bodyLines)
+$header
+#end
+</pre>
+#end
+
+</div>
+</body>
+</html>

File src/main/ruby/do_http_request.rb

-require 'rubygems'
-require 'rack'
 require 'open-uri'
-require 'pp'
-require 'rio'
+require 'java'
 
-open(@url) do |f|
-  # hash with meta information
-  pp  f.meta
-
-  pp "Content-Type: " + f.content_type
-  pp "last modified" + f.last_modified.to_s
-
-  # print the first three lines
-  f.each_with_index do |line, no|
-    print "#{no}: #{line}"
+class RurlResponse
+  include Java::com.atlassian.plugins.polyglot.jrubyexample.servlet.HttpResponseInformation
+  attr_accessor :http_headers, :body_lines
+  def initialize(http_headers, body_lines)
+    @http_headers, @body_lines = http_headers, body_lines
   end
 end
 
-
-# Use a bundled gem instead.
-p rio(@url).read
+class Rurl
+  def curl(url)
+    url = ("http://#{url}" unless url =~ /^http/).strip
+    open(url) do |f|
+      RurlResponse.new(f.meta, f.each_line.to_a[1..10])
+    end
+  end
+end

File src/main/ruby/rurl.rb

+require 'rubygems'
+require 'open-uri'
+require 'java'
+
+class RurlResponse
+  include Java::com.atlassian.plugins.polyglot.jrubyexample.servlet.HttpResponseInformation
+  attr_accessor :http_headers, :body_lines
+  def initialize(http_headers, body_lines)
+    @http_headers, @body_lines = http_headers, body_lines
+  end
+end
+
+class Rurl
+  def curl(url)
+    open(url) do |f|
+      RurlResponse.new(f.meta, f.each_line.to_a)
+    end
+  end
+end

File src/test/java/it/IntegrationTestMyPlugin.java

         gotoPage("/plugins/servlet/sinatra/");
         assertTextPresent("Dashboard");
     }
+
+    public void testRurl() {
+        gotoPage("/plugins/servlet/jruby");
+        assertTextPresent("Make an HTTP Request");
+    }
 }