You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2009/06/11 18:57:34 UTC

svn commit: r783847 - in /camel/trunk/components/camel-web: pom.xml src/main/java/org/apache/camel/web/resources/RouteResource.java src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp

Author: janstey
Date: Thu Jun 11 16:57:34 2009
New Revision: 783847

URL: http://svn.apache.org/viewvc?rev=783847&view=rev
Log:
CAMEL-1655 - Add support for saving Groovy and Ruby route code. Viewing
as Groovy or Ruby is TBD.

Thanks to Xueqiang Mi for this contribution!


Modified:
    camel/trunk/components/camel-web/pom.xml
    camel/trunk/components/camel-web/src/main/java/org/apache/camel/web/resources/RouteResource.java
    camel/trunk/components/camel-web/src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp

Modified: camel/trunk/components/camel-web/pom.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/pom.xml?rev=783847&r1=783846&r2=783847&view=diff
==============================================================================
--- camel/trunk/components/camel-web/pom.xml (original)
+++ camel/trunk/components/camel-web/pom.xml Thu Jun 11 16:57:34 2009
@@ -73,6 +73,14 @@
       <artifactId>camel-spring</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-groovy</artifactId>
+    </dependency>
+    <dependency>
+    	<groupId>org.apache.camel</groupId>
+    	<artifactId>camel-ruby</artifactId>
+    </dependency>
+    <dependency>
       <groupId>com.sun.jersey.contribs</groupId>
       <artifactId>jersey-spring</artifactId>
       <version>${jersey-version}</version>

Modified: camel/trunk/components/camel-web/src/main/java/org/apache/camel/web/resources/RouteResource.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/java/org/apache/camel/web/resources/RouteResource.java?rev=783847&r1=783846&r2=783847&view=diff
==============================================================================
--- camel/trunk/components/camel-web/src/main/java/org/apache/camel/web/resources/RouteResource.java (original)
+++ camel/trunk/components/camel-web/src/main/java/org/apache/camel/web/resources/RouteResource.java Thu Jun 11 16:57:34 2009
@@ -16,12 +16,15 @@
  */
 package org.apache.camel.web.resources;
 
+import java.io.File;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Collections;
+import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -39,12 +42,17 @@
 
 import com.sun.jersey.api.representation.Form;
 import com.sun.jersey.api.view.Viewable;
+import groovy.lang.GroovyClassLoader;
 
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.ruby.RubyCamel;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.view.RouteDotGenerator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.jruby.Main;
 
 /**
  * A single Camel Route which is used to implement one or more
@@ -54,11 +62,23 @@
  */
 public class RouteResource extends CamelChildResourceSupport {
     private static final transient Log LOG = LogFactory.getLog(RouteResource.class);
+    private static final String LANGUAGE_XML = "Xml";
+    private static final String LANGUAGE_GROOVY = "Groovy";
+    private static final String LANGUAGE_RUBY = "Ruby";
+    private static final String LANGUAGE_SCALA = "Scala";
 
     private RouteDefinition route;
     private String error = "";
     private String id;
 
+    // what language is used to define this route
+    private String language = LANGUAGE_XML;
+  
+    // the route configuration: when language is Xml, the routeDefinition is
+    // null; when language is Groovy/Scala/Ruby, the routeDefinition contains
+    // the route definition class. It must be initialized because RouteResource
+    // is stateless.
+    private String routeDefinition = "";
 
     public RouteResource(RoutesResource routesResource, RouteDefinition route) {
         super(routesResource.getContextResource());
@@ -83,15 +103,40 @@
         Marshaller marshaller = context.createMarshaller();
         marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
         // TODO fix to use "" namespace prefix
-        // using this https://jaxb.dev.java.net/nonav/2.1.10/docs/vendorProperties.html#prefixmapper
+        // using this
+        // https://jaxb.dev.java.net/nonav/2.1.10/docs/vendorProperties.html#prefixmapper
         StringWriter buffer = new StringWriter();
         marshaller.marshal(route, buffer);
         return buffer.toString();
     }
 
     /**
-     * Returns the Graphviz DOT <a href="http://camel.apache.org/visualisation.html">Visualisation</a>
-     * of this route
+     * Returns the language
+     */
+    public String getLanguage() {
+        return language;
+    }
+
+    /**
+     * Returns the content of the route definition class
+     */
+    public String getRouteDefinition() {
+        if (language.equals(LANGUAGE_XML)) {
+            try {
+                return getRouteXml();
+            } catch (JAXBException e) {
+                // e.printStackTrace();
+                return "Error on marshal the route definition!";
+            }
+        } else {
+            return routeDefinition;
+        }
+    }
+
+    /**
+     * Returns the Graphviz DOT <a
+     * href="http://camel.apache.org/visualisation.html">Visualisation</a> of
+     * this route
      */
     @GET
     @Produces(Constants.DOT_MIMETYPE)
@@ -100,7 +145,6 @@
         return generator.getRoutesText(getCamelContext());
     }
 
