343482 refactored overlay deployer layout to use WAR layout - work in progress

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3032 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2011-04-27 00:51:08 +00:00
parent 856e4d7491
commit 57c2cc31fa
50 changed files with 270 additions and 109 deletions

View File

@ -4,6 +4,7 @@ jetty-7.4.1-SNAPSHOT
+ 343352 make sure that jetty.osgi.boot is activated when a WAB is registered
+ 343567 HttpClient does not limit the destination's exchange queue
+ 343707 'REQUEST' is printed on console for each incoming HTTP request
+ 343482 refactored overlay deployer layout to use WAR layout
jetty-7.4.0.v20110414
+ 342504 Scanner Listener

View File

@ -278,6 +278,16 @@
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
@ -490,6 +500,15 @@
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
@ -607,6 +626,11 @@
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>

View File

@ -1 +0,0 @@
This directory is for temporary cloudtide files

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.overlays;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
@ -145,6 +146,13 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
public final static String TEMPLATES="templates";
public final static String NODES="nodes";
public final static String INSTANCES="instances";
public final static String LIB="WEB-INF/lib-overlay";
public final static String WEBAPP=".";
public final static String OVERLAY_XML="WEB-INF/overlay.xml";
public final static String TEMPLATE_XML="WEB-INF/template.xml";
public final static String WEB_DEFAULT_XML="WEB-INF/web-default.xml";
public final static String WEB_FRAGMENT_XML="WEB-INF/web-overlay.xml";
enum Monitor { WEBAPPS,TEMPLATES,NODES,INSTANCES} ;
@ -153,31 +161,13 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
static
{
List<String> regexes = new ArrayList<String>();
regexes.add(WEBAPPS+"/[^/]*/");
regexes.add(TEMPLATES+"/[^/]*/");
regexes.add(NODES+"/[^/]*/");
regexes.add(INSTANCES+"/[^/]*/");
regexes.add(WEBAPPS+"/[^/]*");
regexes.add(TEMPLATES+"/[^/]*");
regexes.add(NODES+"/[^/]*");
regexes.add(INSTANCES+"/[^/]*");
regexes.add(TEMPLATES+"/[^/]*/[^/]+");
regexes.add(NODES+"/[^/]*/[^/]+");
regexes.add(INSTANCES+"/[^/]*/[^/]+");
regexes.add(TEMPLATES+"/[^/]*/lib/[^/]+");
regexes.add(NODES+"/[^/]*/lib/[^/]+");
regexes.add(INSTANCES+"/[^/]*/lib/[^/]+");
for (String s:new String[] {"/WEB-INF/lib/[^/]*","/WEB-INF/classes/[^/]*","/WEB-INF/[^/]*\\.xml",})
for (String s:new String[] {".war",".jar","/WEB-INF/syslib/[^/]*","/WEB-INF/lib/[^/]*","/WEB-INF/classes/[^/]*","/WEB-INF/[^/]*\\.xml",})
{
regexes.add(WEBAPPS+"/[^/]*"+s);
regexes.add(TEMPLATES+"/[^/]*/webapp"+s);
regexes.add(NODES+"/[^/]*/webapp"+s);
regexes.add(INSTANCES+"/[^/]*/webapp"+s);
regexes.add(TEMPLATES+"/[^/]*"+s);
regexes.add(NODES+"/[^/]*"+s);
regexes.add(INSTANCES+"/[^/]*"+s);
}
for (String s: regexes)
@ -212,6 +202,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
Set<String> changes = new HashSet<String>();
for (String filename:filenames)
{
File file=new File(filename);
if (file.getName().startsWith(".") || file.getName().endsWith(".swp"))
continue;
@ -232,7 +223,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
String uri=dir+"/"+name;
for (Pattern p : __scanPatterns)
{
if (p.matcher(relname).matches())
@ -244,7 +235,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
__log.debug("{} != {}",relname,p.pattern());
}
}
if (changes.size()>0)
OverlayedAppProvider.this.updateLayers(changes);
}
@ -344,7 +335,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
// Build the instance lib loader
ClassLoader shared_loader = shared.getWebappLoader()!=null?shared.getWebappLoader():(shared.getLibLoader()!=null?shared.getLibLoader():orig_loader);
ClassLoader loader = shared_loader;
Resource instance_lib = instance.getResource("lib");
Resource instance_lib = instance.getResource(LIB);
if (instance_lib.exists())
{
List<URL> libs = new ArrayList<URL>();
@ -370,7 +361,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
// Create the instance context for the template
ContextHandler context=null;
Resource template_context_xml = template.getResource("context.xml");
Resource template_context_xml = template.getResource(OVERLAY_XML);
if (template_context_xml.exists())
{
__log.debug("{}: context.xml={}",origin,template_context_xml);
@ -386,7 +377,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
context=new WebAppContext();
// Set the resource base
final Resource instance_webapp = instance.getResource("webapp");
final Resource instance_webapp = instance.getResource(WEBAPP);
if (instance_webapp.exists())
{
context.setBaseResource(new ResourceCollection(instance_webapp,shared.getBaseResource()));
@ -406,7 +397,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
context.setAttribute("org.eclipse.jetty.server.session.timer", _sessionScavenger);
// Apply any node or instance context.xml
for (Resource context_xml : getLayeredResources("context.xml",node,instance))
for (Resource context_xml : getLayeredResources(OVERLAY_XML,node,instance))
{
__log.debug("{}: context.xml={}",origin,context_xml);
XmlConfiguration xmlc = newXmlConfiguration(context_xml.getURL(),idMap,template,instance);
@ -479,7 +470,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
loader = new URLClassLoader(new URL[]{},shared_loader);
// add default descriptor
List<Resource> webdefaults=getLayeredResources("webdefault.xml",instance,node,template);
List<Resource> webdefaults=getLayeredResources(WEB_DEFAULT_XML,instance,node,template);
if (webdefaults.size()>0)
{
Resource webdefault = webdefaults.get(0);
@ -488,7 +479,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
// add overlay descriptors
for (Resource override : getLayeredResources("web.xml",template,node,instance))
for (Resource override : getLayeredResources(WEB_FRAGMENT_XML,template,node,instance))
{
__log.debug("{}: web override={}",origin,override);
webappcontext.addOverrideDescriptor(override.toString());
@ -541,7 +532,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
// If we have libs directories, create classloader and make it available to
// the XMLconfiguration
List<URL> libs = new ArrayList<URL>();
for (Resource lib : getLayeredResources("lib",node,template))
for (Resource lib : getLayeredResources(LIB,node,template))
{
for (String jar :lib.list())
{
@ -591,7 +582,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
// shared results of running the template and node context.xml files.
// If there is a template context.xml, give it the chance to create the ContextHandler instance
// otherwise create an instance ourselves
for (Resource template_xml : getLayeredResources("template.xml",template,node))
for (Resource template_xml : getLayeredResources(TEMPLATE_XML,template,node))
{
__log.debug("{}: template.xml={}",key,template_xml);
XmlConfiguration xmlc = newXmlConfiguration(template_xml.getURL(),idMap,template,null);
@ -882,6 +873,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
}
/* ------------------------------------------------------------ */
protected File tmpdir(String name,String suffix) throws IOException
{
File dir=_tmpDir;
@ -900,7 +892,8 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
tmp.deleteOnExit();
return tmp;
}
/* ------------------------------------------------------------ */
/**
* Walks the defined webapps, templates, nodes and instances to
* determine what should be deployed, then adjust reality to match.
@ -1026,11 +1019,13 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
/* ------------------------------------------------------------ */
protected void removeInstance(String name)
{
_removedLayers.add(_instances.remove(name));
}
/* ------------------------------------------------------------ */
protected Instance loadInstance(String name, File origin)
throws IOException
{
@ -1039,6 +1034,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
return instance;
}
/* ------------------------------------------------------------ */
protected void removeNode()
{
if (_node!=null)
@ -1046,6 +1042,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
_node=null;
}
/* ------------------------------------------------------------ */
protected Node loadNode(File origin)
throws IOException
{
@ -1054,12 +1051,14 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
_node=new Node(_nodeName,origin);
return _node;
}
/* ------------------------------------------------------------ */
protected void removeTemplate(String name)
{
_removedLayers.add(_templates.remove(name));
}
/* ------------------------------------------------------------ */
protected Template loadTemplate(String name, File origin)
throws IOException
{
@ -1072,7 +1071,8 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
{
_removedLayers.add(_webapps.remove(name));
}
/* ------------------------------------------------------------ */
protected Webapp loadWebapp(String name, File origin)
throws IOException
{
@ -1081,6 +1081,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
return webapp;
}
/* ------------------------------------------------------------ */
private static List<Resource> getLayeredResources(String path, Layer... layers)
{
List<Resource> resources = new ArrayList<Resource>();
@ -1095,6 +1096,9 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
return resources;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
class Layer
{
private final String _name;
@ -1217,10 +1221,13 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
public Resource getContext()
{
return getResource("context.xml");
return getResource(OVERLAY_XML);
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
class Node extends Overlay
{
public Node(String name, File origin) throws IOException
@ -1229,7 +1236,10 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
class ClassifiedOverlay extends Overlay
{
private final String _templateName;
@ -1238,9 +1248,16 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
public ClassifiedOverlay(String name, File origin) throws IOException
{
super(name,origin);
int l=1;
int e=name.indexOf('=');
if (e<0)
{
l=2;
e=name.indexOf("--");
}
_templateName=e>=0?name.substring(0,e):name;
_classifier=e>=0?name.substring(e+1):null;
_classifier=e>=0?name.substring(e+l):null;
}
public String getTemplateName()
@ -1253,7 +1270,10 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
return _classifier;
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
class Template extends ClassifiedOverlay
{
private Webapp _webapp;
@ -1273,7 +1293,10 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
super(name,origin);
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
class Instance extends ClassifiedOverlay
{
Template _template;
@ -1315,7 +1338,10 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
getLoadedKey();
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
static class OverlayedApp extends App
{
final Instance _instance;
@ -1332,4 +1358,5 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
}
}
}

View File

@ -169,7 +169,7 @@ public class OverlayedAppProviderTest
assertTrue(scanned.isEmpty());
// Check scanning for archives
// Check scanning for directories
File war = new File(_webapps,"foo-1.2.3");
war.mkdir();
File template = new File(_templates,"foo=foo-1.2.3");
@ -178,6 +178,12 @@ public class OverlayedAppProviderTest
node.mkdir();
File instance = new File(_instances,"foo=instance");
instance.mkdir();
for (File f : new File[] { war,template,node,instance } )
{
File webinf = new File(f,"WEB-INF");
webinf.mkdir();
touch(webinf,"web.xml");
}
provider.scan();
provider.scan();
@ -204,10 +210,10 @@ public class OverlayedAppProviderTest
for (File d : new File[]{template,node,instance})
{
touch(d,"web.xml");
touch(d,"context.xml");
touch(d,"other");
touch(d,"webapp/WEB-INF/lib/bar.jar");
touch(d,"WEB-INF/web-fragment.xml");
touch(d,"WEB-INF/overlay.xml");
touch(d,"WEB-INF/other");
touch(d,"WEB-INF/lib/bar.jar");
}
provider.scan();
@ -223,9 +229,8 @@ public class OverlayedAppProviderTest
// Touch xml
Thread.sleep(1000); // needed so last modified is different
touch(war,"WEB-INF/web.xml");
for (File d : new File[]{template,node,instance})
touch(d,"context.xml");
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/web.xml");
provider.scan();
provider.scan();
results = scanned.poll();
@ -238,9 +243,8 @@ public class OverlayedAppProviderTest
// Touch XML
Thread.sleep(1000);
touch(war,"WEB-INF/spring.XML");
for (File d : new File[]{template,node,instance})
touch(d,"webapp/WEB-INF/spring.XML");
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/spring.XML");
provider.scan();
provider.scan();
results = scanned.poll();
@ -253,21 +257,17 @@ public class OverlayedAppProviderTest
// Touch unrelated
touch(war,"index.html");
for (File d : new File[]{template,node,instance})
touch(d,"webapp/index.html");
for (File d : new File[]{war,template,node,instance})
touch(d,"index.html");
provider.scan();
provider.scan();
results = scanned.poll();
assertEquals(1,results.size());
assertTrue(results.contains("webapps/foo-1.2.3"));
assertEquals(null,results);
// Touch jar
Thread.sleep(1000);
touch(war,"WEB-INF/lib/bar.jar");
for (File d : new File[]{template,node,instance})
touch(d,"webapp/WEB-INF/lib/bar.jar");
for (File d : new File[]{war,template,node,instance})
touch(d,"WEB-INF/lib/bar.jar");
provider.scan();
provider.scan();
results = scanned.poll();
@ -280,9 +280,7 @@ public class OverlayedAppProviderTest
// touch other class
Thread.sleep(1000);
touch(war,"WEB-INF/other.txt");
touch(war,"index.html");
for (File d : new File[]{template,node,instance})
for (File d : new File[]{war,template,node,instance})
touch(d,"index.html");
provider.scan();
provider.scan();
@ -414,15 +412,20 @@ public class OverlayedAppProviderTest
// Add a war dir
File warDir = new File(_webapps,"foo-1.2.3");
warDir.mkdir();
File warDirWI = new File(warDir,"WEB-INF");
warDirWI.mkdir();
touch(warDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadWebapp foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
assertEquals(warDir.getAbsolutePath(),scanned.poll(1,TimeUnit.SECONDS));
// Add a template dir
File templateDir = new File(_templates,"foo=foo-1.2.3");
templateDir.mkdir();
File templateDirWI = new File(templateDir,"WEB-INF");
templateDirWI.mkdir();
touch(templateDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadTemplate foo=foo-1.2.3",scanned.poll(1,TimeUnit.SECONDS));
@ -431,6 +434,9 @@ public class OverlayedAppProviderTest
// Add a node dir
File nodeADir = new File(_nodes,"nodeA");
nodeADir.mkdir();
File nodeADirWI = new File(nodeADir,"WEB-INF");
nodeADirWI.mkdir();
touch(nodeADirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadNode",scanned.poll(1,TimeUnit.SECONDS));
@ -439,6 +445,9 @@ public class OverlayedAppProviderTest
// Add another node dir
File nodeBDir = new File(_nodes,"nodeB");
nodeBDir.mkdir();
File nodeBDirWI = new File(nodeBDir,"WEB-INF");
nodeBDirWI.mkdir();
touch(nodeADirWI,"web.xml");
provider.scan();
provider.scan();
assertTrue(scanned.isEmpty());
@ -446,6 +455,9 @@ public class OverlayedAppProviderTest
// Add an instance dir
File instanceDir = new File(_instances,"foo=instance");
instanceDir.mkdir();
File instanceDirWI = new File(instanceDir,"WEB-INF");
instanceDirWI.mkdir();
touch(instanceDirWI,"web.xml");
provider.scan();
provider.scan();
assertEquals("loadInstance foo=instance",scanned.poll(1,TimeUnit.SECONDS));
@ -464,11 +476,8 @@ public class OverlayedAppProviderTest
assertTrue(scanned.isEmpty());
// Touch directories
touch(warDir,"WEB-INF/web.xml");
touch(templateDir,"context.xml");
touch(nodeADir,"context.xml");
touch(nodeBDir,"context.xml");
touch(instanceDir,"context.xml");
for (File d : new File[]{warDir,templateDir,nodeADir,nodeBDir,instanceDir})
touch(d,"WEB-INF/web.xml");
provider.scan();
provider.scan();
assertEquals(8,scanned.size());

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=blue WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=green WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

View File

@ -0,0 +1 @@
instance myfoo=red WEB-INF classes

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,10 @@
<h1>Template foo webapp</h1>
<img src=logo.png></img>
Should see index.jsp instead of this!!!
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -0,0 +1,54 @@
<%@page import="java.io.BufferedReader"%>
<%@page import="java.io.InputStreamReader"%>
<%@page import="java.util.Enumeration"%>
<h1><%=application.getServletContextName()%></h1>
<img src=logo.png></img>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>
<p>
<h3>Overlays</h3>
webapp=<%=application.getInitParameter("webapp")%><br/>
template=<%=application.getInitParameter("template")%><br/>
node=<%=application.getInitParameter("node")%><br/>
instance=<%=application.getInitParameter("instance")%><br/>
<h3>Init Parameters</h3>
<%
Enumeration e=application.getInitParameterNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=application.getInitParameter(name);
out.println(name+": "+value+"<br/>");
}
%>
<h3>Attributes</h3>
<%
e=application.getAttributeNames();
while (e.hasMoreElements())
{
String name=e.nextElement().toString();
String value=String.valueOf(application.getAttribute(name));
out.println(name+": "+value+"<br/>");
}
%>
<h3>Resources</h3>
<%
ClassLoader loader = Thread.currentThread().getContextClassLoader();
%>
resourceA.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceA.txt").openStream())).readLine()%><br/>
resourceB.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceB.txt").openStream())).readLine()%><br/>
resourceC.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceC.txt").openStream())).readLine()%><br/>
resourceD.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceD.txt").openStream())).readLine()%><br/>
resourceE.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceE.txt").openStream())).readLine()%><br/>
resourceF.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceF.txt").openStream())).readLine()%><br/>
resourceG.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceG.txt").openStream())).readLine()%><br/>
resourceH.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceH.txt").openStream())).readLine()%><br/>
resourceI.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceI.txt").openStream())).readLine()%><br/>
resourceJ.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceJ.txt").openStream())).readLine()%><br/>
resourceK.txt=<%=new BufferedReader(new InputStreamReader(loader.getResource("resourceK.txt").openStream())).readLine()%><br/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,7 @@
<h1>Cloudtide Deployer Demo</h1>
<p>
<a href="/red">Red</a>,
<a href="/blue">Blue</a>,
<a href="/green">Green</a>

View File

@ -149,6 +149,9 @@ $(jetty.home)/lib/jetty-http-$(version).jar
[All,websocket]
$(jetty.home)/lib/jetty-websocket-$(version).jar ! available org.eclipse.jetty.websocket.WebSocket
[All,overlay]
$(jetty.home)/lib/jetty-overlay-deployer-$(version).jar ! available org.eclipse.jetty.overlay.OverlayedAppProvider
# Add ext if it exists
[Server,All,default,ext]

View File

@ -18,6 +18,7 @@ import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
@ -513,4 +514,37 @@ public class TypeUtil
}
return null;
}
public static Object call(Class<?> oClass, String method, Object obj, Object[] arg)
throws InvocationTargetException, NoSuchMethodException
{
// Lets just try all methods for now
Method[] methods = oClass.getMethods();
for (int c = 0; methods != null && c < methods.length; c++)
{
if (!methods[c].getName().equals(method))
continue;
if (methods[c].getParameterTypes().length != arg.length)
continue;
if (Modifier.isStatic(methods[c].getModifiers()) != (obj == null))
continue;
if ((obj == null) && methods[c].getDeclaringClass() != oClass)
continue;
try
{
return methods[c].invoke(obj,arg);
}
catch (IllegalAccessException e)
{
Log.ignore(e);
}
catch (IllegalArgumentException e)
{
Log.ignore(e);
}
}
throw new NoSuchMethodException(method);
}
}

View File

@ -209,7 +209,7 @@ public class XmlConfiguration
}
catch (Exception e)
{
Log.ignore(e);
Log.warn(e);
}
if (_processor!=null)
break;
@ -684,44 +684,21 @@ public class XmlConfiguration
if (Log.isDebugEnabled())
Log.debug("XML call " + method);
// Lets just try all methods for now
Method[] methods = oClass.getMethods();
for (int c = 0; methods != null && c < methods.length; c++)
try
{
if (!methods[c].getName().equals(method))
continue;
if (methods[c].getParameterTypes().length != size)
continue;
if (Modifier.isStatic(methods[c].getModifiers()) != (obj == null))
continue;
if ((obj == null) && methods[c].getDeclaringClass() != oClass)
continue;
Object n = null;
boolean called = false;
try
{
n = methods[c].invoke(obj,arg);
called = true;
}
catch (IllegalAccessException e)
{
Log.ignore(e);
}
catch (IllegalArgumentException e)
{
Log.ignore(e);
}
if (called)
{
if (id != null)
_idMap.put(id,n);
configure(n,node,argi);
return n;
}
Object n= TypeUtil.call(oClass,method,obj,arg);
if (id != null)
_idMap.put(id,n);
configure(n,node,argi);
return n;
}
catch (NoSuchMethodException e)
{
IllegalStateException ise = new IllegalStateException("No Method: " + node + " on " + oClass);
ise.initCause(e);
throw ise;
}
throw new IllegalStateException("No Method: " + node + " on " + oClass);
}
/* ------------------------------------------------------------ */