[CVS spice] Initial version of GroovyJettyContainerBuilder and JUnit test
sjoberg-yCVjj/[email protected] 19 Oct 2005 15:08:05 -0000
| Newsgroups | gmane.comp.java.spice.cvs |
|---|---|
| Message-ID | <[email protected]> |
<html>
<head>
<style><!--
body {background-color:#ffffff;}
.file {border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;}
.pathname {font-family:monospace; float:right;}
.fileheader {margin-bottom:.5em;}
.diff {margin:0;}
.tasklist {padding:4px;border:1px dashed #000000;margin-top:1em;}
.tasklist ul {margin-top:0;margin-bottom:0;}
tr.alt {background-color:#eeeeee}
#added {background-color:#ddffdd;}
#addedchars {background-color:#99ff99;font-weight:bolder;}
tr.alt #added {background-color:#ccf7cc;}
#removed {background-color:#ffdddd;}
#removedchars {background-color:#ff9999;font-weight:bolder;}
tr.alt #removed {background-color:#f7cccc;}
#info {color:#888888;}
#context {background-color:#eeeeee;}
td {padding-left:.3em;padding-right:.3em;}
tr.head {border-bottom-width:1px;border-bottom-style:solid;}
tr.head td {padding:0;padding-top:.2em;}
.task {background-color:#ffff00;}
.comment {padding:4px;border:1px dashed #000000;background-color:#ffffdd}
.error {color:red;}
hr {border-width:0px;height:2px;background:black;}
--></style>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head"><td colspan="4">Commit in <b><tt>spice/components/jervlet</tt></b><span id="info"> on MAIN</span></td></tr>
<tr><td><tt>src/java/org/codehaus/spice/jervlet/containers/jetty/pico/<a href="#file1"><span id="added">GroovyJettyContainerBuilder.java</span></a></tt></td><td align="right" id="added">+385</td><td></td><td nowrap="nowrap" align="right">added 1.1</td></tr>
<tr class="alt"><td><tt>src/java/org/codehaus/spice/jervlet/containers/jetty/JettyFilterHolder.java</tt></td><td colspan="2" align="center"><small id="info">[empty]</small></td><td nowrap="nowrap" align="center">1.1 -> 1.2</td></tr>
<tr><td><tt> /JettyServletHolder.java</tt></td><td colspan="2" align="center"><small id="info">[empty]</small></td><td nowrap="nowrap" align="center">1.1 -> 1.2</td></tr>
<tr class="alt"><td><tt> /ShieldingJettyContainer.java</tt></td><td colspan="2" align="center"><small id="info">[empty]</small></td><td nowrap="nowrap" align="center">1.1 -> 1.2</td></tr>
<tr><td><tt>src/test/org/codehaus/spice/jervlet/containers/jetty/pico/<a href="#file5"><span id="added">GroovyJettyContainerBuilderTestCase.java</span></a></tt></td><td align="right" id="added">+125</td><td></td><td nowrap="nowrap" align="right">added 1.1</td></tr>
<tr class="alt"><td><tt>project.xml</tt></td><td colspan="2" align="center"><small id="info">[empty]</small></td><td nowrap="nowrap" align="center">1.5 -> 1.6</td></tr>
<tr><td></td><td align="right" id="added">+510</td><td></td><td></td></tr>
</table>
<small id="info">2 added + 4 modified, total 6 files</small><br />
<div class="tasklist"><ul>
<li><a href="#task1">TODO: Sould PicoJettyContainer also implement ContextHandler for a default and open ContextHandler?</a></li>
</ul></div>
<pre class="comment">
Initial version of GroovyJettyContainerBuilder and JUnit test
</pre>
<hr /><a name="file1" /><div class="file">
<span class="pathname" id="added">spice/components/jervlet/src/java/org/codehaus/spice/jervlet/containers/jetty/pico<br /></span>
<div class="fileheader" id="added"><big><b>GroovyJettyContainerBuilder.java</b></big> <small id="info">added at 1.1</small></div>
<pre class="diff"><small id="info">diff -N GroovyJettyContainerBuilder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ GroovyJettyContainerBuilder.java 19 Oct 2005 15:08:04 -0000 1.1
@@ -0,0 +1,385 @@
</small></pre><pre class="diff" id="added">+/*
+ * Copyright (C) The Spice Group. All rights reserved.
+ *
+ * This software is published under the terms of the Spice
+ * Software License version 1.1, a copy of which has been included
+ * with this distribution in the LICENSE.txt file.
+ */
+package org.codehaus.spice.jervlet.containers.jetty.pico;
+
+import groovy.util.BuilderSupport;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.io.File;
+
+import org.codehaus.spice.jervlet.ContextMonitor;
+import org.codehaus.spice.jervlet.ListenerMonitor;
+import org.codehaus.spice.jervlet.Listener;
+import org.codehaus.spice.jervlet.ListenerException;
+import org.codehaus.spice.jervlet.Context;
+import org.codehaus.spice.jervlet.Instantiator;
+import org.codehaus.spice.jervlet.ContextException;
+import org.codehaus.spice.jervlet.impl.DefaultListener;
+import org.codehaus.spice.jervlet.impl.DefaultContext;
+
+/**
+ * Groovy container builder using
+ * <code>PicoJettyContainer</code> under the hood.
+ *
+ * @author Johan Sjoberg
+ * @author Paul Hammant
+ */
+public class GroovyJettyContainerBuilder extends BuilderSupport
+{
+ public GroovyJettyContainerBuilder()
+ {
+ }
+
+ /**
+ * Set a child object on its parent
+ * <br/><br/>
+ * Possible parent - child combinations are:
+ * <ul>
+ * <li>PicoJettyContainer - JettyContainerConfiguration</li>
+ * <li>DefaultJettyContainerConfiguration - Properties</li>
+ * <li>PicoJettyContainer - Listener</li>
+ * <li>PicoJettyContainer - Context</li>
+ * </ul>
+ * If a <code>Context</code> is added as a child to a
+ * <code>PicoJettyContainer</code> a new <code>ContextHandler</code>
+ * is created and used for the new context. There is no way of
+ * getting a reference to this context handler again. If access to
+ * the context or context handler is needed, create a new context
+ * handler using a <code>PicoJettyContainer</code> and deploy contexts
+ * directly to it.
+ *
<a name="task1" />+ * <span class="task">TODO</span>: Sould PicoJettyContainer also implement ContextHandler for a default and open ContextHandler?
+ *
+ * @param object the parent
+ * @param object1 the child
+ */
+ protected void setParent( Object object, Object object1 )
+ {
+ if( object instanceof PicoJettyContainer
+ && object1 instanceof JettyContainerConfiguration )
+ {
+ PicoJettyContainer container = (PicoJettyContainer)object;
+ DefaultJettyContainerConfiguration configuration =
+ (DefaultJettyContainerConfiguration)object1;
+ container.setConfiguration( configuration );
+ }
+ else if( object instanceof DefaultJettyContainerConfiguration
+ && object1 instanceof Properties )
+ {
+ Properties property = (Properties)object1;
+ DefaultJettyContainerConfiguration configuration =
+ (DefaultJettyContainerConfiguration)object;
+ if( null == configuration.getProperties() )
+ {
+ configuration.setProperties( property );
+ }
+ else
+ {
+ configuration.getProperties().putAll( property );
+ }
+ }
+ else if( object instanceof PicoJettyContainer
+ && object1 instanceof Listener )
+ {
+ try
+ {
+ PicoJettyContainer container = (PicoJettyContainer)object;
+ container.initialize();
+ container.addListener( (Listener)object1 );
+ }
+ catch( ListenerException le )
+ {
+ throw new RuntimeException( "The given listener couldn't be added.", le );
+ }
+ }
+ else if( object instanceof PicoJettyContainer
+ && object1 instanceof Context )
+ {
+ try
+ {
+ PicoJettyContainer container = (PicoJettyContainer)object;
+ container.initialize();
+ container.createContextHandler().addContext( (Context)object1 );
+ }
+ catch( ContextException ce )
+ {
+ throw new RuntimeException( "The given context couldn't be added.", ce );
+ }
+ }
+ }
+
+ /**
+ * Create a new instance of something.
+ *
+ * @param name the command
+ * @return a new instance of some type or null
+ */
+ protected Object createNode( Object name )
+ {
+ return createNode( name, Collections.EMPTY_MAP );
+ }
+
+ /**
+ * Not used
+ *
+ * @param name
+ * @param value
+ * @return null
+ */
+ protected Object createNode( Object name, Object value )
+ {
+ return null;
+ }
+
+ /**
+ * Create a new instance of something.
+ * <br/><br/>
+ * Possible commands are:
+ * <ul>
+ * <li>picoJettyContainer</li>
+ * <li>configuration</li>
+ * <li>parameter</li>
+ * <li>listener</li>
+ * <li>context</li>
+ * </ul>
+ *
+ * @param object the command
+ * @param map parameters
+ * @return a new instance of some type or null
+ */
+ protected Object createNode( Object object, Map map )
+ {
+ if( object instanceof String )
+ {
+ final String command = (String)object;
+ if( "picoJettyContainer".equals( command ) )
+ {
+ return getPicoJettyContainer( map );
+ }
+ else if( "configuration".equals( command ) )
+ {
+ return getConfiguration( map );
+ }
+ else if( "parameter".equals( command ) )
+ {
+ return getParameter( map );
+ }
+ else if( "listener".equals( command ) )
+ {
+ return getListener( map );
+ }
+ else if( "context".equals( command ) )
+ {
+ return getContext( map );
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Not used
+ *
+ * @param name
+ * @param attributes
+ * @param object1
+ * @return null
+ */
+ protected Object createNode( Object name, Map attributes, Object object1 )
+ {
+ return null;
+ }
+
+ /**
+ * Create a PicoJettyContainer
+ * <br/><br/>
+ * Possible parameters are:
+ * <ul>
+ * <li>contextMonitor</li>
+ * <li>listenerMonitor</li>
+ * </ul>
+ * @param map a map of parameters. Used keys are
+ * <code>contextMonitor</code> and <code>listenerMonitor</code>.
+ * @return a new PicoJettyContainer, initialized with the
+ * optional monitors.
+ */
+ private PicoJettyContainer getPicoJettyContainer( Map map )
+ {
+ ContextMonitor contextMonitor = (ContextMonitor)map.get( "contextMonitor" );
+ ListenerMonitor listenerMonitor = (ListenerMonitor)map.get( "listenerMonitor" );
+ return new PicoJettyContainer( contextMonitor, listenerMonitor );
+ }
+
+ /**
+ * Create a JettyContainerConfiguration
+ *
+ * @param map a map of parameters. Used keys are
+ * <code>configuration</code> and <code>configurationURL</code>.
+ * @return a new instance of a <code>DefaultJettyContainerConfiguration</code>.
+ * @throws IllegalArgumentException if
+ */
+ private JettyContainerConfiguration getConfiguration( Map map )
+ {
+ if( map.containsKey( "configuration" ) &&
+ map.containsKey( "configurationURL" ) )
+ {
+ throw new IllegalArgumentException( "Either 'configuration' or "
+ + "'configurationURL' can be given. Not both." );
+ }
+ DefaultJettyContainerConfiguration configuration = new DefaultJettyContainerConfiguration();
+ if( map.containsKey( "configuration" ) )
+ {
+ configuration.setConfiguration( map.get( "configuration" ) );
+ }
+ else if( map.containsKey( "configurationURL" ) )
+ {
+ try
+ {
+ URL url = new URL( (String)map.get( "configurationURL" ) );
+ configuration.setConfiguration( url );
+ }
+ catch( MalformedURLException mue )
+ {
+ throw new IllegalArgumentException( "The given URL [" +
+ map.get( "configurationURL" ) + "] was not well formed. " +
+ "Error message was [" + mue.getMessage() + "]." );
+ }
+ }
+ return configuration;
+ }
+
+ /**
+ * Fetch a Jetty configuration parameter from a given map
+ *
+ * @param map a map including the keys <code>key</code>
+ * and <code>value</code>.
+ * @return a new Properties instance with one key value pair
+ * @throws IllegalArgumentException if 'key' or 'value' was missing
+ * in the given map
+ */
+ private Properties getParameter( Map map )
+ {
+ if( !map.containsKey( "key" ) || !map.containsKey( "value" ) )
+ {
+ throw new IllegalArgumentException( "Missing argument. "
+ + "Both 'key' and 'value' are needed." );
+ }
+ Properties properties = new Properties();
+ properties.setProperty( (String)map.get( "key" ), (String)map.get( "value" ) );
+ return properties;
+ }
+
+ /**
+ * Create a listener
+ *
+ * @param map with at least the parameters <code>port</code>
+ * and <code>type</code>. <code>host</code> is also
+ * supported.
+ * @return a new <code>DefaultListener</code> instance
+ */
+ private Listener getListener( Map map )
+ {
+ //System.out.println( "getListener [" + map + "]" );
+ if( !map.containsKey( "port" ) || !map.containsKey( "type" ) )
+ {
+ throw new IllegalArgumentException( "Missing argument. "
+ + "At least 'port' and 'type' must be given." );
+ }
+ int type = -1;
+ final String typeString = (String)map.get( "type" );
+ if( typeString.equalsIgnoreCase( "http" ) )
+ {
+ type = Listener.HTTP;
+ }
+ else if( typeString.equalsIgnoreCase( "tsl") || typeString.equalsIgnoreCase( "ssl" ) )
+ {
+ type = Listener.TSL;
+ }
+ else if( typeString.equalsIgnoreCase( "ajp13" ) )
+ {
+ type = Listener.AJP13;
+ }
+ if( -1 == type )
+ {
+ throw new IllegalArgumentException( "Unknown listener type [" +
+ typeString + "]." );
+ }
+ return new DefaultListener( (String)map.get( "host" ),
+ Integer.parseInt( (String)map.get( "port" ) ),
+ type );
+ }
+
+ /**
+ * Create a context
+ *
+ * @param map map of needed arguments
+ * @return a new context
+ * @throws IllegalArgumentException if a mandatory
+ * parameter was missing in the given map
+ * or if the parameters had errors
+ */
+ private Context getContext( Map map )
+ {
+ if( !map.containsKey( "webPath" ) ||
+ !map.containsKey( "warPath" ) ||
+ !map.containsKey( "instantiator" ) )
+ {
+ throw new IllegalArgumentException( "Missing argument. At least" +
+ " 'instantiator', 'webPath' and 'warPath' must be given." );
+ }
+ String webPath = (String)map.get( "webPath" );
+ String[] hosts = getHosts( (String)map.get( "hosts" ) );
+ URL resource;
+ boolean extractWar = false;
+ Instantiator instantiator = (Instantiator)map.get( "instantiator" );
+ try
+ {
+ File resourceFile = new File( (String)map.get( "warPath" ) );
+ if( !resourceFile.exists() )
+ {
+ throw new IllegalArgumentException( "File [" +
+ map.get( "warParh" ) + "] given in parameter 'warPath' doesn't exist." );
+ }
+ resource = resourceFile.toURL();
+ }
+ catch( MalformedURLException mue )
+ {
+ throw new IllegalArgumentException( "Couldn't translate parameter "
+ + "'warPath' into a URL. Message was [" + mue.getMessage() + "]." );
+ }
+ return new DefaultContext( webPath,
+ hosts,
+ resource,
+ extractWar,
+ instantiator );
+ }
+
+ /**
+ * Create an array from the ',' separated host list.
+ *
+ * @param hostString the string to split up
+ * @return a new string array or null
+ */
+ private String[] getHosts( final String hostString )
+ {
+ if( null == hostString || "".equals( hostString ) )
+ {
+ return null;
+ }
+ String[] hosts = hostString.split( "," );
+ for( int i = 0; i < hosts.length; i++ )
+ {
+ hosts[i] = hosts[i].trim();
+ System.out.println( hosts[i] );
+ }
+ return hosts;
+ }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file5" /><div class="file">
<span class="pathname" id="added">spice/components/jervlet/src/test/org/codehaus/spice/jervlet/containers/jetty/pico<br /></span>
<div class="fileheader" id="added"><big><b>GroovyJettyContainerBuilderTestCase.java</b></big> <small id="info">added at 1.1</small></div>
<pre class="diff"><small id="info">diff -N GroovyJettyContainerBuilderTestCase.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ GroovyJettyContainerBuilderTestCase.java 19 Oct 2005 15:08:04 -0000 1.1
@@ -0,0 +1,125 @@
</small></pre><pre class="diff" id="added">+/*
+ * Copyright (C) The Spice Group. All rights reserved.
+ *
+ * This software is published under the terms of the Spice
+ * Software License version 1.1, a copy of which has been included
+ * with this distribution in the LICENSE.txt file.
+ */
+package org.codehaus.spice.jervlet.containers.jetty.pico;
+
+import junit.framework.TestCase;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyCodeSource;
+import groovy.lang.Script;
+import groovy.lang.Binding;
+
+/**
+ * Test cases for <code>GroovyJettyContainerBuilder</code>
+ *
+ * @author Johan Sjoberg
+ * @author Paul Hammant
+ */
+public class GroovyJettyContainerBuilderTestCase extends TestCase
+{
+ private static final String m_jettyConfiguration =
+ "../../testdata/jetty/jetty.xml";
+ private static final String m_plainWebapp =
+ "../../testdata/webapps/plain";
+ private static final String m_plainWebappWAR =
+ "../../testdata/webapps/plain.war";
+ private static final String m_picoWebapp =
+ "../../testdata/webapps/pico";
+
+ /**
+ * Test various parts of <code>GroovyJettyContainerBuilder</code>
+ *
+ * @throws CompilationFailedException if the groovy script couldn't be compiled
+ */
+ public void testContainerBuilder() throws CompilationFailedException
+ {
+ final Reader script = new StringReader(
+ "package org.codehaus.spice.jervlet.containers.jetty.pico\n" +
+ "import org.picocontainer.defaults.DefaultPicoContainer\n" +
+ "import org.codehaus.spice.jervlet.containers.jetty.pico.GroovyJettyContainerBuilder\n" +
+ "import org.codehaus.spice.jervlet.containers.jetty.pico.PicoJettyContainer\n" +
+ "import org.codehaus.spice.jervlet.impl.pico.PicoInstantiator\n" +
+ "import org.codehaus.spice.jervlet.impl.Pinger\n" +
+ "import org.codehaus.spice.jervlet.impl.DefaultContext\n" +
+ "import org.codehaus.spice.jervlet.impl.SystemOutContextMonitor\n" +
+ "import org.codehaus.spice.jervlet.impl.NoopListenerMonitor\n" +
+
+ "def pico = new DefaultPicoContainer()\n" +
+ "def pinger = new Pinger()\n" +
+ "pinger.ping( '' + System.currentTimeMillis() )\n" +
+ "pico.registerComponentInstance( pinger )\n" +
+ "def builder = new GroovyJettyContainerBuilder()\n" +
+ "def instantiator = new PicoInstantiator( pico )\n" +
+ "def contextMonitor = new SystemOutContextMonitor()\n" +
+ "def listenerMonitor = new NoopListenerMonitor()\n" +
+
+ "def webServer = builder.picoJettyContainer( contextMonitor:contextMonitor, listenerMonitor:listenerMonitor )\n" +
+ "{\n" +
+ "configuration( configuration:'" + m_jettyConfiguration + "' )\n" +
+ "{\n" +
+ "parameter( key:'jetty.port', value:'16842' )\n" +
+ "}\n" +
+ "listener( port:'16843', type:'http' )\n" +
+ "listener( port:'16844', type:'ajp13' )\n" +
+ "context( webPath:'pico1', warPath:'" + m_picoWebapp + "', extractWar:false, instantiator:instantiator, hosts:'localhost' )\n" +
+ "}\n" +
+
+ "def contextHandler = webServer.createContextHandler()\n" +
+ "def context2 = builder.context( webPath:'pico2',\n" +
+ "warPath:'" + m_picoWebapp + "',\n" +
+ "extractWar:false,\n" +
+ "instantiator:instantiator,\n" +
+ "hosts:'localhost, 127.0.0.1' )\n" +
+ "contextHandler.addContext( context2 )\n" +
+
+ "webServer.start()\n" +
+
+ "def context3 = builder.context( webPath:'pico3', warPath:'" + m_picoWebapp + "', extractWar:false, instantiator:instantiator )\n" +
+ "contextHandler.addContext( context3 )\n" +
+ "contextHandler.startContext( context3 )\n" +
+ "contextHandler.stopContext( context3 )\n" +
+ "contextHandler.removeContext( context3 )\n" +
+
+ "webServer.stop()" );
+
+ doGroovy( new InputStream()
+ {
+ public int read() throws IOException
+ {
+ return script.read();
+ }
+ } );
+ assertEquals( "", "" );
+ }
+
+ /**
+ * Run a groovy script
+ *
+ * @param is the input stream holding the script
+ * @throws CompilationFailedException if the script couldn't be compiled
+ */
+ protected void doGroovy( InputStream is ) throws CompilationFailedException
+ {
+ GroovyClassLoader loader = new GroovyClassLoader( getClass().getClassLoader() );
+ GroovyCodeSource groovyCodeSource = new GroovyCodeSource(
+ is,"nanocontainer.groovy", "groovyGeneratedForNanoContainer" );
+ Class scriptClass = loader.parseClass( groovyCodeSource );
+ Script groovyScript = InvokerHelper.createScript( scriptClass, null );
+ Binding binding = new Binding();
+ groovyScript.setBinding( binding );
+ groovyScript.run();
+ }
+}
</pre></div>
<center><small><a href="http://www.badgers-in-foil.co.uk/projects/cvsspam/" title="commit -> email">CVSspam</a> 0.2.8</small></center>
</body></html>