-
     /**
      * Allows a route definition to be updated
      */
@@ -115,46 +159,188 @@
         getCamelContext().addRouteDefinitions(Collections.singletonList(routeDefinition));
     }
 
+    /**
+     * Allows a routes builder to be updated
+     */
+    public void postRoutes(RouteBuilder builder) throws Exception {
+        // remove current route
+        DefaultCamelContext camelContext = (DefaultCamelContext)getCamelContext();
+        camelContext.removeRouteDefinition(id);
+
+        // lets install the updated routes
+        camelContext.addRoutes(builder);
+    }
 
     /**
      * Updates a route definition using form encoded data from a web form
-     *
-     * @param formData is the form data POSTed typically from a HTML form with the <code>route</code> field used to encode
-     *                 the XML text of the new route definition
+     * 
+     * @param formData is the form data POSTed typically from a HTML form with
+     *            the <code>route</code> field used to encode the XML text of
+     *            the new route definition
      */
     @POST
     @Consumes("application/x-www-form-urlencoded")
     public Response postRouteForm(@Context UriInfo uriInfo, Form formData) throws URISyntaxException {
         // TODO replace the Form class with an injected bean?
-        String xml = formData.getFirst("route", String.class);
+        String language = formData.getFirst("language", String.class);
+        String body = formData.getFirst("route", String.class);
         if (LOG.isDebugEnabled()) {
-            LOG.debug("new XML is: " + xml);
+            LOG.debug("new Route is: " + body);
         }
-        if (xml == null) {
-            error = "No XML submitted!";
-        } else {
-            try {
-                JAXBContext context = JAXBContext.newInstance(Constants.JAXB_PACKAGES);
-                Unmarshaller unmarshaller = context.createUnmarshaller();
-                Object value = unmarshaller.unmarshal(new StringReader(xml));
-                if (value instanceof RouteDefinition) {
-                    RouteDefinition routeDefinition = (RouteDefinition) value;
-                    postRoute(routeDefinition);
-                    return Response.seeOther(new URI("/routes")).build();
-                } else {
-                    error = "Posted XML is not a route but is of type " + ObjectHelper.className(value);
-                }
-            } catch (JAXBException e) {
-                error = "Failed to parse XML: " + e.getMessage();
-            } catch (Exception e) {
-                error = "Failed to install route: " + e.getMessage();
+        LOG.info(body);
+        if (body == null) {
+            error = "No Route submitted!";
+        } else if (language.equals(LANGUAGE_XML)) {
+            return parseXml(body);
+        } else if (language.equals(LANGUAGE_GROOVY)) {
+            return parseGroovy(body);
+        } else if (language.equals(LANGUAGE_RUBY)) {
+            return parseRuby(body);
+        } else if (language.equals(LANGUAGE_SCALA)) {
+            return parseScala(body);
+        }
+        error = "Not supproted language!";
+        return Response.ok(new Viewable("edit", this)).build();
+
+    }
+
+    /**
+     * process the route configuration defined in Xml
+     */
+    private Response parseXml(String xml) {
+        try {
+            JAXBContext context = JAXBContext.newInstance(Constants.JAXB_PACKAGES);
+            Unmarshaller unmarshaller = context.createUnmarshaller();
+            Object value = unmarshaller.unmarshal(new StringReader(xml));
+            if (value instanceof RouteDefinition) {
+                RouteDefinition routeDefinition = (RouteDefinition)value;
+                postRoute(routeDefinition);
+                return Response.seeOther(new URI("/routes")).build();
+            } else {
+                error = "Posted XML is not a route but is of type " + ObjectHelper.className(value);
+            }
+        } catch (JAXBException e) {
+            error = "Failed to parse XML: " + e.getMessage();
+        } catch (Exception e) {
+            error = "Failed to install route: " + e.getMessage();
+        }
+        // lets re-render the form
+        return Response.ok(new Viewable("edit", this)).build();
+    }
+
+    /**
+     * process the route configuration defined in Groovy class
+     */
+    private Response parseGroovy(String route) {
+        try {
+            // store the route definition
+            File file = storeRoute(route, LANGUAGE_GROOVY);
+
+            // load the definition class into a RouteBuilder instance
+            GroovyClassLoader classLoader = new GroovyClassLoader();
+            Class clazz = classLoader.parseClass(file);
+            RouteBuilder builder = (RouteBuilder)clazz.newInstance();
+            LOG.info("Loaded builder: " + builder);
+
+            postRoutes(builder);
+
+            return Response.seeOther(new URI("/routes")).build();
+
+        } catch (IOException e) {
+            // e.printStackTrace();
+            error = "Failed to store the route: " + e.getMessage();
+        } catch (InstantiationException e) {
+            // e.printStackTrace();
+            error = "Failed to instantiate the route: " + e.getMessage();
+
+        } catch (IllegalAccessException e) {
+            // e.printStackTrace();
+            error = "Failed to instantiate the route: " + e.getMessage();
+        } catch (Exception e) {
+            // e.printStackTrace();
+            error = "Failed to edit the route: " + e.getMessage();
+        }
+        // lets re-render the form
+        return Response.ok(new Viewable("edit", this)).build();
+    }
+
+    /**
+     * process the route configuration defined in Ruby class
+     */
+    private Response parseRuby(String route) {
+        try {
+            // add the script of addRouteBuilder into ruby script
+            route += "\n RubyCamel.addRouteBuilder(RubyRoute.new)";
+
+            // store the route definition
+            File file = storeRoute(route, LANGUAGE_RUBY);
+
+            // execute the ruby script, which will store the RouteBuilder
+            // instances into RubyCamel
+            String[] args = {file.getAbsolutePath()};
+            Main.main(args);
+
+            // get the route builders from the RubyCamel and add them into this
+            // route
+            List<RouteBuilder> list = RubyCamel.getRoutes();
+            for (RouteBuilder builder : list) {
+                postRoutes(builder);
             }
+
+            return Response.seeOther(new URI("/routes")).build();
+
+        } catch (IOException e) {
+            // e.printStackTrace();
+            error = "Failed to store the route: " + e.getMessage();
+        } catch (Exception e) {
+            // e.printStackTrace();
+            error = "Failed to edit the route: " + e.getMessage();
+
         }
         // lets re-render the form
         return Response.ok(new Viewable("edit", this)).build();
     }
 
     /**
+     * process the route configuration defined in Scala class
+     */
+    private Response parseScala(String route) {
+        try {
+
+            // store the route definition
+            File file = storeRoute(route, LANGUAGE_SCALA);
+
+            // load the definition class
+
+            return Response.seeOther(new URI("/routes")).build();
+
+        } catch (IOException e) {
+            // e.printStackTrace();
+            error = "Failed to store the route: " + e.getMessage();
+        } catch (Exception e) {
+            // e.printStackTrace();
+            error = "Failed to edit the route: " + e.getMessage();
+        }
+        // lets re-render the form
+        return Response.ok(new Viewable("edit", this)).build();
+    }
+
+    /**
+     * Stores the route definition class into a file
+     */
+    private File storeRoute(String route, String language) throws IOException {
+        // create a temporary file to store the route definition class
+        File file = File.createTempFile("Route-", "." + language);
+        FileWriter fw = new FileWriter(file);
+
+        // write the route into the file
+        fw.write(route);
+        fw.flush();
+        fw.close();
+        return file;
+    }
+
+    /**
      * Looks up an individual route
      */
     @Path("status")

Modified: camel/trunk/components/camel-web/src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp?rev=783847&r1=783846&r2=783847&view=diff
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp (original)
+++ camel/trunk/components/camel-web/src/main/webapp/org/apache/camel/web/resources/RouteResource/edit.jsp Thu Jun 11 16:57:34 2009
@@ -1,28 +1,33 @@
 <html>
 <head>
-  <script type='text/javascript' src="<c:url value='/js/dojo/dojo.js'/>"></script>
-  <script type='text/javascript' src="<c:url value='/js/bespin/editor/embed.js'/>"></script>
-  <script type='text/javascript' src="<c:url value='/js/route.js'/>"></script>
+<script type='text/javascript' src="<c:url value='/js/dojo/dojo.js'/>"></script>
+<script type='text/javascript'
+	src="<c:url value='/js/bespin/editor/embed.js'/>"></script>
+<script type='text/javascript' src="<c:url value='/js/route.js'/>"></script>
 
-  <title>Edit ${it.route.id}</title>
+<title>Edit ${it.route.id}</title>
 </head>
 <body>
 
-<form id="routeForm" action="<c:url value="/routes/${it.route.id}"/>" method="post">
+<form id="routeForm" action="<c:url value="/routes/${it.route.id}"/>"
+	method="post">
 <table>
-  <tr>
-    <td>
-      <h2>Edit ${it.route.id}</h2>
-    </td>
-    <td>
-      <input type="submit" value="Save">
-    </td>
-  </tr>
-  <tr>
-    <td colspan="2">
-      <textarea id="route" name="route" style="width: 800px; height: 300px; border: 10px solid #ddd; -moz-border-radius: 10px; -webkit-border-radius: 10px;">${it.routeXml}</textarea>
-    </td>
-  </tr> 
+	<tr>
+		<td>
+		<h2>Edit ${it.route.id}</h2>
+		</td>
+		<td><input type="submit" value="Save">&nbsp; as &nbsp;<select id="language" name="language">
+			<option value="Xml" selected>XML</option>
+			<option value="Groovy">Groovy</option>
+			<option value="Ruby">Ruby</option>
+			<option value="Scala">Scala</option>
+		</select></td>
+	</tr>
+	<tr>
+		<td colspan="2"><textarea id="route" name="route"
+			style="width: 800px; height: 300px; border: 10px solid #ddd; -moz-border-radius: 10px; -webkit-border-radius: 10px;">${it.routeDefinition}</textarea>
+		</td>
+	</tr>
 </table>
 
 <div class="error">${it.error}</div>