320073 Reconcile jetty-8 and jetty-7 webapp configuration mechanisms
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2145 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
8210d068c4
commit
314f94decc
|
@ -17,30 +17,36 @@ import java.net.URI;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.Descriptor;
|
||||
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
|
||||
import org.eclipse.jetty.webapp.FragmentDescriptor;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor.Descriptor;
|
||||
import org.eclipse.jetty.webapp.Descriptor.MetaDataComplete;
|
||||
|
||||
|
||||
public abstract class AbstractConfiguration implements Configuration
|
||||
{
|
||||
public static final String CONTAINER_JAR_RESOURCES = WebInfConfiguration.CONTAINER_JAR_RESOURCES;
|
||||
public static final String WEB_INF_JAR_RESOURCES = WebInfConfiguration.WEB_INF_JAR_RESOURCES;
|
||||
public static final String WEBXML_VERSION = WebXmlProcessor.WEBXML_VERSION;
|
||||
public static final String METADATA_COMPLETE = WebXmlProcessor.METADATA_COMPLETE;
|
||||
public static final String WEBXML_CLASSNAMES = WebXmlProcessor.WEBXML_CLASSNAMES;
|
||||
|
||||
public static final String WEB_INF_ORDERED_JAR_RESOURCES = WebInfConfiguration.WEB_INF_ORDERED_JAR_RESOURCES;
|
||||
public static final String METADATA_COMPLETE = MetaData.METADATA_COMPLETE;
|
||||
public static final String WEBXML_CLASSNAMES = MetaData.WEBXML_CLASSNAMES;
|
||||
public static final String DISCOVERED_ANNOTATIONS = "org.eclipse.jetty.discoveredAnnotations";
|
||||
|
||||
public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
//if no pattern for the container path is defined, then by default scan NOTHING
|
||||
Log.debug("Scanning container jars");
|
||||
|
||||
List<DiscoveredAnnotation> discoveredAnnotations = new ArrayList<DiscoveredAnnotation>();
|
||||
context.setAttribute(DISCOVERED_ANNOTATIONS, discoveredAnnotations);
|
||||
|
||||
|
||||
//Convert from Resource to URI
|
||||
ArrayList<URI> containerUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(CONTAINER_JAR_RESOURCES);
|
||||
|
@ -68,60 +74,71 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
return false;
|
||||
}
|
||||
});
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException ("No metadata");
|
||||
|
||||
metaData.addDiscoveredAnnotations((List<DiscoveredAnnotation>)context.getAttribute(DISCOVERED_ANNOTATIONS));
|
||||
context.removeAttribute(DISCOVERED_ANNOTATIONS);
|
||||
}
|
||||
|
||||
|
||||
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
WebXmlProcessor webXmlProcessor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (webXmlProcessor == null)
|
||||
throw new IllegalStateException ("No processor for web xml");
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException ("No metadata");
|
||||
|
||||
List<Descriptor> frags = webXmlProcessor.getFragments();
|
||||
List<FragmentDescriptor> frags = metaData.getFragments();
|
||||
|
||||
//Get the web-inf lib jars who have a web-fragment.xml that is not metadata-complete (or is not set)
|
||||
//email from Rajiv Mordani jsrs 315 7 April 2010
|
||||
//jars that do not have a web-fragment.xml are still considered fragments
|
||||
//they have to participate in the ordering
|
||||
ArrayList<URI> webInfUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(WEB_INF_JAR_RESOURCES);
|
||||
|
||||
for (Resource r : jarResources)
|
||||
List<Resource> jars = (List<Resource>)context.getAttribute(WEB_INF_ORDERED_JAR_RESOURCES);
|
||||
|
||||
//No ordering just use the jars in any order
|
||||
if (jars == null || jars.isEmpty())
|
||||
jars = (List<Resource>)context.getAttribute(WEB_INF_JAR_RESOURCES);
|
||||
|
||||
List<DiscoveredAnnotation> discoveredAnnotations = new ArrayList<DiscoveredAnnotation>();
|
||||
context.setAttribute(DISCOVERED_ANNOTATIONS, discoveredAnnotations);
|
||||
|
||||
for (Resource r : jars)
|
||||
{
|
||||
discoveredAnnotations.clear(); //start fresh for each jar
|
||||
URI uri = r.getURI();
|
||||
Descriptor d = null;
|
||||
for (Descriptor frag: frags)
|
||||
FragmentDescriptor f = getFragmentFromJar(r, frags);
|
||||
|
||||
//if a jar has no web-fragment.xml we scan it (because it is not exluded by the ordering)
|
||||
//or if it has a fragment we scan it if it is not metadata complete
|
||||
if (f == null || !isMetaDataComplete(f))
|
||||
{
|
||||
Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml
|
||||
if (Resource.isContainedIn(fragResource,r))
|
||||
{
|
||||
d = frag;
|
||||
break;
|
||||
}
|
||||
parser.parse(uri,
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
metaData.addDiscoveredAnnotations(r, discoveredAnnotations);
|
||||
}
|
||||
|
||||
//if there was no web-fragment.xml for the jar, or there was one
|
||||
//and its metadata is NOT complete, we want to exame it for annotations
|
||||
if (d == null || (d != null && !d.isMetaDataComplete()))
|
||||
webInfUris.add(uri);
|
||||
}
|
||||
|
||||
parser.parse(webInfUris.toArray(new URI[webInfUris.size()]),
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
context.removeAttribute(DISCOVERED_ANNOTATIONS);
|
||||
}
|
||||
|
||||
public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
|
||||
|
@ -133,6 +150,13 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
Resource classesDir = context.getWebInf().addPath("classes/");
|
||||
if (classesDir.exists())
|
||||
{
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException ("No metadata");
|
||||
|
||||
List<DiscoveredAnnotation> discoveredAnnotations = new ArrayList<DiscoveredAnnotation>();
|
||||
context.setAttribute(DISCOVERED_ANNOTATIONS, discoveredAnnotations);
|
||||
|
||||
parser.parse(classesDir,
|
||||
new ClassNameResolver()
|
||||
{
|
||||
|
@ -151,37 +175,36 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//TODO - where to set the annotations discovered from WEB-INF/classes?
|
||||
metaData.addDiscoveredAnnotations (discoveredAnnotations);
|
||||
context.removeAttribute(DISCOVERED_ANNOTATIONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parse25Classes (final WebAppContext context, final AnnotationParser parser)
|
||||
|
||||
|
||||
public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
|
||||
throws Exception
|
||||
{
|
||||
//only parse servlets, filters and listeners from web.xml
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning only classes from web.xml");
|
||||
ArrayList<String> classNames = (ArrayList<String>)context.getAttribute(WEBXML_CLASSNAMES);
|
||||
for (String s : classNames)
|
||||
//check if the jar has a web-fragment.xml
|
||||
FragmentDescriptor d = null;
|
||||
for (FragmentDescriptor frag: frags)
|
||||
{
|
||||
Class clazz = Loader.loadClass(null, s);
|
||||
parser.parse(clazz, new ClassNameResolver()
|
||||
Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml
|
||||
if (Resource.isContainedIn(fragResource,jar))
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}, true);
|
||||
d = frag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
public boolean isMetaDataComplete (Descriptor d)
|
||||
{
|
||||
return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,17 +13,18 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
* Configuration for Annotations
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AnnotationConfiguration extends AbstractConfiguration
|
||||
{
|
||||
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
|
||||
|
||||
|
||||
|
||||
public void preConfigure(final WebAppContext context) throws Exception
|
||||
{
|
||||
|
@ -31,53 +32,9 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
Boolean b = (Boolean)context.getAttribute(METADATA_COMPLETE);
|
||||
boolean metadataComplete = (b != null && b.booleanValue());
|
||||
Integer i = (Integer)context.getAttribute(WEBXML_VERSION);
|
||||
int webxmlVersion = (i == null? 0 : i.intValue());
|
||||
|
||||
if (metadataComplete)
|
||||
{
|
||||
//Never scan any jars or classes for annotations if metadata is complete
|
||||
if (Log.isDebugEnabled()) Log.debug("Metadata-complete==true, not processing annotations for context "+context);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Only scan jars and classes if metadata is not complete and the web app is version 3.0, or
|
||||
//a 2.5 version webapp that has specifically asked to discover annotations
|
||||
if (Log.isDebugEnabled()) Log.debug("parsing annotations");
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", new ResourceAnnotationHandler (context));
|
||||
parser.registerAnnotationHandler("javax.annotation.Resources", new ResourcesAnnotationHandler (context));
|
||||
parser.registerAnnotationHandler("javax.annotation.PostConstruct", new PostConstructAnnotationHandler(context));
|
||||
parser.registerAnnotationHandler("javax.annotation.PreDestroy", new PreDestroyAnnotationHandler(context));
|
||||
parser.registerAnnotationHandler("javax.annotation.security.RunAs", new RunAsAnnotationHandler(context));
|
||||
parser.registerAnnotationHandler("javax.annotation.security.DeclareRoles", new DeclareRolesAnnotationHandler(context));
|
||||
|
||||
ClassInheritanceHandler classHandler = new ClassInheritanceHandler();
|
||||
parser.registerClassHandler(classHandler);
|
||||
|
||||
|
||||
if (webxmlVersion >= 30 || context.isConfigurationDiscovered())
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning all classes for annotations: webxmlVersion="+webxmlVersion+" configurationDiscovered="+context.isConfigurationDiscovered());
|
||||
parseContainerPath(context, parser);
|
||||
parseWebInfLib (context, parser);
|
||||
parseWebInfClasses(context, parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning only classes in web.xml for annotations");
|
||||
parse25Classes(context, parser);
|
||||
}
|
||||
|
||||
//save the type inheritance map created by the parser for later reference
|
||||
context.setAttribute(CLASS_INHERITANCE_MAP, classHandler.getMap());
|
||||
}
|
||||
{
|
||||
WebAppDecoratorWrapper wrapper = new WebAppDecoratorWrapper(context, context.getDecorator());
|
||||
context.setDecorator(wrapper);
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +49,5 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
context.setAttribute(CLASS_INHERITANCE_MAP, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/**
|
||||
* AnnotationIntrospector
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AnnotationIntrospector
|
||||
{
|
||||
protected List<IntrospectableAnnotationHandler> _handlers = new ArrayList<IntrospectableAnnotationHandler>();
|
||||
|
||||
|
||||
/**
|
||||
* IntrospectableAnnotationHandler
|
||||
*
|
||||
* Interface for all handlers that wish to introspect a class to find a particular annotation
|
||||
*/
|
||||
public interface IntrospectableAnnotationHandler
|
||||
{
|
||||
public void handle(Class clazz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AbstractIntrospectableAnnotationHandler
|
||||
*
|
||||
* Base class for handlers that introspect a class to find a particular annotation.
|
||||
* A handler can optionally introspect the parent hierarchy of a class.
|
||||
*/
|
||||
public static abstract class AbstractIntrospectableAnnotationHandler implements IntrospectableAnnotationHandler
|
||||
{
|
||||
private boolean _introspectAncestors;
|
||||
|
||||
public abstract void doHandle(Class clazz);
|
||||
|
||||
|
||||
public AbstractIntrospectableAnnotationHandler(boolean introspectAncestors)
|
||||
{
|
||||
_introspectAncestors = introspectAncestors;
|
||||
}
|
||||
|
||||
public void handle(Class clazz)
|
||||
{
|
||||
Class c = clazz;
|
||||
|
||||
//process the whole inheritance hierarchy for the class
|
||||
while (c!=null && (!c.equals(Object.class)))
|
||||
{
|
||||
doHandle(clazz);
|
||||
if (!_introspectAncestors)
|
||||
break;
|
||||
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerHandler (IntrospectableAnnotationHandler handler)
|
||||
{
|
||||
_handlers.add(handler);
|
||||
}
|
||||
|
||||
public void introspect (Class clazz)
|
||||
{
|
||||
if (_handlers == null)
|
||||
return;
|
||||
if (clazz == null)
|
||||
return;
|
||||
|
||||
for (IntrospectableAnnotationHandler handler:_handlers)
|
||||
{
|
||||
try
|
||||
{
|
||||
handler.handle(clazz);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ import org.objectweb.asm.commons.EmptyVisitor;
|
|||
public class AnnotationParser
|
||||
{
|
||||
protected List<String> _parsedClassNames = new ArrayList<String>();
|
||||
protected Map<String, AnnotationHandler> _annotationHandlers = new HashMap<String, AnnotationHandler>();
|
||||
protected Map<String, List<DiscoverableAnnotationHandler>> _annotationHandlers = new HashMap<String, List<DiscoverableAnnotationHandler>>();
|
||||
protected List<ClassHandler> _classHandlers = new ArrayList<ClassHandler>();
|
||||
protected List<MethodHandler> _methodHandlers = new ArrayList<MethodHandler>();
|
||||
protected List<FieldHandler> _fieldHandlers = new ArrayList<FieldHandler>();
|
||||
|
@ -157,7 +157,7 @@ public class AnnotationParser
|
|||
|
||||
|
||||
|
||||
public interface AnnotationHandler
|
||||
public interface DiscoverableAnnotationHandler
|
||||
{
|
||||
public void handleClass (String className, int version, int access,
|
||||
String signature, String superName, String[] interfaces,
|
||||
|
@ -310,12 +310,15 @@ public class AnnotationParser
|
|||
public void visitEnd()
|
||||
{
|
||||
super.visitEnd();
|
||||
|
||||
|
||||
//call all AnnotationHandlers with classname, annotation name + values
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handlers != null)
|
||||
{
|
||||
handler.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
|
||||
for (DiscoverableAnnotationHandler h:handlers)
|
||||
{
|
||||
h.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -340,10 +343,13 @@ public class AnnotationParser
|
|||
{
|
||||
super.visitEnd();
|
||||
//call all AnnotationHandlers with classname, method, annotation name + values
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handlers != null)
|
||||
{
|
||||
handler.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
|
||||
for (DiscoverableAnnotationHandler h:handlers)
|
||||
{
|
||||
h.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -369,10 +375,13 @@ public class AnnotationParser
|
|||
public void visitEnd()
|
||||
{
|
||||
super.visitEnd();
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handlers != null)
|
||||
{
|
||||
handler.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
|
||||
for (DiscoverableAnnotationHandler h:handlers)
|
||||
{
|
||||
h.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -383,9 +392,22 @@ public class AnnotationParser
|
|||
}
|
||||
|
||||
|
||||
public void registerAnnotationHandler (String annotationName, AnnotationHandler handler)
|
||||
/**
|
||||
* Register a handler that will be called back when the named annotation is
|
||||
* encountered on a class.
|
||||
*
|
||||
* @param annotationName
|
||||
* @param handler
|
||||
*/
|
||||
public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
|
||||
{
|
||||
_annotationHandlers.put(annotationName, handler);
|
||||
List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
|
||||
if (handlers == null)
|
||||
{
|
||||
handlers = new ArrayList<DiscoverableAnnotationHandler>();
|
||||
_annotationHandlers.put(annotationName, handlers);
|
||||
}
|
||||
handlers.add(handler);
|
||||
}
|
||||
|
||||
public void registerClassHandler (ClassHandler handler)
|
||||
|
@ -587,6 +609,14 @@ public class AnnotationParser
|
|||
scanner.scan(null, uris, true);
|
||||
}
|
||||
|
||||
public void parse (URI uri, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (uri == null)
|
||||
return;
|
||||
URI[] uris = {uri};
|
||||
parse(uris, resolver);
|
||||
}
|
||||
|
||||
private void scanClass (InputStream is)
|
||||
throws IOException
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
|
@ -11,79 +11,58 @@
|
|||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.ListValue;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.SimpleValue;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import javax.annotation.security.DeclareRoles;
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class DeclareRolesAnnotationHandler implements AnnotationHandler
|
||||
/**
|
||||
* DeclaresRolesAnnotationHandler
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DeclareRolesAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
|
||||
protected WebAppContext _context;
|
||||
|
||||
public DeclareRolesAnnotationHandler (WebAppContext wac)
|
||||
/**
|
||||
* @param introspectAncestors
|
||||
*/
|
||||
public DeclareRolesAnnotationHandler(WebAppContext context)
|
||||
{
|
||||
_wac = wac;
|
||||
super(false);
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A DeclareRoles annotation is equivalent to a <security-role> in web.xml.
|
||||
*
|
||||
* @see org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
|
||||
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
|
||||
*/
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
//Add the role names to the list of roles for the webapp
|
||||
Set<String> roles = new HashSet<String>();
|
||||
if (!Servlet.class.isAssignableFrom(clazz))
|
||||
return; //only applicable on javax.servlet.Servlet derivatives
|
||||
|
||||
try
|
||||
{
|
||||
Set<String> existing = ((ConstraintSecurityHandler)_wac.getSecurityHandler()).getRoles();
|
||||
roles.addAll(existing);
|
||||
|
||||
if (values != null && values.size() == 1)
|
||||
{
|
||||
Value v = values.get(0);
|
||||
if (v instanceof SimpleValue)
|
||||
{
|
||||
roles.add((String)((SimpleValue)v).getValue());
|
||||
}
|
||||
else if (v instanceof ListValue)
|
||||
{
|
||||
for (Value vv:((ListValue)v).getList())
|
||||
{
|
||||
roles.add((String)((SimpleValue)vv).getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
DeclareRoles declareRoles = (DeclareRoles) clazz.getAnnotation(DeclareRoles.class);
|
||||
if (declareRoles == null)
|
||||
return;
|
||||
|
||||
String[] roles = declareRoles.value();
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@DeclareRoles annotation not applicable for field: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@DeclareRoles annotation not applicable for method: "+className+"."+methodName);
|
||||
if (roles != null && roles.length > 0)
|
||||
{
|
||||
for (String r:roles)
|
||||
((ConstraintSecurityHandler)_context.getSecurityHandler()).addRole(r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,77 +13,65 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class PostConstructAnnotationHandler implements AnnotationHandler
|
||||
public class PostConstructAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
protected WebAppContext _context;
|
||||
protected LifeCycleCallbackCollection _callbacks;
|
||||
|
||||
public PostConstructAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
_callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
super(true);
|
||||
_context = wac;
|
||||
_callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
}
|
||||
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@PostConstruct annotation not applicable to classes: "+className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PostConstruct annotation not applicable to fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
try
|
||||
//Check that the PostConstruct is on a class that we're interested in
|
||||
if (Util.isServletType(clazz))
|
||||
{
|
||||
org.objectweb.asm.Type[] args = org.objectweb.asm.Type.getArgumentTypes(desc);
|
||||
|
||||
if (args.length != 0)
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (int i=0; i<methods.length; i++)
|
||||
{
|
||||
Log.warn("Skipping PostConstruct annotation on "+className+"."+methodName+": has parameters");
|
||||
return;
|
||||
Method m = (Method)methods[i];
|
||||
if (m.isAnnotationPresent(PostConstruct.class))
|
||||
{
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
//ServletSpec 3.0 p80 If web.xml declares even one post-construct then all post-constructs
|
||||
//in fragments must be ignored. Otherwise, they are additive.
|
||||
MetaData metaData = ((MetaData)_context.getAttribute(MetaData.METADATA));
|
||||
MetaData.Origin origin = metaData.getOrigin("post-construct");
|
||||
if (origin != null &&
|
||||
(origin == MetaData.Origin.WebXml ||
|
||||
origin == MetaData.Origin.WebDefaults ||
|
||||
origin == MetaData.Origin.WebOverride))
|
||||
return;
|
||||
|
||||
PostConstructCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz.getName(), m.getName());
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
if (org.objectweb.asm.Type.getReturnType(desc) != org.objectweb.asm.Type.VOID_TYPE)
|
||||
{
|
||||
Log.warn("Skipping PostConstruct annotation on "+className+"."+methodName+": is not void");
|
||||
return;
|
||||
}
|
||||
|
||||
if (exceptions != null && exceptions.length != 0)
|
||||
{
|
||||
Log.warn("Skipping PostConstruct annotation on "+className+"."+methodName+": throws checked exceptions");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((access & org.objectweb.asm.Opcodes.ACC_STATIC) > 0)
|
||||
{
|
||||
Log.warn("Skipping PostConstruct annotation on "+className+"."+methodName+": is static");
|
||||
return;
|
||||
}
|
||||
|
||||
PostConstructCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(className, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,75 +13,64 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class PreDestroyAnnotationHandler implements AnnotationHandler
|
||||
public class PreDestroyAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
WebAppContext _wac;
|
||||
WebAppContext _context;
|
||||
LifeCycleCallbackCollection _callbacks;
|
||||
|
||||
public PreDestroyAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
_callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
super(true);
|
||||
_context = wac;
|
||||
_callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PreDestroy annotation not applicable for classes: "+className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PreDestroy annotation not applicable for fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
try
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
//Check that the PreDestroy is on a class that we're interested in
|
||||
if (Util.isServletType(clazz))
|
||||
{
|
||||
org.objectweb.asm.Type[] args = org.objectweb.asm.Type.getArgumentTypes(desc);
|
||||
|
||||
if (args.length != 0)
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (int i=0; i<methods.length; i++)
|
||||
{
|
||||
Log.warn("Skipping PreDestroy annotation on "+className+"."+methodName+": has parameters");
|
||||
return;
|
||||
Method m = (Method)methods[i];
|
||||
if (m.isAnnotationPresent(PreDestroy.class))
|
||||
{
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
//ServletSpec 3.0 p80 If web.xml declares even one predestroy then all predestroys
|
||||
//in fragments must be ignored. Otherwise, they are additive.
|
||||
MetaData metaData = ((MetaData)_context.getAttribute(MetaData.METADATA));
|
||||
MetaData.Origin origin = metaData.getOrigin("pre-destroy");
|
||||
if (origin != null &&
|
||||
(origin == MetaData.Origin.WebXml ||
|
||||
origin == MetaData.Origin.WebDefaults ||
|
||||
origin == MetaData.Origin.WebOverride))
|
||||
return;
|
||||
|
||||
PreDestroyCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz.getName(), m.getName());
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
if (org.objectweb.asm.Type.getReturnType(desc) != org.objectweb.asm.Type.VOID_TYPE)
|
||||
{
|
||||
Log.warn("Skipping PreDestroy annotation on "+className+"."+methodName+": is not void");
|
||||
return;
|
||||
}
|
||||
|
||||
if (exceptions != null && exceptions.length != 0)
|
||||
{
|
||||
Log.warn("Skipping PreDestroy annotation on "+className+"."+methodName+": throws checked exceptions");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((access & org.objectweb.asm.Opcodes.ACC_STATIC) > 0)
|
||||
{
|
||||
Log.warn("Skipping PreDestroy annotation on "+className+"."+methodName+": is static");
|
||||
return;
|
||||
}
|
||||
|
||||
PreDestroyCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(className, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,28 +13,33 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.MetaData.Origin;
|
||||
|
||||
public class ResourceAnnotationHandler implements AnnotationHandler
|
||||
public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
protected WebAppContext _context;
|
||||
protected InjectionCollection _injections;
|
||||
|
||||
public ResourceAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
_injections = (InjectionCollection)_wac.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
super(true);
|
||||
_context = wac;
|
||||
_injections = (InjectionCollection)_context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,95 +48,104 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
* environment that will be looked up at runtime. They do
|
||||
* not specify an injection.
|
||||
*/
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
public void doHandle(Class clazz)
|
||||
{
|
||||
String name = null;
|
||||
String mappedName = null;
|
||||
String resourceType = null;
|
||||
if (values != null)
|
||||
if (Util.isServletType(clazz))
|
||||
{
|
||||
for (Value v : values)
|
||||
{
|
||||
if ("name".equals(v.getName()))
|
||||
name = (String)v.getValue();
|
||||
else if ("mappedName".equals(v.getName()))
|
||||
mappedName = (String)v.getValue();
|
||||
else if ("type".equals(v.getName()))
|
||||
resourceType = (String)v.getValue();
|
||||
}
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
|
||||
try
|
||||
{
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name,mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name,mappedName))
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
handleClass(clazz);
|
||||
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (int i=0; i<methods.length; i++)
|
||||
handleMethod(clazz, methods[i]);
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
//For each field, get all of it's annotations
|
||||
for (int i=0; i<fields.length; i++)
|
||||
handleField(clazz, fields[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleClass (Class clazz)
|
||||
{
|
||||
Resource resource = (Resource)clazz.getAnnotation(Resource.class);
|
||||
if (resource != null)
|
||||
{
|
||||
String name = resource.name();
|
||||
String mappedName = resource.mappedName();
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
Class type = resource.type();
|
||||
boolean shareable = resource.shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
|
||||
try
|
||||
{
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context, name,mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context.getServer(), name,mappedName))
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
public void handleField(Class clazz, Field field)
|
||||
{
|
||||
try
|
||||
Resource resource = (Resource)field.getAnnotation(Resource.class);
|
||||
if (resource != null)
|
||||
{
|
||||
//JavaEE Spec 5.2.3: Field cannot be static
|
||||
if ((access & org.objectweb.asm.Opcodes.ACC_STATIC) > 0)
|
||||
if (Modifier.isStatic(field.getModifiers()))
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+fieldName+": cannot be static");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+field.getName()+": cannot be static");
|
||||
return;
|
||||
}
|
||||
|
||||
//JavaEE Spec 5.2.3: Field cannot be final
|
||||
if ((access & org.objectweb.asm.Opcodes.ACC_FINAL) > 0)
|
||||
if (Modifier.isFinal(field.getModifiers()))
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+fieldName+": cannot be final");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+field.getName()+": cannot be final");
|
||||
return;
|
||||
}
|
||||
|
||||
//work out default name
|
||||
String name = className+"/"+fieldName;
|
||||
String mappedName = null;
|
||||
org.objectweb.asm.Type resourceType = null;
|
||||
if (values != null)
|
||||
String name = clazz.getCanonicalName()+"/"+field.getName();
|
||||
|
||||
//allow @Resource name= to override the field name
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
//get the type of the Field
|
||||
Class type = field.getType();
|
||||
|
||||
//Servlet Spec 3.0 p. 76
|
||||
//If a descriptor has specified at least 1 injection target for this
|
||||
//resource, then it overrides this annotation
|
||||
MetaData metaData = ((MetaData)_context.getAttribute(MetaData.METADATA));
|
||||
if (metaData.getOriginDescriptor("resource-ref."+name+".injection") != null)
|
||||
{
|
||||
for (Value val :values)
|
||||
{
|
||||
//allow @Resource name= to override the field name
|
||||
if (val.getName().equals("name") && !"".equals((String)val.getValue()))
|
||||
name = (String)(val.getValue());
|
||||
//get the mappedName if there is one
|
||||
else if (val.getName().equals("mappedName") && !"".equals((String)val.getValue()))
|
||||
mappedName = (String)val.getValue();
|
||||
//save @Resource type, so we can check it is compatible with field type later
|
||||
else if (val.getName().equals("type"))
|
||||
{
|
||||
resourceType = (org.objectweb.asm.Type)(val.getValue());
|
||||
}
|
||||
}
|
||||
//at least 1 injection was specified for this resource by a descriptor, so
|
||||
//it overrides this annotation
|
||||
return;
|
||||
}
|
||||
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = _injections.getInjection(name, className, fieldName);
|
||||
if (webXmlInjection == null)
|
||||
|
||||
//No injections for this resource in any descriptors, so we can add it
|
||||
//Does the injection already exist?
|
||||
Injection injection = _injections.getInjection(name, clazz, field);
|
||||
if (injection == null)
|
||||
{
|
||||
//No injection has been specified, add it
|
||||
try
|
||||
{
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName);
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context, name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName);
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context.getServer(), name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||
if (!bound)
|
||||
{
|
||||
//see if there is an env-entry value been bound from web.xml
|
||||
//see if there is an env-entry value been bound
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
|
@ -149,16 +163,17 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it if the binding succeeded
|
||||
Injection injection = new Injection();
|
||||
injection.setTarget(className, fieldName, Util.asCanonicalName(resourceType));
|
||||
injection = new Injection();
|
||||
injection.setTarget(clazz, field, type);
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
_injections.add(injection);
|
||||
}
|
||||
else if (!Util.isEnvEntryType(fieldType))
|
||||
{
|
||||
System.err.println(fieldType);
|
||||
|
||||
//TODO - an @Resource is equivalent to a resource-ref, resource-env-ref, message-destination
|
||||
metaData.setOrigin("resource-ref."+name+".injection");
|
||||
}
|
||||
else if (!Util.isEnvEntryType(type))
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
|
@ -171,29 +186,26 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!Util.isEnvEntryType(fieldType))
|
||||
if (!Util.isEnvEntryType(type))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a Resource annotation on a Method.
|
||||
*
|
||||
* This will generate a JNDI entry, and an Injection to be
|
||||
* processed when an instance of the class is created.
|
||||
*/
|
||||
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
public void handleMethod(Class clazz, Method method)
|
||||
{
|
||||
try
|
||||
|
||||
Resource resource = (Resource)method.getAnnotation(Resource.class);
|
||||
if (resource != null)
|
||||
{
|
||||
|
||||
/*
|
||||
* Commons Annotations Spec 2.3
|
||||
* " The Resource annotation is used to declare a reference to a resource.
|
||||
|
@ -212,70 +224,68 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
* or field, inject it!".
|
||||
*/
|
||||
//JavaEE Spec 5.2.3: Method cannot be static
|
||||
if ((access & org.objectweb.asm.Opcodes.ACC_STATIC) > 0)
|
||||
if (Modifier.isStatic(method.getModifiers()))
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+methodName+": cannot be static");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+method.getName()+": cannot be static");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check it is a valid javabean: must be void return type, the name must start with "set" and it must have
|
||||
// only 1 parameter
|
||||
if (!methodName.startsWith("set"))
|
||||
if (!method.getName().startsWith("set"))
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+methodName+": invalid java bean, does not start with 'set'");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+method.getName()+": invalid java bean, does not start with 'set'");
|
||||
return;
|
||||
}
|
||||
org.objectweb.asm.Type[] args = org.objectweb.asm.Type.getArgumentTypes(desc);
|
||||
if (args == null || args.length != 1)
|
||||
|
||||
if (method.getParameterTypes().length != 1)
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+methodName+": invalid java bean, not single argument to method");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+method.getName()+": invalid java bean, not single argument to method");
|
||||
return;
|
||||
}
|
||||
org.objectweb.asm.Type retVal = org.objectweb.asm.Type.getReturnType(desc);
|
||||
if (!org.objectweb.asm.Type.VOID_TYPE.equals(retVal))
|
||||
|
||||
if (Void.TYPE != method.getReturnType())
|
||||
{
|
||||
Log.warn("Skipping Resource annotation on "+className+"."+methodName+": invalid java bean, not void");
|
||||
Log.warn("Skipping Resource annotation on "+clazz.getName()+"."+method.getName()+": invalid java bean, not void");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//default name is the javabean property name
|
||||
String name = methodName.substring(3);
|
||||
String name = method.getName().substring(3);
|
||||
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||
name = className+"/"+name;
|
||||
String mappedName = null;
|
||||
org.objectweb.asm.Type resourceType = null;
|
||||
if (values != null)
|
||||
{
|
||||
for (Value v : values)
|
||||
{
|
||||
//allow default name to be overridden
|
||||
if ("name".equals(v.getName()))
|
||||
name = (String)(v.getValue());
|
||||
//get the mappedName if there is one
|
||||
else if ("mappedName".equals(v.getName()) && !"".equals((String)(v.getValue())))
|
||||
mappedName = (String)(v.getValue());
|
||||
else if ("type".equals(v.getName()))
|
||||
{
|
||||
resourceType = (org.objectweb.asm.Type)(v.getValue());
|
||||
}
|
||||
//TODO: authentication and shareable
|
||||
}
|
||||
}
|
||||
name = clazz.getCanonicalName()+"/"+name;
|
||||
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
Class paramType = method.getParameterTypes()[0];
|
||||
|
||||
Class resourceType = resource.type();
|
||||
|
||||
//Servlet Spec 3.0 p. 76
|
||||
//If a descriptor has specified at least 1 injection target for this
|
||||
//resource, then it overrides this annotation
|
||||
MetaData metaData = ((MetaData)_context.getAttribute(MetaData.METADATA));
|
||||
if (metaData.getOriginDescriptor("resource-ref."+name+".injection") != null)
|
||||
{
|
||||
//at least 1 injection was specified for this resource by a descriptor, so
|
||||
//it overrides this annotation
|
||||
return;
|
||||
}
|
||||
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = _injections.getInjection(name, className, methodName, Util.asCanonicalName(args[0]));
|
||||
if (webXmlInjection == null)
|
||||
Injection injection = _injections.getInjection(name, clazz, method, paramType);
|
||||
if (injection == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try binding name to environment
|
||||
//try the webapp's environment first
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName);
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context, name, mappedName);
|
||||
|
||||
//try the server's environment
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName);
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_context.getServer(), name, mappedName);
|
||||
|
||||
//try the jvm's environment
|
||||
if (!bound)
|
||||
|
@ -302,13 +312,15 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it
|
||||
Injection injection = new Injection();
|
||||
injection.setTarget(className, methodName, Util.asCanonicalName(args[0]), Util.asCanonicalName(resourceType));
|
||||
injection = new Injection();
|
||||
injection.setTarget(clazz, method,paramType,resourceType);
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
_injections.add(injection);
|
||||
//TODO - an @Resource is equivalent to a resource-ref, resource-env-ref, message-destination
|
||||
metaData.setOrigin("resource-ref."+name+".injection");
|
||||
}
|
||||
else if (!Util.isEnvEntryType(args[0].getDescriptor()))
|
||||
else if (!Util.isEnvEntryType(paramType))
|
||||
{
|
||||
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
|
@ -322,14 +334,11 @@ public class ResourceAnnotationHandler implements AnnotationHandler
|
|||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!Util.isEnvEntryType(args[0].getDescriptor()))
|
||||
if (!Util.isEnvEntryType(paramType))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,78 +13,63 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.Resources;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.ListValue;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class ResourcesAnnotationHandler implements AnnotationHandler
|
||||
public class ResourcesAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
|
||||
protected WebAppContext _wac;
|
||||
|
||||
public ResourcesAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
super(true);
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
public void doHandle (Class clazz)
|
||||
{
|
||||
if (values != null && values.size() == 1)
|
||||
Resources resources = (Resources)clazz.getAnnotation(Resources.class);
|
||||
if (resources != null)
|
||||
{
|
||||
List<ListValue> list = (List<ListValue>)(values.get(0).getValue());
|
||||
for (ListValue resource : list)
|
||||
Resource[] resArray = resources.value();
|
||||
if (resArray==null||resArray.length==0)
|
||||
{
|
||||
List<Value> resourceValues = resource.getList();
|
||||
String name = null;
|
||||
String mappedName = null;
|
||||
for (Value v:resourceValues)
|
||||
Log.warn ("Skipping empty or incorrect Resources annotation on "+clazz.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
for (int j=0;j<resArray.length;j++)
|
||||
{
|
||||
|
||||
String name = resArray[j].name();
|
||||
String mappedName = resArray[j].mappedName();
|
||||
Resource.AuthenticationType auth = resArray[j].authenticationType();
|
||||
Class type = resArray[j].type();
|
||||
boolean shareable = resArray[j].shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
|
||||
try
|
||||
{
|
||||
if ("name".equals(v.getName()))
|
||||
name = (String)v.getValue();
|
||||
else if ("mappedName".equals(v.getName()))
|
||||
mappedName = (String)v.getValue();
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName))
|
||||
Log.warn("Skipping Resources(Resource) annotation on "+clazz.getName()+" for name "+name+": No resource bound at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
if (name == null)
|
||||
Log.warn ("Skipping Resources(Resource) annotation with no name on class "+className);
|
||||
else
|
||||
catch (NamingException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName))
|
||||
Log.warn("Skipping Resources(Resource) annotation on "+className+" for name "+name+": No resource bound at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warn("Skipping empty or incorrect Resources annotation on "+className);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@Resources not applicable for fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@Resources not applicable for methods: "+className+"."+methodName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,47 +15,63 @@ package org.eclipse.jetty.annotations;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.Descriptor;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class RunAsAnnotationHandler implements AnnotationHandler
|
||||
public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
protected WebAppContext _context;
|
||||
|
||||
public RunAsAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
//Introspect only the given class for a RunAs annotation, as it is a class level annotation,
|
||||
//and according to Common Annotation Spec p2-6 a class-level annotation is not inheritable.
|
||||
super(false);
|
||||
_context = wac;
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
public void doHandle (Class clazz)
|
||||
{
|
||||
RunAsCollection runAsCollection = (RunAsCollection)_wac.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
|
||||
try
|
||||
RunAsCollection runAsCollection = (RunAsCollection)_context.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
|
||||
if (!Servlet.class.isAssignableFrom(clazz))
|
||||
return;
|
||||
|
||||
javax.annotation.security.RunAs runAs = (javax.annotation.security.RunAs)clazz.getAnnotation(javax.annotation.security.RunAs.class);
|
||||
if (runAs != null)
|
||||
{
|
||||
if (values != null && values.size() == 1)
|
||||
String role = runAs.value();
|
||||
if (role != null)
|
||||
{
|
||||
String role = (String)values.get(0).getValue();
|
||||
if (role != null)
|
||||
ServletHolder holder = getServletHolderForClass(clazz);
|
||||
if (holder != null)
|
||||
{
|
||||
org.eclipse.jetty.plus.annotation.RunAs ra = new org.eclipse.jetty.plus.annotation.RunAs();
|
||||
ra.setTargetClassName(className);
|
||||
ra.setRoleName(role);
|
||||
runAsCollection.add(ra);
|
||||
MetaData metaData = ((MetaData)_context.getAttribute(MetaData.METADATA));
|
||||
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.run-as");
|
||||
//if a descriptor has already set the value for run-as, do not
|
||||
//let the annotation override it
|
||||
if (d == null)
|
||||
{
|
||||
metaData.setOrigin(holder.getName()+".servlet.run-as");
|
||||
org.eclipse.jetty.plus.annotation.RunAs ra = new org.eclipse.jetty.plus.annotation.RunAs();
|
||||
ra.setTargetClassName(clazz.getCanonicalName());
|
||||
ra.setRoleName(role);
|
||||
runAsCollection.add(ra);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Log.warn("Bad value for @RunAs annotation on class "+className);
|
||||
Log.warn("Bad value for @RunAs annotation on class "+clazz.getName());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
|
@ -70,4 +86,20 @@ public class RunAsAnnotationHandler implements AnnotationHandler
|
|||
Log.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature);
|
||||
}
|
||||
|
||||
private ServletHolder getServletHolderForClass (Class clazz)
|
||||
{
|
||||
ServletHolder holder = null;
|
||||
ServletHolder[] holders = _context.getServletHandler().getServlets();
|
||||
if (holders != null)
|
||||
{
|
||||
for (ServletHolder h : holders)
|
||||
{
|
||||
if (h.getClassName().equals(clazz.getName()))
|
||||
{
|
||||
holder = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler.Decorator;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* WebAppDecoratorWrapper
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class WebAppDecoratorWrapper implements Decorator
|
||||
{
|
||||
Decorator _wrappedDecorator;
|
||||
AnnotationIntrospector _introspector = new AnnotationIntrospector();
|
||||
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
public WebAppDecoratorWrapper(WebAppContext context, Decorator wrappedDecorator)
|
||||
{
|
||||
_wrappedDecorator = wrappedDecorator;
|
||||
_introspector.registerHandler(new ResourceAnnotationHandler(context));
|
||||
_introspector.registerHandler(new ResourcesAnnotationHandler(context));
|
||||
_introspector.registerHandler(new RunAsAnnotationHandler(context));
|
||||
_introspector.registerHandler(new PostConstructAnnotationHandler(context));
|
||||
_introspector.registerHandler(new PreDestroyAnnotationHandler(context));
|
||||
_introspector.registerHandler(new DeclareRolesAnnotationHandler(context));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param filter
|
||||
* @throws ServletException
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterHolder(org.eclipse.jetty.servlet.FilterHolder)
|
||||
*/
|
||||
public void decorateFilterHolder(FilterHolder filter) throws ServletException
|
||||
{
|
||||
_wrappedDecorator.decorateFilterHolder(filter);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param <T>
|
||||
* @param filter
|
||||
* @return
|
||||
* @throws ServletException
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterInstance(javax.servlet.Filter)
|
||||
*/
|
||||
public <T extends Filter> T decorateFilterInstance(T filter) throws ServletException
|
||||
{
|
||||
introspect(filter);
|
||||
return _wrappedDecorator.decorateFilterInstance(filter);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param <T>
|
||||
* @param listener
|
||||
* @return
|
||||
* @throws ServletException
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateListenerInstance(java.util.EventListener)
|
||||
*/
|
||||
public <T extends EventListener> T decorateListenerInstance(T listener) throws ServletException
|
||||
{
|
||||
introspect(listener);
|
||||
return _wrappedDecorator.decorateListenerInstance(listener);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param servlet
|
||||
* @throws ServletException
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletHolder(org.eclipse.jetty.servlet.ServletHolder)
|
||||
*/
|
||||
public void decorateServletHolder(ServletHolder servlet) throws ServletException
|
||||
{
|
||||
_wrappedDecorator.decorateServletHolder(servlet);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param <T>
|
||||
* @param servlet
|
||||
* @return
|
||||
* @throws ServletException
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletInstance(javax.servlet.Servlet)
|
||||
*/
|
||||
public <T extends Servlet> T decorateServletInstance(T servlet) throws ServletException
|
||||
{
|
||||
introspect(servlet);
|
||||
return _wrappedDecorator.decorateServletInstance(servlet);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param f
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyFilterInstance(javax.servlet.Filter)
|
||||
*/
|
||||
public void destroyFilterInstance(Filter f)
|
||||
{
|
||||
_wrappedDecorator.destroyFilterInstance(f);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param s
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyServletInstance(javax.servlet.Servlet)
|
||||
*/
|
||||
public void destroyServletInstance(Servlet s)
|
||||
{
|
||||
_wrappedDecorator.destroyServletInstance(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param f
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyListenerInstance(java.util.EventListener)
|
||||
*/
|
||||
public void destroyListenerInstance(EventListener f)
|
||||
{
|
||||
_wrappedDecorator.destroyListenerInstance(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for annotations that can be discovered with introspection:
|
||||
* <ul>
|
||||
* <li> Resource
|
||||
* <li> Resources
|
||||
* <li> PostConstruct
|
||||
* <li> PreDestroy
|
||||
* <li> ServletSecurity?
|
||||
* </ul>
|
||||
* @param o
|
||||
*/
|
||||
protected void introspect (Object o)
|
||||
{
|
||||
_introspector.introspect(o.getClass());
|
||||
}
|
||||
}
|
|
@ -28,8 +28,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
|
||||
@RunAs("admin")
|
||||
public class FilterC implements Filter
|
||||
{
|
||||
|
|
|
@ -15,8 +15,6 @@ package org.eclipse.jetty.annotations;
|
|||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
|
||||
|
||||
public class ListenerC implements ServletContextListener
|
||||
{
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// Copyright (c) 2008-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
|
@ -17,7 +17,7 @@ import java.io.IOException;
|
|||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.Resources;
|
||||
import javax.annotation.security.DeclareRoles;
|
||||
import javax.annotation.security.RunAs;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -26,11 +26,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
|
||||
|
||||
|
||||
@Resources({
|
||||
@Resource(name="apple", mappedName="foo"),
|
||||
@Resource(name="banana", mappedName="foo")
|
||||
})
|
||||
@DeclareRoles({"alice"})
|
||||
@RunAs("admin")
|
||||
public class ServletC extends HttpServlet
|
||||
{
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.FragmentDescriptor;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* TestAnnotationConfiguration
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TestAnnotationConfiguration extends TestCase
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
public void testGetFragmentFromJar ()
|
||||
throws Exception
|
||||
{
|
||||
String dir = System.getProperty("basedir", ".");
|
||||
File file = new File(dir);
|
||||
file=new File(file.getCanonicalPath());
|
||||
URL url=file.toURL();
|
||||
|
||||
Resource jar1 = Resource.newResource(url+"file.jar");
|
||||
|
||||
AbstractConfiguration config = new AbstractConfiguration()
|
||||
{
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
WebAppContext wac = new WebAppContext();
|
||||
|
||||
List<FragmentDescriptor> frags = new ArrayList<FragmentDescriptor>();
|
||||
frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file.jar!/fooa.props"), null));
|
||||
frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file2.jar!/foob.props"), null));
|
||||
|
||||
assertNotNull(config.getFragmentFromJar(jar1, frags));
|
||||
}
|
||||
}
|
|
@ -13,31 +13,29 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TestAnnotationInheritance
|
||||
{
|
||||
private List<String> classNames = new ArrayList<String>();
|
||||
|
||||
private class SampleHandler implements AnnotationHandler
|
||||
List<String> classNames = new ArrayList<String>();
|
||||
|
||||
|
||||
class SampleHandler implements DiscoverableAnnotationHandler
|
||||
{
|
||||
public final List<String> annotatedClassNames = new ArrayList<String>();
|
||||
public final List<String> annotatedMethods = new ArrayList<String>();
|
||||
|
@ -188,40 +186,4 @@ public class TestAnnotationInheritance
|
|||
});
|
||||
assertEquals (1, handler.annotatedClassNames.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeInheritanceHandling() throws Exception
|
||||
{
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
ClassInheritanceHandler handler = new ClassInheritanceHandler();
|
||||
parser.registerClassHandler(handler);
|
||||
|
||||
class Foo implements InterfaceD
|
||||
{
|
||||
}
|
||||
|
||||
classNames.clear();
|
||||
classNames.add(ClassA.class.getName());
|
||||
classNames.add(ClassB.class.getName());
|
||||
classNames.add(InterfaceD.class.getName());
|
||||
classNames.add(Foo.class.getName());
|
||||
|
||||
parser.parse(classNames, null);
|
||||
|
||||
MultiMap map = handler.getMap();
|
||||
assertNotNull(map);
|
||||
assertFalse(map.isEmpty());
|
||||
assertEquals(2, map.size());
|
||||
Map stringArrayMap = map.toStringArrayMap();
|
||||
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
|
||||
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
|
||||
String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA");
|
||||
assertEquals(1, classes.length);
|
||||
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
|
||||
|
||||
classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD");
|
||||
assertEquals(2, classes.length);
|
||||
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
|
||||
assertEquals(Foo.class.getName(), classes[1]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ package org.eclipse.jetty.annotations;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class TestAnnotationParser
|
|||
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassA"};
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
class SampleAnnotationHandler implements AnnotationHandler
|
||||
class SampleAnnotationHandler implements DiscoverableAnnotationHandler
|
||||
{
|
||||
private List<String> methods = Arrays.asList("a", "b", "c", "d", "l");
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class TestAnnotationParser
|
|||
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassB"};
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
class MultiAnnotationHandler implements AnnotationHandler
|
||||
class MultiAnnotationHandler implements DiscoverableAnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
|
|
|
@ -13,17 +13,15 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* TestServletAnnotations
|
||||
|
@ -32,172 +30,20 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public class TestServletAnnotations
|
||||
{
|
||||
|
||||
@Test
|
||||
public void testServletAnnotation() throws Exception
|
||||
{
|
||||
List<String> classes = new ArrayList<String>();
|
||||
classes.add("org.eclipse.jetty.annotations.ServletC");
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
class ResourceAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("org.eclipse.jetty.annotations.ServletC", className);
|
||||
|
||||
assertEquals ("foo",fieldName);
|
||||
assertNotNull (values);
|
||||
assertNotNull (annotation);
|
||||
assertTrue (annotation.endsWith("Resource"));
|
||||
|
||||
for (Value v :values)
|
||||
{
|
||||
if (v.getName().equals("mappedName"))
|
||||
assertEquals ("foo", v.getValue());
|
||||
else if (v.getName().equals("type"))
|
||||
{
|
||||
try
|
||||
{
|
||||
assertEquals(fieldType, ((org.objectweb.asm.Type)v.getValue()).getDescriptor());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class CallbackAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("org.eclipse.jetty.annotations.ServletC", className);
|
||||
assertNotNull(methodName);
|
||||
if (methodName.endsWith("pre"))
|
||||
{
|
||||
assertTrue(annotation.endsWith("PreDestroy"));
|
||||
assertTrue(values.isEmpty());
|
||||
}
|
||||
else if (methodName.endsWith("post"))
|
||||
{
|
||||
assertTrue(annotation.endsWith("PostConstruct"));
|
||||
assertTrue(values.isEmpty());
|
||||
}
|
||||
|
||||
assertEquals (org.objectweb.asm.Type.VOID_TYPE, org.objectweb.asm.Type.getReturnType(desc));
|
||||
assertEquals(0, org.objectweb.asm.Type.getArgumentTypes(desc).length);
|
||||
int isstatic = access & org.objectweb.asm.Opcodes.ACC_STATIC;
|
||||
|
||||
assertTrue (isstatic == 0);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class RunAsAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertNotNull (values);
|
||||
assertEquals(1, values.size());
|
||||
Value anv = values.get(0);
|
||||
assertEquals("value", anv.getName());
|
||||
assertEquals("admin", anv.getValue());
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class ResourcesAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass (String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertNotNull (values);
|
||||
for (Value v : values)
|
||||
{
|
||||
List list = (List)(v.getValue());
|
||||
for (Object o : list)
|
||||
{
|
||||
AnnotationParser.ListValue lv = (AnnotationParser.ListValue)o;
|
||||
List<Value> theValues = lv.getList();
|
||||
for (Value vv : theValues)
|
||||
{
|
||||
if ("name".equals((String)vv.getName()))
|
||||
{
|
||||
if (!"apple".equals((String)vv.getValue()) && !"banana".equals((String)vv.getValue()))
|
||||
fail("Wrong name "+vv.getName());
|
||||
}
|
||||
else if ("mappedName".equals((String)vv.getName()))
|
||||
assertEquals("foo", (String)vv.getValue());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
parser.registerAnnotationHandler("javax.annotation.Resources", new ResourcesAnnotationHandler());
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", new ResourceAnnotationHandler ());
|
||||
parser.registerAnnotationHandler("javax.annotation.PostConstruct", new CallbackAnnotationHandler());
|
||||
parser.registerAnnotationHandler("javax.annotation.PreDestroy", new CallbackAnnotationHandler());
|
||||
parser.registerAnnotationHandler("javax.annotation.security.RunAs", new RunAsAnnotationHandler());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
parser.parse(classes, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.err.println("Time to parse class: "+((end-start)));
|
||||
public void testDeclareRoles ()
|
||||
throws Exception
|
||||
{
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setAttribute(MetaData.METADATA, new MetaData(wac));
|
||||
ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
|
||||
wac.setSecurityHandler(sh);
|
||||
sh.setRoles(new HashSet<String>(Arrays.asList(new String[]{"humpty", "dumpty"})));
|
||||
DeclareRolesAnnotationHandler handler = new DeclareRolesAnnotationHandler(wac);
|
||||
handler.doHandle(ServletC.class);
|
||||
assertTrue(sh.getRoles().contains("alice"));
|
||||
assertTrue(sh.getRoles().contains("humpty"));
|
||||
assertTrue(sh.getRoles().contains("dumpty"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationIntrospector;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser;
|
||||
import org.eclipse.jetty.annotations.ClassNameResolver;
|
||||
import org.eclipse.jetty.annotations.ResourceAnnotationHandler;
|
||||
|
@ -13,6 +14,8 @@ import org.eclipse.jetty.annotations.ResourcesAnnotationHandler;
|
|||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -21,40 +24,29 @@ import static org.junit.Assert.assertNotNull;
|
|||
|
||||
public class TestResourceAnnotations
|
||||
{
|
||||
|
||||
@Test
|
||||
public void testResourceAnnotations() throws Exception
|
||||
public void testResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
wac.setAttribute(MetaData.METADATA, new MetaData(wac));
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", 1000, false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", 2000, false);
|
||||
|
||||
ArrayList<String> classNames = new ArrayList<String>();
|
||||
classNames.add(ResourceA.class.getName());
|
||||
classNames.add(ResourceB.class.getName());
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
AnnotationIntrospector parser = new AnnotationIntrospector();
|
||||
ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac);
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", handler);
|
||||
parser.parse(classNames, new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
parser.registerHandler(handler);
|
||||
parser.introspect(ResourceA.class);
|
||||
parser.introspect(ResourceB.class);
|
||||
|
||||
//processing classA should give us these jndi name bindings:
|
||||
// java:comp/env/myf
|
||||
|
@ -82,7 +74,7 @@ public class TestResourceAnnotations
|
|||
//only 1 field injection because the other has no Resource mapping
|
||||
assertEquals(1, resBInjections.size());
|
||||
Injection fi = resBInjections.get(0);
|
||||
assertEquals ("f", fi.getFieldName());
|
||||
assertEquals ("f", fi.getTarget().getName());
|
||||
|
||||
//3 method injections on class ResourceA, 4 field injections
|
||||
List<Injection> resAInjections = injections.getInjections(ResourceA.class.getCanonicalName());
|
||||
|
@ -126,9 +118,11 @@ public class TestResourceAnnotations
|
|||
|
||||
comp.destroySubcontext("env");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testResourcesAnnotation() throws Exception
|
||||
public void testResourcesAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
|
@ -138,29 +132,15 @@ public class TestResourceAnnotations
|
|||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", 1000, false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", 2000, false);
|
||||
|
||||
ArrayList<String> classNames = new ArrayList<String>();
|
||||
classNames.add(ResourceA.class.getName());
|
||||
classNames.add(ResourceB.class.getName());
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||
|
||||
AnnotationIntrospector introspector = new AnnotationIntrospector();
|
||||
ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac);
|
||||
parser.registerAnnotationHandler("javax.annotation.Resources", handler);
|
||||
parser.parse(classNames, new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
introspector.registerHandler(handler);
|
||||
introspector.introspect(ResourceA.class);
|
||||
introspector.introspect(ResourceB.class);
|
||||
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("peach"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("pear"));
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
<!-- Uncomment the following to set up a deployer that will -->
|
||||
<!-- deploy webapps from a directory called webapps-plus. Note -->
|
||||
<!-- that you will need to create this directory first! -->
|
||||
<!--
|
||||
<Ref id="DeploymentManager">
|
||||
<Call name="addAppProvider">
|
||||
<Arg>
|
||||
|
@ -74,6 +73,5 @@
|
|||
</Arg>
|
||||
</Call>
|
||||
</Ref>
|
||||
-->
|
||||
</Configure>
|
||||
|
||||
|
|
|
@ -39,12 +39,9 @@ public class Injection
|
|||
private String _jndiName;
|
||||
private String _mappingName;
|
||||
private Member _target;
|
||||
private String _className;
|
||||
private String _fieldName;
|
||||
private String _methodName;
|
||||
private String _paramCanonicalName;
|
||||
private String _annotationResourceType;
|
||||
|
||||
private Class _paramClass;
|
||||
private Class _resourceClass;
|
||||
|
||||
|
||||
public Injection ()
|
||||
{}
|
||||
|
@ -58,35 +55,24 @@ public class Injection
|
|||
return _targetClass;
|
||||
}
|
||||
|
||||
|
||||
public String getTargetClassName()
|
||||
public Class getParamClass ()
|
||||
{
|
||||
return _className;
|
||||
return _paramClass;
|
||||
}
|
||||
|
||||
public String getFieldName ()
|
||||
|
||||
public Class getResourceClass ()
|
||||
{
|
||||
return _fieldName;
|
||||
}
|
||||
|
||||
public String getMethodName ()
|
||||
{
|
||||
return _methodName;
|
||||
}
|
||||
|
||||
public String getParamCanonicalName ()
|
||||
{
|
||||
return _paramCanonicalName;
|
||||
return _resourceClass;
|
||||
}
|
||||
|
||||
public boolean isField ()
|
||||
{
|
||||
return (_fieldName != null);
|
||||
return (_target != null && _target instanceof Field);
|
||||
}
|
||||
|
||||
public boolean isMethod ()
|
||||
{
|
||||
return (_methodName != null);
|
||||
return (_target != null && _target instanceof Method);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,59 +112,51 @@ public class Injection
|
|||
return _target;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set up an injection target that is a field
|
||||
* @param className
|
||||
* @param fieldName
|
||||
*/
|
||||
public void setTarget (String className, String fieldName, String annotationResourceType)
|
||||
|
||||
public void setTarget(Class clazz, Field field, Class resourceType)
|
||||
{
|
||||
_className = className;
|
||||
_fieldName = fieldName;
|
||||
_annotationResourceType = annotationResourceType;
|
||||
_targetClass = clazz;
|
||||
_target = field;
|
||||
_resourceClass = resourceType;
|
||||
}
|
||||
public void setTarget(Class clazz, Method method, Class arg, Class resourceType)
|
||||
{
|
||||
_targetClass = clazz;
|
||||
_target = method;
|
||||
_resourceClass = resourceType;
|
||||
_paramClass = arg;
|
||||
}
|
||||
|
||||
public void setTarget (String className, String methodName, String paramCanonicalName, String annotationResourceType)
|
||||
{
|
||||
_className = className;
|
||||
_methodName = methodName;
|
||||
_paramCanonicalName = paramCanonicalName;
|
||||
_annotationResourceType = annotationResourceType;
|
||||
}
|
||||
|
||||
|
||||
public void setTarget (Class clazz, String targetName, Class targetType)
|
||||
|
||||
public void setTarget (Class clazz, String target, Class resourceType)
|
||||
{
|
||||
_targetClass = clazz;
|
||||
_resourceClass = resourceType;
|
||||
|
||||
//first look for a javabeans style setter matching the targetName
|
||||
String setter = "set"+targetName.substring(0,1).toUpperCase()+targetName.substring(1);
|
||||
String setter = "set"+target.substring(0,1).toUpperCase()+target.substring(1);
|
||||
try
|
||||
{
|
||||
Log.debug("Looking for method for setter: "+setter+" with arg "+targetType);
|
||||
_target = IntrospectionUtil.findMethod(clazz, setter, new Class[] {targetType}, true, false);
|
||||
Log.debug("Looking for method for setter: "+setter+" with arg "+_resourceClass);
|
||||
_target = IntrospectionUtil.findMethod(clazz, setter, new Class[] {_resourceClass}, true, false);
|
||||
_targetClass = clazz;
|
||||
_className = clazz.getCanonicalName();
|
||||
_methodName = targetName;
|
||||
_paramCanonicalName = targetType.getCanonicalName();
|
||||
_paramClass = _resourceClass;
|
||||
}
|
||||
catch (NoSuchMethodException me)
|
||||
{
|
||||
//try as a field
|
||||
try
|
||||
{
|
||||
_target = IntrospectionUtil.findField(clazz, targetName, targetType, true, false);
|
||||
_targetClass = clazz;
|
||||
_className = clazz.getCanonicalName();
|
||||
_fieldName = targetName;
|
||||
_target = IntrospectionUtil.findField(clazz, target, resourceType, true, false);
|
||||
_targetClass = clazz;
|
||||
}
|
||||
catch (NoSuchFieldException fe)
|
||||
{
|
||||
throw new IllegalArgumentException("No such field or method "+targetName+" on class "+_targetClass);
|
||||
throw new IllegalArgumentException("No such field or method "+target+" on class "+_targetClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a value for a Resource from JNDI into an object
|
||||
|
@ -186,19 +164,6 @@ public class Injection
|
|||
*/
|
||||
public void inject (Object injectable)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_target == null)
|
||||
loadField();
|
||||
|
||||
if (_target == null)
|
||||
loadMethod();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException (e);
|
||||
}
|
||||
|
||||
if (_target != null)
|
||||
{
|
||||
if (_target instanceof Field)
|
||||
|
@ -223,7 +188,7 @@ public class Injection
|
|||
return context.lookup("java:comp/env/"+getJndiName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inject value from jndi into a field of an instance
|
||||
|
@ -231,24 +196,19 @@ public class Injection
|
|||
* @param injectable
|
||||
*/
|
||||
protected void injectField (Field field, Object injectable)
|
||||
{
|
||||
if (validateInjection())
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean accessibility = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.set(injectable, lookupInjectedValue());
|
||||
field.setAccessible(accessibility);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
throw new IllegalStateException("Inject failed for field "+field.getName());
|
||||
}
|
||||
boolean accessibility = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
field.set(injectable, lookupInjectedValue());
|
||||
field.setAccessible(accessibility);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
throw new IllegalStateException("Inject failed for field "+field.getName());
|
||||
}
|
||||
else
|
||||
throw new IllegalStateException ("Invalid injection for "+_className+"."+_fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,100 +218,18 @@ public class Injection
|
|||
*/
|
||||
protected void injectMethod (Method method, Object injectable)
|
||||
{
|
||||
if (validateInjection())
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean accessibility = method.isAccessible();
|
||||
method.setAccessible(true);
|
||||
method.invoke(injectable, new Object[] {lookupInjectedValue()});
|
||||
method.setAccessible(accessibility);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
throw new IllegalStateException("Inject failed for method "+method.getName());
|
||||
}
|
||||
boolean accessibility = method.isAccessible();
|
||||
method.setAccessible(true);
|
||||
method.invoke(injectable, new Object[] {lookupInjectedValue()});
|
||||
method.setAccessible(accessibility);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
throw new IllegalStateException("Inject failed for method "+method.getName());
|
||||
}
|
||||
else
|
||||
throw new IllegalStateException("Invalid injection for "+_className+"."+_methodName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void loadField()
|
||||
throws ClassNotFoundException, NoSuchFieldException
|
||||
{
|
||||
if (_fieldName == null || _className == null)
|
||||
return;
|
||||
|
||||
if (_targetClass == null)
|
||||
_targetClass = Loader.loadClass(null, _className);
|
||||
|
||||
_target = _targetClass.getDeclaredField(_fieldName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load the target class and method.
|
||||
* A valid injection target method only has 1 argument.
|
||||
* @throws ClassNotFoundException
|
||||
* @throws NoSuchMethodException
|
||||
*/
|
||||
protected void loadMethod ()
|
||||
throws ClassNotFoundException, NoSuchMethodException
|
||||
{
|
||||
if (_methodName == null || _className == null)
|
||||
return;
|
||||
|
||||
if (_targetClass == null)
|
||||
_targetClass = Loader.loadClass(null, _className);
|
||||
|
||||
Class arg = TypeUtil.fromName(_paramCanonicalName);
|
||||
|
||||
if (arg == null)
|
||||
arg = Loader.loadClass(null, _paramCanonicalName);
|
||||
|
||||
_target = _targetClass.getDeclaredMethod(_methodName, new Class[] {arg});
|
||||
}
|
||||
|
||||
|
||||
private boolean validateInjection ()
|
||||
{
|
||||
|
||||
//check that if the injection came from an annotation, the type specified in the annotation
|
||||
//is compatible with the field or method to inject
|
||||
//JavaEE spec sec 5.2.4
|
||||
if (_annotationResourceType != null)
|
||||
{
|
||||
if (_target == null)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
Class<?> annotationType = TypeUtil.fromName(_annotationResourceType);
|
||||
if (annotationType == null)
|
||||
annotationType = Loader.loadClass(null, _annotationResourceType);
|
||||
|
||||
if (_target instanceof Field)
|
||||
{
|
||||
return ((Field)_target).getType().isAssignableFrom(annotationType);
|
||||
}
|
||||
else if (_target instanceof Method)
|
||||
{
|
||||
Class<?>[] args = ((Method)_target).getParameterTypes();
|
||||
return args[0].isAssignableFrom(annotationType);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Unable to verify injection for "+_className+"."+ (_fieldName==null?_methodName:_fieldName));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
package org.eclipse.jetty.plus.annotation;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -30,22 +32,22 @@ public class InjectionCollection
|
|||
public static final String INJECTION_COLLECTION = "org.eclipse.jetty.injectionCollection";
|
||||
private HashMap<String, List<Injection>> _injectionMap = new HashMap<String, List<Injection>>();//map of classname to injections
|
||||
|
||||
|
||||
public void add (Injection injection)
|
||||
{
|
||||
if ((injection==null) || injection.getTargetClassName()==null)
|
||||
if ((injection==null) || injection.getTargetClass()==null)
|
||||
return;
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Adding injection for class="+(injection.getTargetClassName()+ " on a "+(injection.isField()?injection.getFieldName():injection.getMethodName())));
|
||||
Log.debug("Adding injection for class="+(injection.getTargetClass()+ " on a "+(injection.getTarget().getName())));
|
||||
|
||||
|
||||
List<Injection> injections = (List<Injection>)_injectionMap.get(injection.getTargetClassName());
|
||||
List<Injection> injections = (List<Injection>)_injectionMap.get(injection.getTargetClass().getCanonicalName());
|
||||
if (injections==null)
|
||||
{
|
||||
injections = new ArrayList<Injection>();
|
||||
_injectionMap.put(injection.getTargetClassName(), injections);
|
||||
_injectionMap.put(injection.getTargetClass().getCanonicalName(), injections);
|
||||
}
|
||||
|
||||
injections.add(injection);
|
||||
}
|
||||
|
||||
|
@ -57,14 +59,15 @@ public class InjectionCollection
|
|||
|
||||
return _injectionMap.get(className);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Injection getInjection (String jndiName, String className, String fieldName)
|
||||
public Injection getInjection (String jndiName, Class clazz, Field field)
|
||||
{
|
||||
if (fieldName == null || className == null)
|
||||
if (field == null || clazz == null)
|
||||
return null;
|
||||
|
||||
List<Injection> injections = getInjections(className);
|
||||
List<Injection> injections = getInjections(clazz.getCanonicalName());
|
||||
if (injections == null)
|
||||
return null;
|
||||
Iterator<Injection> itor = injections.iterator();
|
||||
|
@ -72,19 +75,19 @@ public class InjectionCollection
|
|||
while (itor.hasNext() && injection == null)
|
||||
{
|
||||
Injection i = itor.next();
|
||||
if (fieldName.equals(i.getFieldName()))
|
||||
if (i.isField() && field.getName().equals(i.getTarget().getName()))
|
||||
injection = i;
|
||||
}
|
||||
|
||||
return injection;
|
||||
}
|
||||
|
||||
public Injection getInjection (String jndiName, String className, String methodName, String paramCanonicalName)
|
||||
public Injection getInjection (String jndiName, Class clazz, Method method, Class paramClass)
|
||||
{
|
||||
if (className == null || methodName == null || paramCanonicalName == null)
|
||||
if (clazz == null || method == null || paramClass == null)
|
||||
return null;
|
||||
|
||||
List<Injection> injections = getInjections(className);
|
||||
List<Injection> injections = getInjections(clazz.getCanonicalName());
|
||||
if (injections == null)
|
||||
return null;
|
||||
Iterator<Injection> itor = injections.iterator();
|
||||
|
@ -92,7 +95,7 @@ public class InjectionCollection
|
|||
while (itor.hasNext() && injection == null)
|
||||
{
|
||||
Injection i = itor.next();
|
||||
if (methodName.equals(i.getMethodName()) && paramCanonicalName.equals(i.getParamCanonicalName()))
|
||||
if (i.isMethod() && i.getTarget().getName().equals(method.getName()) && paramClass.equals(i.getParamClass()))
|
||||
injection = i;
|
||||
}
|
||||
|
||||
|
@ -101,7 +104,6 @@ public class InjectionCollection
|
|||
|
||||
|
||||
public void inject (Object injectable)
|
||||
throws Exception
|
||||
{
|
||||
if (injectable==null)
|
||||
return;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.plus.annotation;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
|
@ -93,8 +94,8 @@ public abstract class LifeCycleCallback
|
|||
|
||||
|
||||
|
||||
public void callback (Object instance)
|
||||
throws Exception
|
||||
public void callback (Object instance)
|
||||
throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
if (_target == null)
|
||||
{
|
||||
|
|
|
@ -101,14 +101,16 @@ public class LifeCycleCallbackCollection
|
|||
|
||||
Class clazz = o.getClass();
|
||||
List<LifeCycleCallback> callbacks = postConstructCallbacksMap.get(clazz.getName());
|
||||
|
||||
|
||||
if (callbacks == null)
|
||||
return;
|
||||
|
||||
|
||||
for (int i=0;i<callbacks.size();i++)
|
||||
{
|
||||
((LifeCycleCallback)callbacks.get(i)).callback(o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Call the method, if one exists, that is annotated with PreDestroy
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.plus.annotation;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
|
@ -45,8 +46,8 @@ public class PostConstructCallback extends LifeCycleCallback
|
|||
}
|
||||
|
||||
|
||||
public void callback (Object instance)
|
||||
throws Exception
|
||||
public void callback (Object instance)
|
||||
throws SecurityException, IllegalArgumentException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
super.callback(instance);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class RunAs
|
|||
}
|
||||
|
||||
|
||||
public void setRunAs (ServletHolder holder, SecurityHandler securityHandler)
|
||||
public void setRunAs (ServletHolder holder)
|
||||
throws ServletException
|
||||
{
|
||||
if (holder == null)
|
||||
|
@ -61,6 +61,11 @@ public class RunAs
|
|||
String className = holder.getClassName();
|
||||
|
||||
if (className.equals(_className))
|
||||
holder.setRunAsRole(_roleName);
|
||||
{
|
||||
//Only set the RunAs if it has not already been set, presumably by web/web-fragment.xml
|
||||
if (holder.getRegistration().getRunAsRole() == null)
|
||||
holder.getRegistration().setRunAsRole(_roleName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import javax.servlet.ServletException;
|
|||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -31,6 +32,7 @@ public class RunAsCollection
|
|||
{
|
||||
public static final String RUNAS_COLLECTION = "org.eclipse.jetty.runAsCollection";
|
||||
private HashMap _runAsMap = new HashMap();//map of classname to run-as
|
||||
|
||||
|
||||
|
||||
public void add (RunAs runAs)
|
||||
|
@ -49,32 +51,23 @@ public class RunAsCollection
|
|||
if (o==null)
|
||||
return null;
|
||||
|
||||
if (!(o instanceof ServletHolder))
|
||||
return null;
|
||||
|
||||
ServletHolder holder = (ServletHolder)o;
|
||||
|
||||
String className = holder.getClassName();
|
||||
return (RunAs)_runAsMap.get(className);
|
||||
return (RunAs)_runAsMap.get(o.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
public void setRunAs(Object o, SecurityHandler securityHandler)
|
||||
public void setRunAs(Object o)
|
||||
throws ServletException
|
||||
{
|
||||
if (o==null)
|
||||
if (o == null)
|
||||
return;
|
||||
|
||||
if (!(o instanceof ServletHolder))
|
||||
if (!ServletHolder.class.isAssignableFrom(o.getClass()))
|
||||
return;
|
||||
|
||||
ServletHolder holder = (ServletHolder)o;
|
||||
|
||||
String className = holder.getClassName();
|
||||
RunAs runAs = (RunAs)_runAsMap.get(className);
|
||||
|
||||
RunAs runAs = (RunAs)_runAsMap.get(o.getClass().getName());
|
||||
if (runAs == null)
|
||||
return;
|
||||
|
||||
runAs.setRunAs(holder, securityHandler);
|
||||
|
||||
runAs.setRunAs((ServletHolder)o);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -70,54 +70,5 @@ public class ServletHandler extends org.eclipse.jetty.servlet.ServletHandler
|
|||
this._injections = injections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletHandler#customizeFilter(javax.servlet.Filter)
|
||||
*/
|
||||
public Filter customizeFilter(Filter filter) throws Exception
|
||||
{
|
||||
if (_injections != null)
|
||||
_injections.inject(filter);
|
||||
|
||||
if (_callbacks != null)
|
||||
_callbacks.callPostConstructCallback(filter);
|
||||
return super.customizeFilter(filter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletHandler#customizeServlet(javax.servlet.Servlet)
|
||||
*/
|
||||
public Servlet customizeServlet(Servlet servlet) throws Exception
|
||||
{
|
||||
if (_injections != null)
|
||||
_injections.inject(servlet);
|
||||
if (_callbacks != null)
|
||||
_callbacks.callPostConstructCallback(servlet);
|
||||
return super.customizeServlet(servlet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletHandler#customizeFilterDestroy(Filter)
|
||||
*/
|
||||
public Filter customizeFilterDestroy(Filter filter) throws Exception
|
||||
{
|
||||
if (_callbacks != null)
|
||||
_callbacks.callPreDestroyCallback(filter);
|
||||
return super.customizeFilterDestroy(filter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletHandler#customizeServletDestroy(Servlet)
|
||||
*/
|
||||
public Servlet customizeServletDestroy(Servlet servlet) throws Exception
|
||||
{
|
||||
if (_callbacks != null)
|
||||
_callbacks.callPreDestroyCallback(servlet);
|
||||
return super.customizeServletDestroy(servlet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,508 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.plus.webapp;
|
||||
|
||||
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.UnavailableException;
|
||||
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.plus.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor.Descriptor;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractConfiguration implements Configuration
|
||||
{
|
||||
public abstract void bindEnvEntry (WebAppContext context, String name, Object value) throws Exception;
|
||||
|
||||
public abstract void bindResourceRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
public abstract void bindResourceEnvRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
public abstract void bindUserTransaction (WebAppContext context) throws Exception;
|
||||
|
||||
public abstract void bindMessageDestinationRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
|
||||
public class PlusWebXmlProcessor
|
||||
{
|
||||
WebAppContext _context;
|
||||
|
||||
public PlusWebXmlProcessor (WebAppContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public void process (Descriptor d)
|
||||
throws Exception
|
||||
{
|
||||
if (d != null)
|
||||
process(d.getRoot());
|
||||
}
|
||||
|
||||
public void process (XmlParser.Node root)
|
||||
throws Exception
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
|
||||
Iterator iter = root.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
String name = node.getTag();
|
||||
initWebXmlElement(name, node);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Configuration problem at " + node, e);
|
||||
throw new UnavailableException("Configuration problem");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initWebXmlElement(String element,XmlParser.Node node) throws Exception
|
||||
{
|
||||
if ("env-entry".equals(element))
|
||||
{
|
||||
initEnvEntry (node);
|
||||
}
|
||||
else if ("resource-ref".equals(element))
|
||||
{
|
||||
//resource-ref entries are ONLY for connection factories
|
||||
//the resource-ref says how the app will reference the jndi lookup relative
|
||||
//to java:comp/env, but it is up to the deployer to map this reference to
|
||||
//a real resource in the environment. At the moment, we insist that the
|
||||
//jetty.xml file name of the resource has to be exactly the same as the
|
||||
//name in web.xml deployment descriptor, but it shouldn't have to be
|
||||
initResourceRef(node);
|
||||
}
|
||||
else if ("resource-env-ref".equals(element))
|
||||
{
|
||||
//resource-env-ref elements are a non-connection factory type of resource
|
||||
//the app looks them up relative to java:comp/env
|
||||
//again, need a way for deployer to link up app naming to real naming.
|
||||
//Again, we insist now that the name of the resource in jetty.xml is
|
||||
//the same as web.xml
|
||||
initResourceEnvRef(node);
|
||||
}
|
||||
else if ("message-destination-ref".equals(element))
|
||||
{
|
||||
initMessageDestinationRef(node);
|
||||
}
|
||||
else if ("post-construct".equals(element))
|
||||
{
|
||||
//post-construct is the name of a class and method to call after all
|
||||
//resources have been setup but before the class is put into use
|
||||
initPostConstruct(node);
|
||||
}
|
||||
else if ("pre-destroy".equals(element))
|
||||
{
|
||||
//pre-destroy is the name of a class and method to call just as
|
||||
//the instance is being destroyed
|
||||
initPreDestroy(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JavaEE 5.4.1.3
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initEnvEntry (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String name=node.getString("env-entry-name",false,true);
|
||||
String type = node.getString("env-entry-type",false,true);
|
||||
String valueStr = node.getString("env-entry-value",false,true);
|
||||
|
||||
//if there's no value there's no point in making a jndi entry
|
||||
//nor processing injection entries
|
||||
if (valueStr==null || valueStr.equals(""))
|
||||
{
|
||||
Log.warn("No value for env-entry-name "+name);
|
||||
return;
|
||||
}
|
||||
|
||||
//the javaee_5.xsd says that the env-entry-type is optional
|
||||
//if there is an <injection> element, because you can get
|
||||
//type from the element, but what to do if there is more
|
||||
//than one <injection> element, do you just pick the type
|
||||
//of the first one?
|
||||
|
||||
//check for <injection> elements
|
||||
initInjection (node, name, TypeUtil.fromName(type));
|
||||
|
||||
//bind the entry into jndi
|
||||
Object value = TypeUtil.valueOf(type,valueStr);
|
||||
bindEnvEntry(_context, name, value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-ref is for:
|
||||
* - javax.sql.DataSource
|
||||
* - javax.jms.ConnectionFactory
|
||||
* - javax.jms.QueueConnectionFactory
|
||||
* - javax.jms.TopicConnectionFactory
|
||||
* - javax.mail.Session
|
||||
* - java.net.URL
|
||||
* - javax.resource.cci.ConnectionFactory
|
||||
* - org.omg.CORBA_2_3.ORB
|
||||
* - any other connection factory defined by a resource adapter
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("res-ref-name",false,true);
|
||||
String type = node.getString("res-type", false, true);
|
||||
String auth = node.getString("res-auth", false, true);
|
||||
String shared = node.getString("res-sharing-scope", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-env-ref is for:
|
||||
* - javax.transaction.UserTransaction
|
||||
* - javax.resource.cci.InteractionSpec
|
||||
* - anything else that is not a connection factory
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceEnvRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("resource-env-ref-name",false,true);
|
||||
String type = node.getString("resource-env-ref-type", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
|
||||
//JavaEE Spec sec 5.7.1.3 says the resource-env-ref-type
|
||||
//is mandatory, but the schema says it is optional!
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceEnvRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* message-destination-ref is for:
|
||||
* - javax.jms.Queue
|
||||
* - javax.jms.Topic
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initMessageDestinationRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("message-destination-ref-name",false,true);
|
||||
String type = node.getString("message-destination-type",false,true);
|
||||
String usage = node.getString("message-destination-usage",false,true);
|
||||
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection(node, jndiName, typeClass);
|
||||
|
||||
bindMessageDestinationRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process <post-construct>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPostConstruct(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for class "+className);
|
||||
return;
|
||||
}
|
||||
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process <pre-destroy>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPreDestroy(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified for pre-destroy");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
|
||||
return;
|
||||
}
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the <injection-target> entries for a node
|
||||
*
|
||||
* @param node
|
||||
* @param jndiName
|
||||
* @param valueClass
|
||||
*/
|
||||
protected void initInjection (XmlParser.Node node, String jndiName, Class valueClass)
|
||||
{
|
||||
Iterator itor = node.iterator("injection-target");
|
||||
|
||||
while(itor.hasNext())
|
||||
{
|
||||
XmlParser.Node injectionNode = (XmlParser.Node)itor.next();
|
||||
String targetClassName = injectionNode.getString("injection-target-class", false, true);
|
||||
String targetName = injectionNode.getString("injection-target-name", false, true);
|
||||
if ((targetClassName==null) || targetClassName.equals(""))
|
||||
{
|
||||
Log.warn("No classname found in injection-target");
|
||||
continue;
|
||||
}
|
||||
if ((targetName==null) || targetName.equals(""))
|
||||
{
|
||||
Log.warn("No field or method name in injection-target");
|
||||
continue;
|
||||
}
|
||||
|
||||
InjectionCollection injections = (InjectionCollection)_context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
// comments in the javaee_5.xsd file specify that the targetName is looked
|
||||
// for first as a java bean property, then if that fails, as a field
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(targetClassName);
|
||||
Injection injection = new Injection();
|
||||
injection.setJndiName(jndiName);
|
||||
injection.setTarget(clazz, targetName, valueClass);
|
||||
injections.add(injection);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load injection target class "+targetClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void preConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
//set up our special ServletHandler to remember injections and lifecycle callbacks
|
||||
ServletHandler servletHandler = new ServletHandler();
|
||||
SecurityHandler securityHandler = context.getSecurityHandler();
|
||||
org.eclipse.jetty.servlet.ServletHandler existingHandler = context.getServletHandler();
|
||||
servletHandler.setFilters(existingHandler.getFilters());
|
||||
servletHandler.setFilterMappings(existingHandler.getFilterMappings());
|
||||
servletHandler.setServlets(existingHandler.getServlets());
|
||||
servletHandler.setServletMappings(existingHandler.getServletMappings());
|
||||
context.setServletHandler(servletHandler);
|
||||
securityHandler.setHandler(servletHandler);
|
||||
|
||||
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
|
||||
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, callbacks);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
context.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
RunAsCollection runAsCollection = new RunAsCollection();
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, null);
|
||||
context.setAttribute(InjectionCollection.INJECTION_COLLECTION, null);
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, null);
|
||||
}
|
||||
|
||||
public void configure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
bindUserTransaction(context);
|
||||
|
||||
WebXmlProcessor webXmlProcessor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (webXmlProcessor == null)
|
||||
throw new IllegalStateException ("No processor for web xml");
|
||||
|
||||
//TODO: When webdefaults.xml, web.xml, fragments and web-override.xml are merged into an effective web.xml this
|
||||
//will change
|
||||
PlusWebXmlProcessor plusProcessor = new PlusWebXmlProcessor(context);
|
||||
plusProcessor.process(webXmlProcessor.getWebDefault());
|
||||
plusProcessor.process(webXmlProcessor.getWebXml());
|
||||
|
||||
//Process plus-elements of each descriptor
|
||||
for (Descriptor frag: webXmlProcessor.getFragments())
|
||||
{
|
||||
plusProcessor.process(frag);
|
||||
}
|
||||
|
||||
//process the override-web.xml descriptor
|
||||
plusProcessor.process(webXmlProcessor.getOverrideWeb());
|
||||
|
||||
|
||||
//configure injections and callbacks to be called by the FilterHolder and ServletHolder
|
||||
//when they lazily instantiate the Filter/Servlet.
|
||||
((ServletHandler)context.getServletHandler()).setInjections((InjectionCollection)context.getAttribute(InjectionCollection.INJECTION_COLLECTION));
|
||||
((ServletHandler)context.getServletHandler()).setCallbacks((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
|
||||
|
||||
//do any injects on the listeners that were created and then
|
||||
//also callback any postConstruct lifecycle methods
|
||||
injectAndCallPostConstructCallbacks(context);
|
||||
}
|
||||
|
||||
public void deconfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
//call any preDestroy methods on the listeners
|
||||
callPreDestroyCallbacks(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void injectAndCallPostConstructCallbacks(WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
InjectionCollection injections = (InjectionCollection)context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
RunAsCollection runAsCollection = (RunAsCollection)context.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
SecurityHandler securityHandler = context.getSecurityHandler();
|
||||
|
||||
//look thru the servlets to apply any runAs annotations
|
||||
//NOTE: that any run-as in web.xml will already have been applied
|
||||
if (runAsCollection != null)
|
||||
{
|
||||
ServletHolder[] holders = context.getServletHandler().getServlets();
|
||||
for (int i=0;holders!=null && i<holders.length;i++)
|
||||
{
|
||||
runAsCollection.setRunAs(holders[i], securityHandler);
|
||||
}
|
||||
}
|
||||
|
||||
EventListener[] listeners = context.getEventListeners();
|
||||
for (int i=0;listeners!=null && i<listeners.length;i++)
|
||||
{
|
||||
if (injections != null)
|
||||
injections.inject(listeners[i]);
|
||||
if (callbacks != null)
|
||||
callbacks.callPostConstructCallback(listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void callPreDestroyCallbacks (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
|
||||
if (callbacks != null)
|
||||
{
|
||||
EventListener[] listeners = context.getEventListeners();
|
||||
for (int i=0; listeners!=null && i<listeners.length;i++)
|
||||
{
|
||||
callbacks.callPreDestroyCallback(listeners[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,14 +19,14 @@ import javax.naming.Context;
|
|||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
|
||||
import org.eclipse.jetty.jndi.NamingUtil;
|
||||
import org.eclipse.jetty.plus.jndi.EnvEntry;
|
||||
import org.eclipse.jetty.plus.jndi.Link;
|
||||
import org.eclipse.jetty.plus.jndi.NamingEntry;
|
||||
import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.plus.jndi.Transaction;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.FragmentDescriptor;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -34,80 +34,71 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public class Configuration extends AbstractConfiguration
|
||||
public class Configuration implements org.eclipse.jetty.webapp.Configuration
|
||||
{
|
||||
|
||||
private Integer _key;
|
||||
|
||||
|
||||
/**
|
||||
* @see AbstractConfiguration#bindEnvEntry(WebAppContext, String, Object)
|
||||
* @param name
|
||||
* @param value
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindEnvEntry(WebAppContext context, String name, Object value) throws Exception
|
||||
{
|
||||
InitialContext ic = null;
|
||||
boolean bound = false;
|
||||
//check to see if we bound a value and an EnvEntry with this name already
|
||||
//when we processed the server and the webapp's naming environment
|
||||
//@see EnvConfiguration.bindEnvEntries()
|
||||
ic = new InitialContext();
|
||||
try
|
||||
{
|
||||
NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntryUtil.makeNamingEntryName(ic.getNameParser(""), name));
|
||||
if (ne!=null && ne instanceof EnvEntry)
|
||||
{
|
||||
EnvEntry ee = (EnvEntry)ne;
|
||||
bound = ee.isOverrideWebXml();
|
||||
}
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
|
||||
if (!bound)
|
||||
{
|
||||
//either nothing was bound or the value from web.xml should override
|
||||
Context envCtx = (Context)ic.lookup("java:comp/env");
|
||||
NamingUtil.bind(envCtx, name, value);
|
||||
}
|
||||
public void preConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
|
||||
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, callbacks);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
context.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
RunAsCollection runAsCollection = new RunAsCollection();
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
|
||||
WebAppDecorator decorator = new WebAppDecorator(context);
|
||||
context.setDecorator(decorator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bind a resource reference.
|
||||
*
|
||||
* If a resource reference with the same name is in a jetty-env.xml
|
||||
* file, it will already have been bound.
|
||||
*
|
||||
* @see AbstractConfiguration#bindResourceRef(WebAppContext, String, Class)
|
||||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceRef(WebAppContext context, String name, Class typeClass)
|
||||
public void configure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(context, name, typeClass);
|
||||
}
|
||||
bindUserTransaction(context);
|
||||
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException ("No metadata");
|
||||
|
||||
metaData.addDescriptorProcessor(new PlusDescriptorProcessor());
|
||||
|
||||
/*
|
||||
* THE PROCESSING IS NOW DONE IN metadata.resolve ()
|
||||
|
||||
PlusDescriptorProcessor plusProcessor = new PlusDescriptorProcessor(metaData);
|
||||
plusProcessor.process(metaData.getWebDefault());
|
||||
plusProcessor.process(metaData.getWebXml());
|
||||
|
||||
|
||||
/**
|
||||
* @see AbstractConfiguration#bindResourceEnvRef(WebAppContext, String, Class)
|
||||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceEnvRef(WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(context, name, typeClass);
|
||||
//Process plus-elements of each descriptor
|
||||
for (FragmentDescriptor frag: metaData.getOrderedFragments())
|
||||
{
|
||||
plusProcessor.process(frag);
|
||||
}
|
||||
|
||||
//process the override-web.xml descriptor
|
||||
plusProcessor.process(metaData.getOverrideWeb());
|
||||
*/
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
//lock this webapp's java:comp namespace as per J2EE spec
|
||||
lockCompEnv(context);
|
||||
|
||||
public void bindMessageDestinationRef(WebAppContext context, String name, Class typeClass)
|
||||
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, null);
|
||||
context.setAttribute(InjectionCollection.INJECTION_COLLECTION, null);
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, null);
|
||||
}
|
||||
|
||||
public void deconfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(context, name, typeClass);
|
||||
unlockCompEnv(context);
|
||||
_key = null;
|
||||
}
|
||||
|
||||
public void bindUserTransaction (WebAppContext context)
|
||||
|
@ -123,40 +114,8 @@ public class Configuration extends AbstractConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
public void preConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.preConfigure(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void configure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.configure (context);
|
||||
}
|
||||
|
||||
public void postConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
//lock this webapp's java:comp namespace as per J2EE spec
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
lockCompEnv(context);
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
|
||||
public void deconfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
unlockCompEnv(context);
|
||||
_key = null;
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
super.deconfigure (context);
|
||||
}
|
||||
|
||||
protected void lockCompEnv (WebAppContext wac)
|
||||
throws Exception
|
||||
{
|
||||
|
@ -180,86 +139,20 @@ public class Configuration extends AbstractConfiguration
|
|||
throws Exception
|
||||
{
|
||||
if (_key!=null)
|
||||
{ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
|
||||
try
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup("java:comp");
|
||||
compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
|
||||
|
||||
/**
|
||||
* Bind a resource with the given name from web.xml of the given type
|
||||
* with a jndi resource from either the server or the webapp's naming
|
||||
* environment.
|
||||
*
|
||||
* As the servlet spec does not cover the mapping of names in web.xml with
|
||||
* names from the execution environment, jetty uses the concept of a Link, which is
|
||||
* a subclass of the NamingEntry class. A Link defines a mapping of a name
|
||||
* from web.xml with a name from the execution environment (ie either the server or the
|
||||
* webapp's naming environment).
|
||||
*
|
||||
* @param name name of the resource from web.xml
|
||||
* @param typeClass
|
||||
* @throws Exception
|
||||
*/
|
||||
private void bindEntry (WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
String nameInEnvironment = name;
|
||||
boolean bound = false;
|
||||
|
||||
//check if the name in web.xml has been mapped to something else
|
||||
//check a context-specific naming environment first
|
||||
Object scope = context;
|
||||
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
|
||||
|
||||
if (ne!=null && (ne instanceof Link))
|
||||
{
|
||||
//if we found a mapping, get out name it is mapped to in the environment
|
||||
nameInEnvironment = (String)((Link)ne).getObjectToBind();
|
||||
Link l = (Link)ne;
|
||||
try
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup("java:comp");
|
||||
compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
|
||||
//try finding that mapped name in the webapp's environment first
|
||||
scope = context;
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//try the server's environment
|
||||
scope = context.getServer();
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//try the jvm environment
|
||||
bound = NamingEntryUtil.bindToENC(null, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//There is no matching resource so try a default name.
|
||||
//The default name syntax is: the [res-type]/default
|
||||
//eg javax.sql.DataSource/default
|
||||
nameInEnvironment = typeClass.getName()+"/default";
|
||||
//First try the server scope
|
||||
NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(context.getServer(), nameInEnvironment);
|
||||
if (defaultNE==null)
|
||||
defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
|
||||
|
||||
if (defaultNE!=null)
|
||||
defaultNE.bindToENC(name);
|
||||
else
|
||||
throw new IllegalStateException("Nothing to bind for name "+nameInEnvironment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,778 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.plus.webapp;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
|
||||
import org.eclipse.jetty.jndi.NamingUtil;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||
import org.eclipse.jetty.plus.jndi.EnvEntry;
|
||||
import org.eclipse.jetty.plus.jndi.Link;
|
||||
import org.eclipse.jetty.plus.jndi.NamingEntry;
|
||||
import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.Descriptor;
|
||||
import org.eclipse.jetty.webapp.FragmentDescriptor;
|
||||
import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.eclipse.jetty.webapp.MetaData.Origin;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
/**
|
||||
* PlusDescriptorProcessor
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
|
||||
{
|
||||
protected WebAppContext _context;
|
||||
protected MetaData _metaData;
|
||||
|
||||
public PlusDescriptorProcessor ()
|
||||
{
|
||||
try
|
||||
{
|
||||
registerVisitor("env-entry", getClass().getDeclaredMethod("visitEnvEntry", __signature));
|
||||
registerVisitor("resource-ref", getClass().getDeclaredMethod("visitResourceRef", __signature));
|
||||
registerVisitor("resource-env-ref", getClass().getDeclaredMethod("visitResourceEnvRef", __signature));
|
||||
registerVisitor("message-destination-ref", getClass().getDeclaredMethod("visitMessageDestinationRef", __signature));
|
||||
registerVisitor("post-construct", getClass().getDeclaredMethod("visitPostConstruct", __signature));
|
||||
registerVisitor("pre-destroy", getClass().getDeclaredMethod("visitPreDestroy", __signature));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#start(org.eclipse.jetty.webapp.Descriptor)
|
||||
*/
|
||||
public void start(Descriptor descriptor)
|
||||
{
|
||||
_metaData = descriptor.getMetaData();
|
||||
_context = _metaData.getContext();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#end(org.eclipse.jetty.webapp.Descriptor)
|
||||
*/
|
||||
public void end(Descriptor descriptor)
|
||||
{
|
||||
_metaData = null;
|
||||
_context = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JavaEE 5.4.1.3
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
public void visitEnvEntry (Descriptor descriptor, XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String name=node.getString("env-entry-name",false,true);
|
||||
String type = node.getString("env-entry-type",false,true);
|
||||
String valueStr = node.getString("env-entry-value",false,true);
|
||||
|
||||
//if there's no value there's no point in making a jndi entry
|
||||
//nor processing injection entries
|
||||
if (valueStr==null || valueStr.equals(""))
|
||||
{
|
||||
Log.warn("No value for env-entry-name "+name);
|
||||
return;
|
||||
}
|
||||
|
||||
Origin o = _metaData.getOrigin("env-entry."+name);
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//no descriptor has configured an env-entry of this name previously
|
||||
_metaData.setOrigin("env-entry."+name, descriptor);
|
||||
//the javaee_5.xsd says that the env-entry-type is optional
|
||||
//if there is an <injection> element, because you can get
|
||||
//type from the element, but what to do if there is more
|
||||
//than one <injection> element, do you just pick the type
|
||||
//of the first one?
|
||||
addInjections (descriptor, node, name, TypeUtil.fromName(type));
|
||||
Object value = TypeUtil.valueOf(type,valueStr);
|
||||
bindEnvEntry(name, value);
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//ServletSpec 3.0 p75. web.xml (or web-override/web-defaults) declared
|
||||
//the env-entry. A fragment is not allowed to change that, except unless
|
||||
//the web.xml did not declare any injections.
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
//We're processing web-defaults, web.xml or web-override. Any of them can
|
||||
//set or change the env-entry.
|
||||
_metaData.setOrigin("env-entry."+name, descriptor);
|
||||
addInjections (descriptor, node, name, TypeUtil.fromName(type));
|
||||
Object value = TypeUtil.valueOf(type,valueStr);
|
||||
bindEnvEntry(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//A web.xml declared the env-entry. Check to see if any injections have been
|
||||
//declared for it. If it was declared in web.xml then don't merge any injections.
|
||||
//If it was declared in a web-fragment, then we can keep merging fragments.
|
||||
Descriptor d = _metaData.getOriginDescriptor("env-entry."+name+".injection");
|
||||
if (d==null || d instanceof FragmentDescriptor)
|
||||
addInjections(descriptor, node, name, TypeUtil.fromName(type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//ServletSpec p.75. No declaration in web.xml, but in multiple web-fragments. Error.
|
||||
throw new IllegalStateException("Conflicting env-entry "+name+" in "+descriptor.getResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-ref is for:
|
||||
* - javax.sql.DataSource
|
||||
* - javax.jms.ConnectionFactory
|
||||
* - javax.jms.QueueConnectionFactory
|
||||
* - javax.jms.TopicConnectionFactory
|
||||
* - javax.mail.Session
|
||||
* - java.net.URL
|
||||
* - javax.resource.cci.ConnectionFactory
|
||||
* - org.omg.CORBA_2_3.ORB
|
||||
* - any other connection factory defined by a resource adapter
|
||||
*
|
||||
* TODO
|
||||
* If web.xml contains a resource-ref with injection targets, all resource-ref entries
|
||||
* of the same name are ignored in web fragments. If web.xml does not contain any
|
||||
* injection-targets, then they are merged from all the fragments.
|
||||
* If web.xml does not contain a resource-ref element of same name, but 2 fragments
|
||||
* declare the same name it is an error.
|
||||
* resource-ref entries are ONLY for connection factories
|
||||
* the resource-ref says how the app will reference the jndi lookup relative
|
||||
* to java:comp/env, but it is up to the deployer to map this reference to
|
||||
* a real resource in the environment. At the moment, we insist that the
|
||||
* jetty.xml file name of the resource has to be exactly the same as the
|
||||
* name in web.xml deployment descriptor, but it shouldn't have to be
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
public void visitResourceRef (Descriptor descriptor, XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("res-ref-name",false,true);
|
||||
String type = node.getString("res-type", false, true);
|
||||
String auth = node.getString("res-auth", false, true);
|
||||
String shared = node.getString("res-sharing-scope", false, true);
|
||||
|
||||
Origin o = _metaData.getOrigin("resource-ref."+jndiName);
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//No descriptor or annotation previously declared a resource-ref of this name.
|
||||
_metaData.setOrigin("resource-ref."+jndiName, descriptor);
|
||||
|
||||
//check for <injection> elements
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections(descriptor, node, jndiName, typeClass);
|
||||
bindResourceRef(jndiName, typeClass);
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//A web xml previously declared the resource-ref.
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
//We're processing web-defaults, web.xml or web-override. Any of them can
|
||||
//set or change the resource-ref.
|
||||
_metaData.setOrigin("resource-ref."+jndiName, descriptor);
|
||||
|
||||
//check for <injection> elements
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
|
||||
addInjections(descriptor, node, jndiName, typeClass);
|
||||
|
||||
//bind the entry into jndi
|
||||
bindResourceRef(jndiName, typeClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
//A web xml declared the resource-ref and we're processing a
|
||||
//web-fragment. Check to see if any injections were declared for it by web.xml.
|
||||
//If any injection was declared in web.xml then don't merge any injections.
|
||||
//If it was declared in a web-fragment, then we can keep merging fragments.
|
||||
Descriptor d = _metaData.getOriginDescriptor("resource-ref."+jndiName+".injection");
|
||||
if (d==null || d instanceof FragmentDescriptor)
|
||||
{
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections(descriptor, node, jndiName, TypeUtil.fromName(type));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//ServletSpec p.75. No declaration of resource-ref in web xml, but in multiple web-fragments. Error.
|
||||
throw new IllegalStateException("Conflicting resource-ref "+jndiName+" in "+descriptor.getResource());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-env-ref is for:
|
||||
* - javax.transaction.UserTransaction
|
||||
* - javax.resource.cci.InteractionSpec
|
||||
* - anything else that is not a connection factory
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
public void visitResourceEnvRef (Descriptor descriptor, XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("resource-env-ref-name",false,true);
|
||||
String type = node.getString("resource-env-ref-type", false, true);
|
||||
|
||||
Origin o = _metaData.getOrigin("resource-env-ref."+jndiName);
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//First declaration of resource-env-ref with this jndiName
|
||||
//JavaEE Spec sec 5.7.1.3 says the resource-env-ref-type
|
||||
//is mandatory, but the schema says it is optional!
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections (descriptor, node, jndiName, typeClass);
|
||||
bindResourceEnvRef(jndiName, typeClass);
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//A resource-env-ref of this name has been declared first in a web xml.
|
||||
//Only allow other web-default, web.xml, web-override to change it.
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
//We're processing web-defaults, web.xml or web-override. Any of them can
|
||||
//set or change the resource-env-ref.
|
||||
_metaData.setOrigin("resource-env-ref."+jndiName, descriptor);
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections (descriptor, node, jndiName, typeClass);
|
||||
bindResourceEnvRef(jndiName, typeClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
//We're processing a web-fragment. It can only contribute injections if the
|
||||
//there haven't been any injections declared yet, or they weren't declared in a WebXml file.
|
||||
Descriptor d = _metaData.getOriginDescriptor("resource-env-ref."+jndiName+".injection");
|
||||
if (d == null || d instanceof FragmentDescriptor)
|
||||
{
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections (descriptor, node, jndiName, typeClass);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//ServletSpec p.75. No declaration of resource-env-ref in web xml, but in multiple web-fragments. Error.
|
||||
throw new IllegalStateException("Conflicting resource-env-ref "+jndiName+" in "+descriptor.getResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* message-destination-ref is for:
|
||||
* - javax.jms.Queue
|
||||
* - javax.jms.Topic
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
public void visitMessageDestinationRef (Descriptor descriptor, XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("message-destination-ref-name",false,true);
|
||||
String type = node.getString("message-destination-type",false,true);
|
||||
String usage = node.getString("message-destination-usage",false,true);
|
||||
|
||||
Origin o = _metaData.getOrigin("message-destination-ref."+jndiName);
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//A message-destination-ref of this name has not been previously declared
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections(descriptor, node, jndiName, typeClass);
|
||||
bindMessageDestinationRef(jndiName, typeClass);
|
||||
_metaData.setOrigin("message-destination-ref."+jndiName, descriptor);
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//A message-destination-ref of this name has been declared first in a web xml.
|
||||
//Only allow other web-default, web.xml, web-override to change it.
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections(descriptor, node, jndiName, typeClass);
|
||||
bindMessageDestinationRef(jndiName, typeClass);
|
||||
_metaData.setOrigin("message-destination-ref."+jndiName, descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
//A web-fragment has declared a message-destination-ref with the same name as a web xml.
|
||||
//It can only contribute injections, and only if the web xml didn't declare any.
|
||||
Descriptor d = _metaData.getOriginDescriptor("message-destination-ref."+jndiName+".injection");
|
||||
if (d == null || d instanceof FragmentDescriptor)
|
||||
{
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
addInjections(descriptor, node, jndiName, typeClass);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//ServletSpec p.75. No declaration of message-destination-ref in web xml, but in multiple web-fragments. Error.
|
||||
throw new IllegalStateException("Conflicting message-destination-ref "+jndiName+" in "+descriptor.getResource());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO
|
||||
* If web.xml has at least 1 post-construct, then all post-constructs in fragments
|
||||
* are ignored. Otherwise, post-constructs from fragments are merged.
|
||||
* post-construct is the name of a class and method to call after all
|
||||
* resources have been setup but before the class is put into use
|
||||
* @param node
|
||||
*/
|
||||
public void visitPostConstruct(Descriptor descriptor, XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for class "+className);
|
||||
return;
|
||||
}
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
//ServletSpec 3.0 p80 If web.xml declares a post-construct then all post-constructs
|
||||
//in fragments must be ignored. Otherwise, they are additive.
|
||||
Origin o = _metaData.getOrigin("post-construct");
|
||||
switch (o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//No post-constructs have been declared previously.
|
||||
_metaData.setOrigin("post-construct", descriptor);
|
||||
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//A web xml first declared a post-construct. Only allow other web xml files (web-defaults, web-overrides etc)
|
||||
//to add to it
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//A web-fragment first declared a post-construct. Allow all other web-fragments to merge in their post-constructs
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* pre-destroy is the name of a class and method to call just as
|
||||
* the instance is being destroyed
|
||||
* @param node
|
||||
*/
|
||||
public void visitPreDestroy(Descriptor descriptor, XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified for pre-destroy");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
|
||||
return;
|
||||
}
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
|
||||
Origin o = _metaData.getOrigin("pre-destroy");
|
||||
switch(o)
|
||||
{
|
||||
case NotSet:
|
||||
{
|
||||
//No pre-destroys have been declared previously. Record this descriptor
|
||||
//as the first declarer.
|
||||
_metaData.setOrigin("pre-destroy", descriptor);
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebXml:
|
||||
case WebDefaults:
|
||||
case WebOverride:
|
||||
{
|
||||
//A web xml file previously declared a pre-destroy. Only allow other web xml files
|
||||
//(not web-fragments) to add to them.
|
||||
if (!(descriptor instanceof FragmentDescriptor))
|
||||
{
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebFragment:
|
||||
{
|
||||
//No pre-destroys in web xml, so allow all fragments to merge their pre-destroys.
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the <injection-target> entries for a node
|
||||
*
|
||||
* @param descriptor
|
||||
* @param node
|
||||
* @param jndiName
|
||||
* @param valueClass
|
||||
* @return
|
||||
*/
|
||||
public void addInjections (Descriptor descriptor, XmlParser.Node node, String jndiName, Class valueClass)
|
||||
{
|
||||
Iterator itor = node.iterator("injection-target");
|
||||
|
||||
while(itor.hasNext())
|
||||
{
|
||||
XmlParser.Node injectionNode = (XmlParser.Node)itor.next();
|
||||
String targetClassName = injectionNode.getString("injection-target-class", false, true);
|
||||
String targetName = injectionNode.getString("injection-target-name", false, true);
|
||||
if ((targetClassName==null) || targetClassName.equals(""))
|
||||
{
|
||||
Log.warn("No classname found in injection-target");
|
||||
continue;
|
||||
}
|
||||
if ((targetName==null) || targetName.equals(""))
|
||||
{
|
||||
Log.warn("No field or method name in injection-target");
|
||||
continue;
|
||||
}
|
||||
|
||||
InjectionCollection injections = (InjectionCollection)_context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
// comments in the javaee_5.xsd file specify that the targetName is looked
|
||||
// for first as a java bean property, then if that fails, as a field
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(targetClassName);
|
||||
Injection injection = new Injection();
|
||||
injection.setJndiName(jndiName);
|
||||
injection.setTarget(clazz, targetName, valueClass);
|
||||
injections.add(injection);
|
||||
|
||||
//Record which was the first descriptor to declare an injection for this name
|
||||
if (_metaData.getOriginDescriptor(node.getTag()+"."+jndiName+".injection") == null)
|
||||
_metaData.setOrigin(node.getTag()+"."+jndiName+".injection", descriptor);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load injection target class "+targetClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindEnvEntry(java.lang.String, java.lang.String)
|
||||
* @param name
|
||||
* @param value
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindEnvEntry(String name, Object value) throws Exception
|
||||
{
|
||||
InitialContext ic = null;
|
||||
boolean bound = false;
|
||||
//check to see if we bound a value and an EnvEntry with this name already
|
||||
//when we processed the server and the webapp's naming environment
|
||||
//@see EnvConfiguration.bindEnvEntries()
|
||||
ic = new InitialContext();
|
||||
try
|
||||
{
|
||||
NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntryUtil.makeNamingEntryName(ic.getNameParser(""), name));
|
||||
if (ne!=null && ne instanceof EnvEntry)
|
||||
{
|
||||
EnvEntry ee = (EnvEntry)ne;
|
||||
bound = ee.isOverrideWebXml();
|
||||
}
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
|
||||
if (!bound)
|
||||
{
|
||||
//either nothing was bound or the value from web.xml should override
|
||||
Context envCtx = (Context)ic.lookup("java:comp/env");
|
||||
NamingUtil.bind(envCtx, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a resource reference.
|
||||
*
|
||||
* If a resource reference with the same name is in a jetty-env.xml
|
||||
* file, it will already have been bound.
|
||||
*
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindResourceRef(java.lang.String)
|
||||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceRef(String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindResourceEnvRef(java.lang.String)
|
||||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceEnvRef(String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
}
|
||||
|
||||
|
||||
public void bindMessageDestinationRef(String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind a resource with the given name from web.xml of the given type
|
||||
* with a jndi resource from either the server or the webapp's naming
|
||||
* environment.
|
||||
*
|
||||
* As the servlet spec does not cover the mapping of names in web.xml with
|
||||
* names from the execution environment, jetty uses the concept of a Link, which is
|
||||
* a subclass of the NamingEntry class. A Link defines a mapping of a name
|
||||
* from web.xml with a name from the execution environment (ie either the server or the
|
||||
* webapp's naming environment).
|
||||
*
|
||||
* @param name name of the resource from web.xml
|
||||
* @param typeClass
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void bindEntry (String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
String nameInEnvironment = name;
|
||||
boolean bound = false;
|
||||
|
||||
//check if the name in web.xml has been mapped to something else
|
||||
//check a context-specific naming environment first
|
||||
Object scope = _context;
|
||||
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
|
||||
|
||||
if (ne!=null && (ne instanceof Link))
|
||||
{
|
||||
//if we found a mapping, get out name it is mapped to in the environment
|
||||
nameInEnvironment = (String)((Link)ne).getObjectToBind();
|
||||
Link l = (Link)ne;
|
||||
}
|
||||
|
||||
//try finding that mapped name in the webapp's environment first
|
||||
scope = _context;
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//try the server's environment
|
||||
scope = _context.getServer();
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//try the jvm environment
|
||||
bound = NamingEntryUtil.bindToENC(null, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
//There is no matching resource so try a default name.
|
||||
//The default name syntax is: the [res-type]/default
|
||||
//eg javax.sql.DataSource/default
|
||||
nameInEnvironment = typeClass.getName()+"/default";
|
||||
//First try the server scope
|
||||
NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(_context.getServer(), nameInEnvironment);
|
||||
if (defaultNE==null)
|
||||
defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
|
||||
|
||||
if (defaultNE!=null)
|
||||
defaultNE.bindToENC(name);
|
||||
else
|
||||
throw new IllegalStateException("Nothing to bind for name "+nameInEnvironment);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.plus.webapp;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.Holder;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler.Decorator;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* WebAppDecorator
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class WebAppDecorator implements Decorator
|
||||
{
|
||||
private WebAppContext _wac;
|
||||
|
||||
public WebAppDecorator (WebAppContext context)
|
||||
{
|
||||
_wac = context;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterHolder(org.eclipse.jetty.servlet.FilterHolder)
|
||||
*/
|
||||
public void decorateFilterHolder(FilterHolder filter) throws ServletException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterInstance(javax.servlet.Filter)
|
||||
*/
|
||||
public <T extends Filter> T decorateFilterInstance(T filter) throws ServletException
|
||||
{
|
||||
decorate(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateListenerInstance(java.util.EventListener)
|
||||
*/
|
||||
public <T extends EventListener> T decorateListenerInstance(T listener) throws ServletException
|
||||
{
|
||||
decorate(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletHolder(org.eclipse.jetty.servlet.ServletHolder)
|
||||
*/
|
||||
public void decorateServletHolder(ServletHolder holder) throws ServletException
|
||||
{
|
||||
decorate(holder);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletInstance(javax.servlet.Servlet)
|
||||
*/
|
||||
public <T extends Servlet> T decorateServletInstance(T servlet) throws ServletException
|
||||
{
|
||||
decorate(servlet);
|
||||
return servlet;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyFilterInstance(javax.servlet.Filter)
|
||||
*/
|
||||
public void destroyFilterInstance(Filter f)
|
||||
{
|
||||
destroy(f);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyServletInstance(javax.servlet.Servlet)
|
||||
*/
|
||||
public void destroyServletInstance(Servlet s)
|
||||
{
|
||||
destroy(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyListenerInstance(java.util.EventListener)
|
||||
*/
|
||||
public void destroyListenerInstance(EventListener l)
|
||||
{
|
||||
destroy(l);
|
||||
}
|
||||
|
||||
|
||||
protected void decorate (Object o)
|
||||
throws ServletException
|
||||
{
|
||||
InjectionCollection injections = (InjectionCollection)_wac.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
RunAsCollection runAses = (RunAsCollection)_wac.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
|
||||
if (runAses != null)
|
||||
runAses.setRunAs(o);
|
||||
|
||||
if (injections != null)
|
||||
injections.inject(o);
|
||||
|
||||
if (callbacks != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
callbacks.callPostConstructCallback(o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void destroy (Object o)
|
||||
{
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
if (callbacks != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
callbacks.callPreDestroyCallback(o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Destroying instance of "+o.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.MetaData;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -50,6 +51,10 @@ public class TestConfiguration
|
|||
WebAppContext wac = new MyWebAppContext();
|
||||
wac.setServer(server);
|
||||
wac.setClassLoader(new WebAppClassLoader(Thread.currentThread().getContextClassLoader(), wac));
|
||||
|
||||
MetaData metaData = new MetaData(wac);
|
||||
|
||||
PlusDescriptorProcessor plusProcessor = new PlusDescriptorProcessor();
|
||||
|
||||
//bind some EnvEntrys at the server level
|
||||
EnvEntry ee1 = new EnvEntry(server, "xxx/a", "100", true);
|
||||
|
@ -73,8 +78,7 @@ public class TestConfiguration
|
|||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/c"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/e"));
|
||||
|
||||
Configuration config = new Configuration();
|
||||
|
||||
//make a new env configuration
|
||||
EnvConfiguration envConfig = new EnvConfiguration();
|
||||
|
||||
|
||||
|
@ -105,20 +109,20 @@ public class TestConfiguration
|
|||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/e");
|
||||
assertNotNull(ne);
|
||||
|
||||
config.bindEnvEntry(wac, "foo", "99");
|
||||
plusProcessor.bindEnvEntry("foo", "99");
|
||||
assertEquals("99",ic.lookup( "java:comp/env/foo"));
|
||||
|
||||
config.bindEnvEntry(wac, "xxx/a", "7");
|
||||
plusProcessor.bindEnvEntry("xxx/a", "7");
|
||||
assertEquals("900", ic.lookup("java:comp/env/xxx/a")); //webapp overrides web.xml
|
||||
config.bindEnvEntry(wac, "yyy/b", "7");
|
||||
plusProcessor.bindEnvEntry("yyy/b", "7");
|
||||
assertEquals("910", ic.lookup("java:comp/env/yyy/b"));//webapp overrides web.xml
|
||||
config.bindEnvEntry(wac,"zzz/c", "7");
|
||||
plusProcessor.bindEnvEntry("zzz/c", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/c"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/d", "7");
|
||||
plusProcessor.bindEnvEntry("zzz/d", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/d"));//server does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/e", "7");
|
||||
plusProcessor.bindEnvEntry("zzz/e", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/e"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/f", "7");
|
||||
plusProcessor.bindEnvEntry("zzz/f", "7");
|
||||
assertEquals("500", ic.lookup("java:comp/env/zzz/f"));//server overrides web.xml
|
||||
|
||||
((Context)ic.lookup("java:comp")).destroySubcontext("env");
|
||||
|
|
|
@ -1269,7 +1269,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
_localeEncodingMap=new HashMap<String,String>();
|
||||
_localeEncodingMap.put(locale, encoding);
|
||||
}
|
||||
|
||||
|
||||
public String getLocaleEncoding (String locale)
|
||||
{
|
||||
if (_localeEncodingMap==null)
|
||||
return null;
|
||||
String encoding = _localeEncodingMap.get(locale);
|
||||
return encoding;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the character encoding for a locale. The full locale name is first
|
||||
|
|
|
@ -13,8 +13,17 @@
|
|||
|
||||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
import org.eclipse.jetty.servlet.api.FilterRegistration;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
|
@ -22,25 +31,26 @@ import org.eclipse.jetty.util.log.Log;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class FilterHolder extends Holder
|
||||
public class FilterHolder extends Holder<Filter>
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
private transient Filter _filter;
|
||||
private transient Config _config;
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/** Constructor for Serialization.
|
||||
/** Constructor
|
||||
*/
|
||||
public FilterHolder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/** Constructor for Serialization.
|
||||
/** Constructor
|
||||
*/
|
||||
public FilterHolder(Class filter)
|
||||
public FilterHolder(Class<? extends Filter> filter)
|
||||
{
|
||||
super (filter);
|
||||
setHeldClass(filter);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
@ -67,9 +77,22 @@ public class FilterHolder extends Holder
|
|||
}
|
||||
|
||||
if (_filter==null)
|
||||
_filter=(Filter)newInstance();
|
||||
{
|
||||
try
|
||||
{
|
||||
_filter=((ServletContextHandler.Context)_servletHandler.getServletContext()).createFilter(getHeldClass());
|
||||
}
|
||||
catch (ServletException se)
|
||||
{
|
||||
Throwable cause = se.getRootCause();
|
||||
if (cause instanceof InstantiationException)
|
||||
throw (InstantiationException)cause;
|
||||
if (cause instanceof IllegalAccessException)
|
||||
throw (IllegalAccessException)cause;
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
|
||||
_filter = getServletHandler().customizeFilter(_filter);
|
||||
_config=new Config();
|
||||
_filter.init(_config);
|
||||
}
|
||||
|
@ -100,13 +123,13 @@ public class FilterHolder extends Holder
|
|||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void destroyInstance (Object o)
|
||||
throws Exception
|
||||
throws Exception
|
||||
{
|
||||
if (o==null)
|
||||
return;
|
||||
Filter f = (Filter)o;
|
||||
f.destroy();
|
||||
getServletHandler().customizeFilterDestroy(f);
|
||||
getServletHandler().destroyFilter(f);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -132,6 +155,74 @@ public class FilterHolder extends Holder
|
|||
return getName();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public FilterRegistration.Dynamic getRegistration()
|
||||
{
|
||||
return new Registration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected class Registration extends HolderRegistration implements FilterRegistration.Dynamic
|
||||
{
|
||||
public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
FilterMapping mapping = new FilterMapping();
|
||||
mapping.setFilterHolder(FilterHolder.this);
|
||||
mapping.setServletNames(servletNames);
|
||||
mapping.setDispatcherTypes(dispatcherTypes);
|
||||
if (isMatchAfter)
|
||||
_servletHandler.addFilterMapping(mapping);
|
||||
else
|
||||
_servletHandler.prependFilterMapping(mapping);
|
||||
}
|
||||
|
||||
public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
FilterMapping mapping = new FilterMapping();
|
||||
mapping.setFilterHolder(FilterHolder.this);
|
||||
mapping.setPathSpecs(urlPatterns);
|
||||
mapping.setDispatcherTypes(dispatcherTypes);
|
||||
if (isMatchAfter)
|
||||
_servletHandler.addFilterMapping(mapping);
|
||||
else
|
||||
_servletHandler.prependFilterMapping(mapping);
|
||||
}
|
||||
|
||||
public Collection<String> getServletNameMappings()
|
||||
{
|
||||
FilterMapping[] mappings =_servletHandler.getFilterMappings();
|
||||
List<String> names=new ArrayList<String>();
|
||||
for (FilterMapping mapping : mappings)
|
||||
{
|
||||
if (mapping.getFilterHolder()!=FilterHolder.this)
|
||||
continue;
|
||||
String[] servlets=mapping.getServletNames();
|
||||
if (servlets!=null && servlets.length>0)
|
||||
names.addAll(Arrays.asList(servlets));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public Collection<String> getUrlPatternMappings()
|
||||
{
|
||||
FilterMapping[] mappings =_servletHandler.getFilterMappings();
|
||||
List<String> patterns=new ArrayList<String>();
|
||||
for (FilterMapping mapping : mappings)
|
||||
{
|
||||
if (mapping.getFilterHolder()!=FilterHolder.this)
|
||||
continue;
|
||||
String[] specs=mapping.getPathSpecs();
|
||||
if (specs!=null && specs.length>0)
|
||||
patterns.addAll(Arrays.asList(specs));
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -16,8 +16,9 @@ package org.eclipse.jetty.servlet;
|
|||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.eclipse.jetty.http.PathMap;
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.http.PathMap;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
||||
|
||||
|
@ -36,18 +37,18 @@ public class FilterMapping
|
|||
/* ------------------------------------------------------------ */
|
||||
/** Dispatch type from name
|
||||
*/
|
||||
public static int dispatch(String type)
|
||||
public static DispatcherType dispatch(String type)
|
||||
{
|
||||
if ("request".equalsIgnoreCase(type))
|
||||
return REQUEST;
|
||||
return DispatcherType.REQUEST;
|
||||
if ("forward".equalsIgnoreCase(type))
|
||||
return FORWARD;
|
||||
return DispatcherType.FORWARD;
|
||||
if ("include".equalsIgnoreCase(type))
|
||||
return INCLUDE;
|
||||
return DispatcherType.INCLUDE;
|
||||
if ("error".equalsIgnoreCase(type))
|
||||
return ERROR;
|
||||
return DispatcherType.ERROR;
|
||||
if ("async".equalsIgnoreCase(type))
|
||||
return ASYNC;
|
||||
return DispatcherType.ASYNC;
|
||||
throw new IllegalArgumentException(type);
|
||||
}
|
||||
|
||||
|
@ -71,28 +72,6 @@ public class FilterMapping
|
|||
}
|
||||
throw new IllegalArgumentException(type.toString());
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Dispatch type from name
|
||||
*/
|
||||
public static DispatcherType dispatch(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case REQUEST:
|
||||
return DispatcherType.REQUEST;
|
||||
case ASYNC:
|
||||
return DispatcherType.ASYNC;
|
||||
case FORWARD:
|
||||
return DispatcherType.FORWARD;
|
||||
case INCLUDE:
|
||||
return DispatcherType.INCLUDE;
|
||||
case ERROR:
|
||||
return DispatcherType.ERROR;
|
||||
}
|
||||
throw new IllegalArgumentException(""+type);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -140,15 +119,6 @@ public class FilterMapping
|
|||
return (_dispatches&type)!=0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the dispatches.
|
||||
*/
|
||||
public int getDispatches()
|
||||
{
|
||||
return _dispatches;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the filterName.
|
||||
|
@ -180,16 +150,23 @@ public class FilterMapping
|
|||
public void setDispatcherTypes(EnumSet<DispatcherType> dispatcherTypes)
|
||||
{
|
||||
_dispatches=DEFAULT;
|
||||
if (dispatcherTypes.contains(DispatcherType.ERROR))
|
||||
_dispatches|=ERROR;
|
||||
if (dispatcherTypes.contains(DispatcherType.FORWARD))
|
||||
_dispatches|=FORWARD;
|
||||
if (dispatcherTypes.contains(DispatcherType.INCLUDE))
|
||||
_dispatches|=INCLUDE;
|
||||
if (dispatcherTypes.contains(DispatcherType.REQUEST))
|
||||
_dispatches|=REQUEST;
|
||||
if (dispatcherTypes!=null)
|
||||
{
|
||||
if (dispatcherTypes.contains(DispatcherType.ERROR))
|
||||
_dispatches|=ERROR;
|
||||
if (dispatcherTypes.contains(DispatcherType.FORWARD))
|
||||
_dispatches|=FORWARD;
|
||||
if (dispatcherTypes.contains(DispatcherType.INCLUDE))
|
||||
_dispatches|=INCLUDE;
|
||||
if (dispatcherTypes.contains(DispatcherType.REQUEST))
|
||||
_dispatches|=REQUEST;
|
||||
if (dispatcherTypes.contains(DispatcherType.ASYNC))
|
||||
_dispatches|=ASYNC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param dispatches The dispatches to set.
|
||||
|
|
|
@ -16,8 +16,11 @@ package org.eclipse.jetty.servlet;
|
|||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.servlet.api.Registration;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.UnavailableException;
|
||||
|
||||
|
@ -31,10 +34,10 @@ import org.eclipse.jetty.util.log.Log;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class Holder extends AbstractLifeCycle
|
||||
public class Holder<T> extends AbstractLifeCycle
|
||||
{
|
||||
protected transient Class<? extends T> _class;
|
||||
protected final Map<String,String> _initParams=new HashMap<String,String>(3);
|
||||
protected transient Class<?> _class;
|
||||
protected String _className;
|
||||
protected String _displayName;
|
||||
protected boolean _extInstance;
|
||||
|
@ -44,22 +47,20 @@ public class Holder extends AbstractLifeCycle
|
|||
protected String _name;
|
||||
protected ServletHandler _servletHandler;
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
protected Holder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
protected Holder(Class held)
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return True if this holder was created for a specific instance.
|
||||
*/
|
||||
public boolean isInstance()
|
||||
{
|
||||
_class=held;
|
||||
if (held!=null)
|
||||
{
|
||||
_className=held.getName();
|
||||
_name=held.getName()+"-"+this.hashCode();
|
||||
}
|
||||
return _extInstance;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void doStart()
|
||||
throws Exception
|
||||
|
@ -85,6 +86,7 @@ public class Holder extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void doStop()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -99,7 +101,7 @@ public class Holder extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Class getHeldClass()
|
||||
public Class<? extends T> getHeldClass()
|
||||
{
|
||||
return _class;
|
||||
}
|
||||
|
@ -127,7 +129,7 @@ public class Holder extends AbstractLifeCycle
|
|||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
public Map getInitParameters()
|
||||
public Map<String,String> getInitParameters()
|
||||
{
|
||||
return _initParams;
|
||||
}
|
||||
|
@ -147,16 +149,6 @@ public class Holder extends AbstractLifeCycle
|
|||
return _servletHandler;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public synchronized Object newInstance()
|
||||
throws InstantiationException,
|
||||
IllegalAccessException
|
||||
{
|
||||
if (_class==null)
|
||||
throw new InstantiationException("!"+_className);
|
||||
return _class.newInstance();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void destroyInstance(Object instance)
|
||||
throws Exception
|
||||
|
@ -177,10 +169,15 @@ public class Holder extends AbstractLifeCycle
|
|||
/**
|
||||
* @param held The class to hold
|
||||
*/
|
||||
public void setHeldClass(Class held)
|
||||
public void setHeldClass(Class<? extends T> held)
|
||||
{
|
||||
_class=held;
|
||||
_className = held!=null?held.getName():null;
|
||||
if (held!=null)
|
||||
{
|
||||
_className=held.getName();
|
||||
if (_name==null)
|
||||
_name=held.getName()+"-"+this.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -276,6 +273,72 @@ public class Holder extends AbstractLifeCycle
|
|||
return Holder.this.getInitParameterNames();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
protected class HolderRegistration implements Registration.Dynamic
|
||||
{
|
||||
public void setAsyncSupported(boolean isAsyncSupported)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
Holder.this.setAsyncSupported(isAsyncSupported);
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug(this+" is "+description);
|
||||
}
|
||||
|
||||
public String getClassName()
|
||||
{
|
||||
return Holder.this.getClassName();
|
||||
}
|
||||
|
||||
public String getInitParameter(String name)
|
||||
{
|
||||
return Holder.this.getInitParameter(name);
|
||||
}
|
||||
|
||||
public Map<String, String> getInitParameters()
|
||||
{
|
||||
return Holder.this.getInitParameters();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return Holder.this.getName();
|
||||
}
|
||||
|
||||
public boolean setInitParameter(String name, String value)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
if (Holder.this.getInitParameter(name)!=null)
|
||||
return false;
|
||||
Holder.this.setInitParameter(name,value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<String> setInitParameters(Map<String, String> initParameters)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
Set<String> clash=null;
|
||||
for (String name : initParameters.keySet())
|
||||
{
|
||||
if (Holder.this.getInitParameter(name)!=null)
|
||||
{
|
||||
if (clash==null)
|
||||
clash=new HashSet<String>();
|
||||
clash.add(name);
|
||||
}
|
||||
}
|
||||
if (clash!=null)
|
||||
return clash;
|
||||
Holder.this.setInitParameters(initParameters);
|
||||
return Collections.emptySet();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,13 +13,26 @@
|
|||
|
||||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintAware;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.server.Dispatcher;
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
|
@ -29,8 +42,10 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.server.handler.ScopedHandler;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.servlet.api.FilterRegistration;
|
||||
import org.eclipse.jetty.servlet.api.ServletRegistration;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -56,6 +71,10 @@ public class ServletContextHandler extends ContextHandler
|
|||
protected SecurityHandler _securityHandler;
|
||||
protected ServletHandler _servletHandler;
|
||||
protected int _options;
|
||||
protected Decorator _decorator;
|
||||
protected Object _restrictedContextListeners;
|
||||
|
||||
protected final Set<Object> _created = Collections.newSetFromMap(new ConcurrentHashMap<Object,Boolean>());
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ServletContextHandler()
|
||||
|
@ -115,6 +134,42 @@ public class ServletContextHandler extends ContextHandler
|
|||
((HandlerCollection)parent).addHandler(this);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.handler.ContextHandler#doStart()
|
||||
*/
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
_created.clear();
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.handler.ContextHandler#doStop()
|
||||
*/
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
_created.clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Check if instance was created by a call to {@link ServletContext#createFilter(Class)},
|
||||
* {@link ServletContext#createServlet(Class)} or {@link ServletContext#createListener(Class)}
|
||||
* @param instance Instance of {@link Servlet}, {@link Filter} or {@link EventListener}
|
||||
* @return True if the instance was created by a call to {@link ServletContext#createFilter(Class)},
|
||||
* {@link ServletContext#createServlet(Class)} or {@link ServletContext#createListener(Class)}
|
||||
*/
|
||||
public boolean isCreatedInstance(Object instance)
|
||||
{
|
||||
return _created.contains(instance);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the defaultSecurityHandlerClass.
|
||||
* @return the defaultSecurityHandlerClass
|
||||
|
@ -201,7 +256,19 @@ public class ServletContextHandler extends ContextHandler
|
|||
|
||||
// OK to Initialize servlet handler now
|
||||
if (_servletHandler != null && _servletHandler.isStarted())
|
||||
{
|
||||
if (_decorator!=null)
|
||||
{
|
||||
if (_servletHandler.getFilters()!=null)
|
||||
for (FilterHolder holder:_servletHandler.getFilters())
|
||||
_decorator.decorateFilterHolder(holder);
|
||||
if(_servletHandler.getServlets()!=null)
|
||||
for (ServletHolder holder:_servletHandler.getServlets())
|
||||
_decorator.decorateServletHolder(holder);
|
||||
}
|
||||
|
||||
_servletHandler.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -262,6 +329,31 @@ public class ServletContextHandler extends ContextHandler
|
|||
getServletHandler().addServletWithMapping(servlet, pathSpec);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** conveniance method to add a filter
|
||||
*/
|
||||
public void addFilter(FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
getServletHandler().addFilterWithMapping(holder,pathSpec,dispatches);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** convenience method to add a filter
|
||||
*/
|
||||
public FilterHolder addFilter(Class<? extends Filter> filterClass,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** convenience method to add a filter
|
||||
*/
|
||||
public FilterHolder addFilter(String filterClass,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** conveniance method to add a filter
|
||||
*/
|
||||
|
@ -286,6 +378,21 @@ public class ServletContextHandler extends ContextHandler
|
|||
return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void callContextInitialized(ServletContextListener l, ServletContextEvent e)
|
||||
{
|
||||
l.contextInitialized(e);
|
||||
}
|
||||
|
||||
|
||||
public void callContextDestroyed(ServletContextListener l, ServletContextEvent e)
|
||||
{
|
||||
l.contextDestroyed(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param sessionHandler The sessionHandler to set.
|
||||
|
@ -322,14 +429,46 @@ public class ServletContextHandler extends ContextHandler
|
|||
_servletHandler = servletHandler;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return The decorator used to resource inject new Filters, Servlets and EventListeners
|
||||
*/
|
||||
public Decorator getDecorator()
|
||||
{
|
||||
return _decorator;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param decorator The inject used to resource inject new Filters, Servlets and EventListeners
|
||||
*/
|
||||
public void setDecorator(Decorator decorator)
|
||||
{
|
||||
_decorator = decorator;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
void destroyServlet(Servlet servlet)
|
||||
{
|
||||
if (_decorator!=null)
|
||||
_decorator.destroyServletInstance(servlet);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
void destroyFilter(Filter filter)
|
||||
{
|
||||
if (_decorator!=null)
|
||||
_decorator.destroyFilterInstance(filter);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public class Context extends ContextHandler.Context
|
||||
{
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public RequestDispatcher getNamedDispatcher(String name)
|
||||
{
|
||||
ContextHandler context=org.eclipse.jetty.servlet.ServletContextHandler.this;
|
||||
|
@ -337,33 +476,307 @@ public class ServletContextHandler extends ContextHandler
|
|||
return null;
|
||||
return new Dispatcher(context, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addFilterMappingForServletNames(String filterName, EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames)
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
FilterMapping mapping = new FilterMapping();
|
||||
mapping.setFilterName(filterName);
|
||||
mapping.setServletNames(servletNames);
|
||||
mapping.setDispatcherTypes(dispatcherTypes);
|
||||
handler.addFilterMapping(mapping);
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final FilterHolder holder= handler.newFilterHolder();
|
||||
holder.setName(filterName);
|
||||
holder.setHeldClass(filterClass);
|
||||
handler.addFilter(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addServletMapping(String servletName, String[] urlPatterns)
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#addFilter(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, String className)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
ServletHolder holder= handler.newServletHolder();
|
||||
holder.setName(servletName);
|
||||
handler.addServlet(holder);
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final FilterHolder holder= handler.newFilterHolder();
|
||||
holder.setName(filterName);
|
||||
holder.setClassName(className);
|
||||
handler.addFilter(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#addFilter(java.lang.String, javax.servlet.Filter)
|
||||
*/
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final FilterHolder holder= handler.newFilterHolder();
|
||||
holder.setName(filterName);
|
||||
holder.setFilter(filter);
|
||||
handler.addFilter(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final ServletHolder holder= handler.newServletHolder();
|
||||
holder.setName(servletName);
|
||||
holder.setHeldClass(servletClass);
|
||||
handler.addServlet(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletContext#addServlet(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, String className)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final ServletHolder holder= handler.newServletHolder();
|
||||
holder.setName(servletName);
|
||||
holder.setClassName(className);
|
||||
handler.addServlet(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
|
||||
final ServletHolder holder= handler.newServletHolder();
|
||||
holder.setName(servletName);
|
||||
holder.setServlet(servlet);
|
||||
handler.addServlet(holder);
|
||||
return holder.getRegistration();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean setInitParameter(String name, String value)
|
||||
{
|
||||
// TODO other started conditions
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
return super.setInitParameter(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public <T extends Filter> T createFilter(Class<T> c) throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
T f = c.newInstance();
|
||||
if (_decorator!=null)
|
||||
f=_decorator.decorateFilterInstance(f);
|
||||
_created.add(f);
|
||||
return f;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
T s = c.newInstance();
|
||||
if (_decorator!=null)
|
||||
s=_decorator.decorateServletInstance(s);
|
||||
_created.add(s);
|
||||
return s;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public FilterRegistration getFilterRegistration(String filterName)
|
||||
{
|
||||
final FilterHolder holder=ServletContextHandler.this.getServletHandler().getFilter(filterName);
|
||||
return (holder==null)?null:holder.getRegistration();
|
||||
}
|
||||
|
||||
|
||||
public Map<String, ? extends FilterRegistration> getFilterRegistrations()
|
||||
{
|
||||
HashMap<String, FilterRegistration> registrations = new HashMap<String, FilterRegistration>();
|
||||
ServletHandler handler=ServletContextHandler.this.getServletHandler();
|
||||
FilterHolder[] holders=handler.getFilters();
|
||||
if (holders!=null)
|
||||
{
|
||||
for (FilterHolder holder : holders)
|
||||
registrations.put(holder.getName(),holder.getRegistration());
|
||||
}
|
||||
return registrations;
|
||||
}
|
||||
|
||||
|
||||
public ServletRegistration getServletRegistration(String servletName)
|
||||
{
|
||||
final ServletHolder holder=ServletContextHandler.this.getServletHandler().getServlet(servletName);
|
||||
return (holder==null)?null:holder.getRegistration();
|
||||
}
|
||||
|
||||
|
||||
public Map<String, ? extends ServletRegistration> getServletRegistrations()
|
||||
{
|
||||
HashMap<String, ServletRegistration> registrations = new HashMap<String, ServletRegistration>();
|
||||
ServletHandler handler=ServletContextHandler.this.getServletHandler();
|
||||
ServletHolder[] holders=handler.getServlets();
|
||||
if (holders!=null)
|
||||
{
|
||||
for (ServletHolder holder : holders)
|
||||
registrations.put(holder.getName(),holder.getRegistration());
|
||||
}
|
||||
return registrations;
|
||||
}
|
||||
|
||||
|
||||
public void addListener(String className)
|
||||
{
|
||||
// TODO other started conditions
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
try
|
||||
{
|
||||
Class<? extends EventListener> clazz = getClassLoader()==null?Loader.loadClass(ContextHandler.class,className):getClassLoader().loadClass(className);
|
||||
addListener(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public <T extends EventListener> void addListener(T t)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
ServletContextHandler.this.addEventListener(t);
|
||||
}
|
||||
|
||||
|
||||
public void addListener(Class<? extends EventListener> listenerClass)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
try
|
||||
{
|
||||
EventListener l = createListener(listenerClass);
|
||||
ServletContextHandler.this.addEventListener(l);
|
||||
}
|
||||
catch (ServletException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
T l = null;
|
||||
try
|
||||
{
|
||||
l = clazz.newInstance();
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
|
||||
if (_decorator!=null)
|
||||
l=_decorator.decorateListenerInstance(l);
|
||||
_created.add(l);
|
||||
return l;
|
||||
}
|
||||
catch(ServletException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void declareRoles(String... roleNames)
|
||||
{
|
||||
if (!isStarting())
|
||||
throw new IllegalStateException();
|
||||
|
||||
//Get a reference to the SecurityHandler, which must be ConstraintAware
|
||||
if (_securityHandler != null && _securityHandler instanceof ConstraintAware)
|
||||
{
|
||||
HashSet<String> union = new HashSet<String>();
|
||||
Set<String> existing = ((ConstraintAware)_securityHandler).getRoles();
|
||||
if (existing != null)
|
||||
union.addAll(existing);
|
||||
union.addAll(Arrays.asList(roleNames));
|
||||
((ConstraintSecurityHandler)_securityHandler).setRoles(union);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Decorator
|
||||
{
|
||||
<T extends Filter> T decorateFilterInstance(T filter) throws ServletException;
|
||||
<T extends Servlet> T decorateServletInstance(T servlet) throws ServletException;
|
||||
<T extends EventListener> T decorateListenerInstance(T listener) throws ServletException;
|
||||
|
||||
void decorateFilterHolder(FilterHolder filter) throws ServletException;
|
||||
void decorateServletHolder(ServletHolder servlet) throws ServletException;
|
||||
|
||||
void destroyServletInstance(Servlet s);
|
||||
void destroyFilterInstance(Filter f);
|
||||
void destroyListenerInstance(EventListener f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,15 @@ package org.eclipse.jetty.servlet;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
|
@ -42,7 +45,6 @@ import org.eclipse.jetty.io.RuntimeIOException;
|
|||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.server.Dispatcher;
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
import org.eclipse.jetty.server.HttpConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -73,7 +75,7 @@ public class ServletHandler extends ScopedHandler
|
|||
public static final String __DEFAULT_SERVLET="default";
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private ContextHandler _contextHandler;
|
||||
private ServletContextHandler _contextHandler;
|
||||
private ContextHandler.Context _servletContext;
|
||||
private FilterHolder[] _filters;
|
||||
private FilterMapping[] _filterMappings;
|
||||
|
@ -85,14 +87,14 @@ public class ServletHandler extends ScopedHandler
|
|||
private ServletHolder[] _servlets;
|
||||
private ServletMapping[] _servletMappings;
|
||||
|
||||
private transient Map<String,FilterHolder> _filterNameMap= new HashMap<String,FilterHolder>();
|
||||
private transient List<FilterMapping> _filterPathMappings;
|
||||
private transient MultiMap<String> _filterNameMappings;
|
||||
private final Map<String,FilterHolder> _filterNameMap= new HashMap<String,FilterHolder>();
|
||||
private List<FilterMapping> _filterPathMappings;
|
||||
private MultiMap<String> _filterNameMappings;
|
||||
|
||||
private transient Map<String,ServletHolder> _servletNameMap=new HashMap();
|
||||
private transient PathMap _servletPathMap;
|
||||
private final Map<String,ServletHolder> _servletNameMap=new HashMap<String,ServletHolder>();
|
||||
private PathMap _servletPathMap;
|
||||
|
||||
protected transient ConcurrentHashMap _chainCache[];
|
||||
protected ConcurrentHashMap<String,FilterChain> _chainCache[];
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -130,7 +132,7 @@ public class ServletHandler extends ScopedHandler
|
|||
throws Exception
|
||||
{
|
||||
_servletContext=ContextHandler.getCurrentContext();
|
||||
_contextHandler=_servletContext==null?null:_servletContext.getContextHandler();
|
||||
_contextHandler=(ServletContextHandler)(_servletContext==null?null:_servletContext.getContextHandler());
|
||||
|
||||
if (_contextHandler!=null)
|
||||
{
|
||||
|
@ -269,6 +271,7 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
return _servletContext;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the servletMappings.
|
||||
|
@ -277,6 +280,30 @@ public class ServletHandler extends ScopedHandler
|
|||
{
|
||||
return _servletMappings;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the servletMappings.
|
||||
*/
|
||||
public ServletMapping getServletMapping(String pattern)
|
||||
{
|
||||
if (_servletMappings!=null)
|
||||
{
|
||||
for (ServletMapping m:_servletMappings)
|
||||
{
|
||||
String[] paths=m.getPathSpecs();
|
||||
if (paths!=null)
|
||||
{
|
||||
for (String path:paths)
|
||||
{
|
||||
if (pattern.equals(path))
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get Servlets.
|
||||
|
@ -726,9 +753,9 @@ public class ServletHandler extends ScopedHandler
|
|||
*/
|
||||
public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
|
||||
{
|
||||
ServletHolder holder = newServletHolder(servlet);
|
||||
ServletHolder holder = newServletHolder();
|
||||
holder.setHeldClass(servlet);
|
||||
setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
|
||||
|
||||
addServletWithMapping(holder,pathSpec);
|
||||
|
||||
return holder;
|
||||
|
@ -797,11 +824,82 @@ public class ServletHandler extends ScopedHandler
|
|||
return new FilterHolder();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public FilterHolder getFilter(String name)
|
||||
{
|
||||
return (FilterHolder)_filterNameMap.get(name);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience method to add a filter.
|
||||
* @param filter class of filter to create
|
||||
* @param pathSpec filter mappings for filter
|
||||
* @param dispatches see {@link FilterMapping#setDispatches(int)}
|
||||
* @return The filter holder.
|
||||
*/
|
||||
public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
FilterHolder holder = newFilterHolder();
|
||||
holder.setHeldClass(filter);
|
||||
addFilterWithMapping(holder,pathSpec,dispatches);
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience method to add a filter.
|
||||
* @param className of filter
|
||||
* @param pathSpec filter mappings for filter
|
||||
* @param dispatches see {@link FilterMapping#setDispatches(int)}
|
||||
* @return The filter holder.
|
||||
*/
|
||||
public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
FilterHolder holder = newFilterHolder();
|
||||
holder.setName(className+"-"+holder.hashCode());
|
||||
holder.setClassName(className);
|
||||
|
||||
addFilterWithMapping(holder,pathSpec,dispatches);
|
||||
return holder;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience method to add a filter.
|
||||
* @param holder filter holder to add
|
||||
* @param pathSpec filter mappings for filter
|
||||
* @param dispatches see {@link FilterMapping#setDispatches(int)}
|
||||
*/
|
||||
public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
FilterHolder[] holders = getFilters();
|
||||
if (holders!=null)
|
||||
holders = (FilterHolder[])holders.clone();
|
||||
|
||||
try
|
||||
{
|
||||
setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
|
||||
|
||||
FilterMapping mapping = new FilterMapping();
|
||||
mapping.setFilterName(holder.getName());
|
||||
mapping.setPathSpec(pathSpec);
|
||||
mapping.setDispatcherTypes(dispatches);
|
||||
setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
setFilters(holders);
|
||||
throw e;
|
||||
}
|
||||
catch (Error e)
|
||||
{
|
||||
setFilters(holders);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience method to add a filter.
|
||||
|
@ -870,6 +968,20 @@ public class ServletHandler extends ScopedHandler
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience method to add a filter with a mapping
|
||||
* @param className
|
||||
* @param pathSpec
|
||||
* @param dispatches
|
||||
* @return the filter holder created
|
||||
* @deprecated use {@link #addFilterWithMapping(Class, String, int)} instead
|
||||
*/
|
||||
public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
|
||||
{
|
||||
return addFilterWithMapping(className, pathSpec, dispatches);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* convenience method to add a filter and mapping
|
||||
|
@ -1282,55 +1394,18 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Customize a servlet.
|
||||
*
|
||||
* Called before the servlet goes into service.
|
||||
* Subclasses of ServletHandler should override
|
||||
* this method.
|
||||
*
|
||||
* @param servlet
|
||||
* @return the potentially customized servlet
|
||||
* @throws Exception
|
||||
*/
|
||||
public Servlet customizeServlet (Servlet servlet)
|
||||
throws Exception
|
||||
void destroyServlet(Servlet servlet)
|
||||
{
|
||||
return servlet;
|
||||
_contextHandler.destroyServlet(servlet);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Servlet customizeServletDestroy (Servlet servlet)
|
||||
throws Exception
|
||||
void destroyFilter(Filter filter)
|
||||
{
|
||||
return servlet;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Customize a Filter.
|
||||
*
|
||||
* Called before the Filter goes into service.
|
||||
* Subclasses of ServletHandler should override
|
||||
* this method.
|
||||
*
|
||||
* @param filter The filter to customize.
|
||||
* @return the potentially customized filter
|
||||
* @throws Exception If there was a problem
|
||||
*/
|
||||
public Filter customizeFilter (Filter filter)
|
||||
throws Exception
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Filter customizeFilterDestroy (Filter filter)
|
||||
throws Exception
|
||||
{
|
||||
return filter;
|
||||
_contextHandler.destroyFilter(filter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
|
|
@ -14,19 +14,26 @@
|
|||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import org.eclipse.jetty.servlet.api.ServletRegistration;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.SingleThreadModel;
|
||||
import javax.servlet.UnavailableException;
|
||||
|
||||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.RunAsToken;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -45,7 +52,7 @@ import org.eclipse.jetty.util.log.Log;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public class ServletHolder extends Holder implements UserIdentity.Scope, Comparable
|
||||
public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable
|
||||
{
|
||||
/* ---------------------------------------------------------------- */
|
||||
private int _initOrder;
|
||||
|
@ -67,7 +74,9 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
/** Constructor .
|
||||
*/
|
||||
public ServletHolder()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/** Constructor for existing servlet.
|
||||
|
@ -80,9 +89,9 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
/* ---------------------------------------------------------------- */
|
||||
/** Constructor for existing servlet.
|
||||
*/
|
||||
public ServletHolder(Class servlet)
|
||||
public ServletHolder(Class<? extends Servlet> servlet)
|
||||
{
|
||||
super(servlet);
|
||||
setHeldClass(servlet);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
@ -124,6 +133,11 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
_initOnStartup=true;
|
||||
_initOrder = order;
|
||||
}
|
||||
|
||||
public boolean isSetInitOrder()
|
||||
{
|
||||
return _initOnStartup;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Comparitor by init order.
|
||||
|
@ -293,7 +307,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
return;
|
||||
Servlet servlet = ((Servlet)o);
|
||||
servlet.destroy();
|
||||
getServletHandler().customizeServletDestroy(servlet);
|
||||
getServletHandler().destroyServlet(servlet);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -404,13 +418,9 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
try
|
||||
{
|
||||
if (_servlet==null)
|
||||
_servlet=(Servlet)newInstance();
|
||||
_servlet=newInstance();
|
||||
if (_config==null)
|
||||
_config=new Config();
|
||||
|
||||
//handle any cusomizations of the servlet, such as @postConstruct
|
||||
if (!(_servlet instanceof SingleThreadedWrapper))
|
||||
_servlet = getServletHandler().customizeServlet(_servlet);
|
||||
|
||||
// Handle run as
|
||||
if (_identityService!=null)
|
||||
|
@ -468,22 +478,6 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
return _roleMap;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getRunAsRole()
|
||||
{
|
||||
return _runAsRole;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the run-as role for this servlet
|
||||
* @param role run-as role for this servlet
|
||||
*/
|
||||
public void setRunAsRole(String role)
|
||||
{
|
||||
_runAsRole=role;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Service a request with this servlet.
|
||||
*/
|
||||
|
@ -560,19 +554,92 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
public class Registration extends HolderRegistration implements ServletRegistration.Dynamic
|
||||
{
|
||||
public Set<String> addMapping(String... urlPatterns)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
Set<String> clash=null;
|
||||
for (String pattern : urlPatterns)
|
||||
{
|
||||
if (_servletHandler.getServletMapping(pattern)!=null)
|
||||
{
|
||||
if (clash==null)
|
||||
clash=new HashSet<String>();
|
||||
clash.add(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
if (clash!=null)
|
||||
return clash;
|
||||
|
||||
ServletMapping mapping = new ServletMapping();
|
||||
mapping.setServletName(ServletHolder.this.getName());
|
||||
mapping.setPathSpecs(urlPatterns);
|
||||
_servletHandler.addServletMapping(mapping);
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection<String> getMappings()
|
||||
{
|
||||
ServletMapping[] mappings =_servletHandler.getServletMappings();
|
||||
List<String> patterns=new ArrayList<String>();
|
||||
for (ServletMapping mapping : mappings)
|
||||
{
|
||||
if (!mapping.getServletName().equals(getName()))
|
||||
continue;
|
||||
String[] specs=mapping.getPathSpecs();
|
||||
if (specs!=null && specs.length>0)
|
||||
patterns.addAll(Arrays.asList(specs));
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
public String getRunAsRole()
|
||||
{
|
||||
return _runAsRole;
|
||||
}
|
||||
|
||||
public void setLoadOnStartup(int loadOnStartup)
|
||||
{
|
||||
illegalStateIfContextStarted();
|
||||
ServletHolder.this.setInitOrder(loadOnStartup);
|
||||
}
|
||||
|
||||
public int getInitOrder()
|
||||
{
|
||||
return ServletHolder.this.getInitOrder();
|
||||
}
|
||||
|
||||
|
||||
public void setRunAsRole(String role)
|
||||
{
|
||||
_runAsRole = role;
|
||||
}
|
||||
}
|
||||
|
||||
public ServletRegistration.Dynamic getRegistration()
|
||||
{
|
||||
return new Registration();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
private class SingleThreadedWrapper implements Servlet
|
||||
{
|
||||
Stack _stack=new Stack();
|
||||
Stack<Servlet> _stack=new Stack<Servlet>();
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
while(_stack.size()>0)
|
||||
try { ((Servlet)_stack.pop()).destroy(); } catch (Exception e) { Log.warn(e); }
|
||||
try { (_stack.pop()).destroy(); } catch (Exception e) { Log.warn(e); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,8 +661,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
{
|
||||
try
|
||||
{
|
||||
Servlet s = (Servlet) newInstance();
|
||||
s = getServletHandler().customizeServlet(s);
|
||||
Servlet s = newInstance();
|
||||
s.init(config);
|
||||
_stack.push(s);
|
||||
}
|
||||
|
@ -622,18 +688,13 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
{
|
||||
try
|
||||
{
|
||||
s = (Servlet) newInstance();
|
||||
s = getServletHandler().customizeServlet(s);
|
||||
s = newInstance();
|
||||
s.init(_config);
|
||||
}
|
||||
catch (ServletException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ServletException(e);
|
||||
|
@ -653,7 +714,30 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return
|
||||
* @throws ServletException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
protected Servlet newInstance() throws ServletException, IllegalAccessException, InstantiationException
|
||||
{
|
||||
try
|
||||
{
|
||||
return ((ServletContextHandler.Context)getServletHandler().getServletContext()).createServlet(getHeldClass());
|
||||
}
|
||||
catch (ServletException se)
|
||||
{
|
||||
Throwable cause = se.getRootCause();
|
||||
if (cause instanceof InstantiationException)
|
||||
throw (InstantiationException)cause;
|
||||
if (cause instanceof IllegalAccessException)
|
||||
throw (IllegalAccessException)cause;
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.eclipse.jetty.servlet.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
|
||||
/**
|
||||
* FilterRegistration
|
||||
*
|
||||
* Mimics the javax.servlet.FilterRegistration class to ease
|
||||
* jetty-7/jetty-8 compatibility
|
||||
*/
|
||||
public interface FilterRegistration
|
||||
{
|
||||
public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames);
|
||||
|
||||
public Collection<String> getServletNameMappings();
|
||||
|
||||
public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns);
|
||||
|
||||
public Collection<String> getUrlPatternMappings();
|
||||
|
||||
interface Dynamic extends FilterRegistration, Registration.Dynamic
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.eclipse.jetty.servlet.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Registration
|
||||
{
|
||||
|
||||
public String getName();
|
||||
|
||||
public String getClassName();
|
||||
|
||||
public boolean setInitParameter(String name, String value);
|
||||
|
||||
public String getInitParameter(String name);
|
||||
|
||||
public Set<String> setInitParameters(Map<String, String> initParameters);
|
||||
|
||||
public Map<String, String> getInitParameters();
|
||||
|
||||
interface Dynamic extends Registration
|
||||
{
|
||||
public void setAsyncSupported(boolean isAsyncSupported);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.eclipse.jetty.servlet.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ServletRegistration
|
||||
{
|
||||
public Set<String> addMapping(String... urlPatterns);
|
||||
|
||||
public Collection<String> getMappings();
|
||||
|
||||
public String getRunAsRole();
|
||||
|
||||
interface Dynamic extends ServletRegistration, Registration.Dynamic
|
||||
{
|
||||
public void setLoadOnStartup(int loadOnStartup);
|
||||
|
||||
public void setRunAsRole(String roleName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* DefaultsDescriptor
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DefaultsDescriptor extends Descriptor
|
||||
{
|
||||
public DefaultsDescriptor(Resource xml, MetaData processor)
|
||||
{
|
||||
super(xml, processor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Descriptor
|
||||
*
|
||||
* A web descriptor (web.xml/web-defaults.xml/web-overrides.xml).
|
||||
*/
|
||||
public class Descriptor
|
||||
{
|
||||
protected static XmlParser _parser;
|
||||
public enum MetaDataComplete {NotSet, True, False};
|
||||
protected Resource _xml;
|
||||
protected XmlParser.Node _root;
|
||||
protected MetaDataComplete _metaDataComplete;
|
||||
protected int _majorVersion = 3; //default to container version
|
||||
protected int _minorVersion = 0;
|
||||
protected ArrayList<String> _classNames = new ArrayList<String>();
|
||||
protected boolean _distributable;
|
||||
protected boolean _validating;
|
||||
protected MetaData _metaData;
|
||||
protected boolean _isOrdered = false;
|
||||
protected List<String> _ordering = new ArrayList<String>();
|
||||
|
||||
|
||||
|
||||
|
||||
public static XmlParser newParser()
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
XmlParser xmlParser=new XmlParser();
|
||||
//set up cache of DTDs and schemas locally
|
||||
URL dtd22=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_2.dtd",true);
|
||||
URL dtd23=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_3.dtd",true);
|
||||
URL j2ee14xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_1_4.xsd",true);
|
||||
URL webapp24xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_4.xsd",true);
|
||||
URL webapp25xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_5.xsd",true);
|
||||
URL webapp30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_3_0.xsd",true);
|
||||
URL webcommon30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-common_3_0.xsd",true);
|
||||
URL webfragment30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-fragment_3_0.xsd",true);
|
||||
URL schemadtd=Loader.getResource(Servlet.class,"javax/servlet/resources/XMLSchema.dtd",true);
|
||||
URL xmlxsd=Loader.getResource(Servlet.class,"javax/servlet/resources/xml.xsd",true);
|
||||
URL webservice11xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_web_services_client_1_1.xsd",true);
|
||||
URL webservice12xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/javaee_web_services_client_1_2.xsd",true);
|
||||
URL datatypesdtd=Loader.getResource(Servlet.class,"javax/servlet/resources/datatypes.dtd",true);
|
||||
|
||||
URL jsp20xsd = null;
|
||||
URL jsp21xsd = null;
|
||||
|
||||
try
|
||||
{
|
||||
Class jsp_page = Loader.loadClass(WebXmlConfiguration.class, "javax.servlet.jsp.JspPage");
|
||||
jsp20xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_0.xsd");
|
||||
jsp21xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_1.xsd");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (jsp20xsd == null) jsp20xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_0.xsd", true);
|
||||
if (jsp21xsd == null) jsp21xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_1.xsd", true);
|
||||
}
|
||||
|
||||
redirect(xmlParser,"web-app_2_2.dtd",dtd22);
|
||||
redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",dtd22);
|
||||
redirect(xmlParser,"web.dtd",dtd23);
|
||||
redirect(xmlParser,"web-app_2_3.dtd",dtd23);
|
||||
redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",dtd23);
|
||||
redirect(xmlParser,"XMLSchema.dtd",schemadtd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/XMLSchema.dtd",schemadtd);
|
||||
redirect(xmlParser,"-//W3C//DTD XMLSCHEMA 200102//EN",schemadtd);
|
||||
redirect(xmlParser,"jsp_2_0.xsd",jsp20xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/jsp_2_0.xsd",jsp20xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/jsp_2_1.xsd",jsp21xsd);
|
||||
redirect(xmlParser,"j2ee_1_4.xsd",j2ee14xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd",j2ee14xsd);
|
||||
redirect(xmlParser,"web-app_2_4.xsd",webapp24xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd",webapp24xsd);
|
||||
redirect(xmlParser,"web-app_2_5.xsd",webapp25xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd",webapp25xsd);
|
||||
redirect(xmlParser,"web-app_3_0.xsd",webapp30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd",webapp30xsd);
|
||||
redirect(xmlParser,"web-common_3_0.xsd",webcommon30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd",webcommon30xsd);
|
||||
redirect(xmlParser,"web-fragment_3_0.xsd",webfragment30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd",webfragment30xsd);
|
||||
redirect(xmlParser,"xml.xsd",xmlxsd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/xml.xsd",xmlxsd);
|
||||
redirect(xmlParser,"datatypes.dtd",datatypesdtd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/datatypes.dtd",datatypesdtd);
|
||||
redirect(xmlParser,"j2ee_web_services_client_1_1.xsd",webservice11xsd);
|
||||
redirect(xmlParser,"http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",webservice11xsd);
|
||||
redirect(xmlParser,"javaee_web_services_client_1_2.xsd",webservice12xsd);
|
||||
redirect(xmlParser,"http://www.ibm.com/webservices/xsd/javaee_web_services_client_1_2.xsd",webservice12xsd);
|
||||
return xmlParser;
|
||||
}
|
||||
|
||||
|
||||
protected static void redirect(XmlParser parser, String resource, URL source)
|
||||
{
|
||||
if (source != null) parser.redirectEntity(resource, source);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Descriptor (Resource xml, MetaData md)
|
||||
{
|
||||
_xml = xml;
|
||||
_metaData = md;
|
||||
}
|
||||
|
||||
public void parse ()
|
||||
throws Exception
|
||||
{
|
||||
if (_parser == null)
|
||||
_parser = newParser();
|
||||
|
||||
if (_root == null)
|
||||
{
|
||||
//boolean oldValidating = _processor.getParser().getValidating();
|
||||
//_processor.getParser().setValidating(_validating);
|
||||
_root = _parser.parse(_xml.getURL().toString());
|
||||
processVersion();
|
||||
processOrdering();
|
||||
//_processor.getParser().setValidating(oldValidating);
|
||||
}
|
||||
}
|
||||
|
||||
public MetaDataComplete getMetaDataComplete()
|
||||
{
|
||||
return _metaDataComplete;
|
||||
}
|
||||
|
||||
|
||||
public XmlParser.Node getRoot ()
|
||||
{
|
||||
return _root;
|
||||
}
|
||||
|
||||
public int getMajorVersion ()
|
||||
{
|
||||
return _majorVersion;
|
||||
}
|
||||
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return _minorVersion;
|
||||
}
|
||||
|
||||
public Resource getResource ()
|
||||
{
|
||||
return _xml;
|
||||
}
|
||||
|
||||
public MetaData getMetaData()
|
||||
{
|
||||
return _metaData;
|
||||
}
|
||||
|
||||
public void processVersion ()
|
||||
{
|
||||
String version = _root.getAttribute("version", "DTD");
|
||||
if ("DTD".equals(version))
|
||||
{
|
||||
_majorVersion = 2;
|
||||
_minorVersion = 3;
|
||||
String dtd = _parser.getDTD();
|
||||
if (dtd != null && dtd.indexOf("web-app_2_2") >= 0)
|
||||
{
|
||||
_majorVersion = 2;
|
||||
_minorVersion = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int dot = version.indexOf(".");
|
||||
if (dot > 0)
|
||||
{
|
||||
_majorVersion = Integer.parseInt(version.substring(0,dot));
|
||||
_minorVersion = Integer.parseInt(version.substring(dot+1));
|
||||
}
|
||||
}
|
||||
|
||||
if (_majorVersion < 2 && _minorVersion < 5)
|
||||
_metaDataComplete = MetaDataComplete.True; // does not apply before 2.5
|
||||
else
|
||||
{
|
||||
String s = (String)_root.getAttribute("metadata-complete");
|
||||
if (s == null)
|
||||
_metaDataComplete = MetaDataComplete.NotSet;
|
||||
else
|
||||
_metaDataComplete = Boolean.valueOf(s).booleanValue()?MetaDataComplete.True:MetaDataComplete.False;
|
||||
}
|
||||
|
||||
Log.debug(_xml.toString()+": Calculated metadatacomplete = " + _metaDataComplete + " with version=" + version);
|
||||
}
|
||||
|
||||
public void processOrdering ()
|
||||
{
|
||||
//Process the web.xml's optional <absolute-ordering> element
|
||||
XmlParser.Node ordering = _root.get("absolute-ordering");
|
||||
if (ordering == null)
|
||||
return;
|
||||
|
||||
_isOrdered = true;
|
||||
//If an absolute-ordering was already set, then ignore it in favour of this new one
|
||||
// _processor.setOrdering(new AbsoluteOrdering());
|
||||
|
||||
Iterator iter = ordering.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
|
||||
if (node.getTag().equalsIgnoreCase("others"))
|
||||
//((AbsoluteOrdering)_processor.getOrdering()).addOthers();
|
||||
_ordering.add("others");
|
||||
else if (node.getTag().equalsIgnoreCase("name"))
|
||||
//((AbsoluteOrdering)_processor.getOrdering()).add(node.toString(false,true));
|
||||
_ordering.add(node.toString(false,true));
|
||||
}
|
||||
}
|
||||
|
||||
public void addClassName (String className)
|
||||
{
|
||||
if (!_classNames.contains(className))
|
||||
_classNames.add(className);
|
||||
}
|
||||
|
||||
public ArrayList<String> getClassNames ()
|
||||
{
|
||||
return _classNames;
|
||||
}
|
||||
|
||||
public void setDistributable (boolean distributable)
|
||||
{
|
||||
_distributable = distributable;
|
||||
}
|
||||
|
||||
public boolean isDistributable()
|
||||
{
|
||||
return _distributable;
|
||||
}
|
||||
|
||||
public void setValidating (boolean validating)
|
||||
{
|
||||
_validating = validating;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOrdered()
|
||||
{
|
||||
return _isOrdered;
|
||||
}
|
||||
|
||||
public List<String> getOrdering()
|
||||
{
|
||||
return _ordering;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
/**
|
||||
* DescriptorProcessor
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface DescriptorProcessor
|
||||
{
|
||||
public void process (Descriptor descriptor) throws Exception;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/**
|
||||
* DiscoveredAnnotation
|
||||
*
|
||||
* Represents an annotation that has been discovered
|
||||
* by scanning source code of WEB-INF/classes and WEB-INF/lib jars.
|
||||
*
|
||||
*/
|
||||
public abstract class DiscoveredAnnotation
|
||||
{
|
||||
protected WebAppContext _context;
|
||||
protected String _className;
|
||||
protected Class _clazz;
|
||||
|
||||
public abstract void apply();
|
||||
|
||||
public DiscoveredAnnotation (WebAppContext context, String className)
|
||||
{
|
||||
_context = context;
|
||||
_className = className;
|
||||
}
|
||||
|
||||
|
||||
public Class getTargetClass()
|
||||
{
|
||||
if (_clazz != null)
|
||||
return _clazz;
|
||||
|
||||
loadClass();
|
||||
|
||||
return _clazz;
|
||||
}
|
||||
|
||||
private void loadClass ()
|
||||
{
|
||||
if (_clazz != null)
|
||||
return;
|
||||
|
||||
if (_className == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_clazz = Loader.loadClass(null, _className);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
/**
|
||||
* FragmentConfiguration
|
||||
*
|
||||
* This configuration supports some Servlet 3.0 features in jetty-7.
|
||||
*
|
||||
*
|
||||
* Process web-fragments in jars
|
||||
*/
|
||||
|
@ -33,20 +33,14 @@ public class FragmentConfiguration implements Configuration
|
|||
{
|
||||
if (!context.isConfigurationDiscovered())
|
||||
return;
|
||||
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException("No metadata");
|
||||
|
||||
//find all web-fragment.xmls
|
||||
findWebFragments(context, metaData);
|
||||
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
|
||||
}
|
||||
|
||||
|
||||
//parse web-fragment.xmls
|
||||
parseWebFragments(context, processor);
|
||||
|
||||
//TODO for jetty-8/servletspec 3 we will need to merge the parsed web fragments into the
|
||||
//effective pom in this preConfigure step
|
||||
}
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
|
@ -54,16 +48,12 @@ public class FragmentConfiguration implements Configuration
|
|||
if (!context.isConfigurationDiscovered())
|
||||
return;
|
||||
|
||||
//TODO for jetty-8/servletspec3 the fragments will not be separately processed here, but
|
||||
//will be done by webXmlConfiguration when it processes the effective merged web.xml
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
|
||||
}
|
||||
|
||||
processor.processFragments();
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException("No metadata");
|
||||
|
||||
//order the fragments
|
||||
metaData.orderFragments();
|
||||
}
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
|
@ -78,20 +68,19 @@ public class FragmentConfiguration implements Configuration
|
|||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Look for any web.xml fragments in META-INF of jars in WEB-INF/lib
|
||||
* Look for any web-fragment.xml fragments in META-INF of jars in WEB-INF/lib
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void parseWebFragments (final WebAppContext context, final WebXmlProcessor processor) throws Exception
|
||||
public void findWebFragments (final WebAppContext context, final MetaData metaData) throws Exception
|
||||
{
|
||||
List<Resource> frags = (List<Resource>)context.getAttribute(FRAGMENT_RESOURCES);
|
||||
if (frags!=null)
|
||||
{
|
||||
for (Resource frag : frags)
|
||||
{
|
||||
processor.parseFragment(Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
|
||||
metaData.addFragment(frag, Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
/**
|
||||
* Fragment
|
||||
*
|
||||
* A web-fragment.xml descriptor.
|
||||
*/
|
||||
public class FragmentDescriptor extends Descriptor
|
||||
{
|
||||
public static final String NAMELESS = "@@-NAMELESS-@@"; //prefix for nameless Fragments
|
||||
public enum OtherType {None, Before, After};
|
||||
|
||||
protected int _counter = 0;
|
||||
protected OtherType _otherType = OtherType.None;
|
||||
|
||||
|
||||
protected List<String> _befores = new ArrayList<String>();
|
||||
protected List<String> _afters = new ArrayList<String>();
|
||||
protected String _name;
|
||||
|
||||
|
||||
public FragmentDescriptor (Resource xml, MetaData processor)
|
||||
throws Exception
|
||||
{
|
||||
super (xml, processor);
|
||||
}
|
||||
|
||||
public String getName ()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void parse ()
|
||||
throws Exception
|
||||
{
|
||||
super.parse();
|
||||
processName();
|
||||
}
|
||||
|
||||
public void processName ()
|
||||
{
|
||||
XmlParser.Node root = getRoot();
|
||||
XmlParser.Node nameNode = root.get("name");
|
||||
_name = NAMELESS+(_counter++);
|
||||
if (nameNode != null)
|
||||
{
|
||||
String tmp = nameNode.toString(false,true);
|
||||
if (tmp!=null && tmp.length()>0)
|
||||
_name = tmp;
|
||||
}
|
||||
}
|
||||
public void processOrdering ()
|
||||
{
|
||||
//Process a fragment jar's web-fragment.xml<ordering> elements
|
||||
XmlParser.Node root = getRoot();
|
||||
|
||||
XmlParser.Node ordering = root.get("ordering");
|
||||
if (ordering == null)
|
||||
return; //No ordering for this fragment
|
||||
|
||||
_isOrdered = true;
|
||||
|
||||
processBefores(ordering);
|
||||
processAfters(ordering);
|
||||
}
|
||||
|
||||
|
||||
public void processBefores (XmlParser.Node ordering)
|
||||
{
|
||||
//Process the <before> elements, looking for an <others/> clause and all of the <name> clauses
|
||||
XmlParser.Node before = ordering.get("before");
|
||||
if (before == null)
|
||||
return;
|
||||
|
||||
Iterator iter = before.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
if (node.getTag().equalsIgnoreCase("others"))
|
||||
{
|
||||
if (_otherType != OtherType.None)
|
||||
throw new IllegalStateException("Duplicate <other> clause detected in "+_xml.getURI());
|
||||
|
||||
_otherType = OtherType.Before;
|
||||
}
|
||||
else if (node.getTag().equalsIgnoreCase("name"))
|
||||
_befores.add(node.toString(false,true));
|
||||
}
|
||||
}
|
||||
|
||||
public void processAfters (XmlParser.Node ordering)
|
||||
{
|
||||
//Process the <after> elements, look for an <others/> clause and all of the <name/> clauses
|
||||
XmlParser.Node after = ordering.get("after");
|
||||
if (after == null)
|
||||
return;
|
||||
|
||||
Iterator iter = after.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
if (node.getTag().equalsIgnoreCase("others"))
|
||||
{
|
||||
if (_otherType != OtherType.After)
|
||||
throw new IllegalStateException("Duplicate <other> clause detected in "+_xml.getURI());
|
||||
|
||||
_otherType = OtherType.After;
|
||||
|
||||
}
|
||||
else if (node.getTag().equalsIgnoreCase("name"))
|
||||
_afters.add(node.toString(false,true));
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getBefores()
|
||||
{
|
||||
return Collections.unmodifiableList(_befores);
|
||||
}
|
||||
|
||||
public List<String> getAfters()
|
||||
{
|
||||
return Collections.unmodifiableList(_afters);
|
||||
}
|
||||
|
||||
public OtherType getOtherType ()
|
||||
{
|
||||
return _otherType;
|
||||
}
|
||||
|
||||
public List<String> getOrdering()
|
||||
{
|
||||
return null; //only used for absolute-ordering in Descriptor
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
/**
|
||||
* IterativeDescriptorProcessor
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class IterativeDescriptorProcessor implements DescriptorProcessor
|
||||
{
|
||||
public static final Class[] __signature = new Class[]{Descriptor.class, XmlParser.Node.class};
|
||||
protected Map<String, Method> _visitors = new HashMap<String, Method>();
|
||||
public abstract void start(Descriptor descriptor);
|
||||
public abstract void end(Descriptor descriptor);
|
||||
|
||||
/**
|
||||
* Register a method to be called back when visiting the node with the given name.
|
||||
* The method must exist on a subclass of this class, and must have the signature:
|
||||
* public void method (Descriptor descriptor, XmlParser.Node node)
|
||||
* @param nodeName
|
||||
* @param m
|
||||
*/
|
||||
public void registerVisitor(String nodeName, Method m)
|
||||
{
|
||||
_visitors.put(nodeName, m);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.DescriptorProcessor#process(org.eclipse.jetty.webapp.Descriptor)
|
||||
*/
|
||||
public void process(Descriptor descriptor)
|
||||
throws Exception
|
||||
{
|
||||
if (descriptor == null)
|
||||
return;
|
||||
|
||||
start(descriptor);
|
||||
|
||||
XmlParser.Node root = descriptor.getRoot();
|
||||
Iterator iter = root.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
visit(descriptor, node);
|
||||
}
|
||||
|
||||
end(descriptor);
|
||||
}
|
||||
|
||||
|
||||
protected void visit (final Descriptor descriptor, final XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String name = node.getTag();
|
||||
Method m = _visitors.get(name);
|
||||
if (m != null)
|
||||
m.invoke(this, new Object[]{descriptor, node});
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ import org.eclipse.jetty.xml.XmlConfiguration;
|
|||
*
|
||||
* JettyWebConfiguration.
|
||||
*
|
||||
* Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jetty6-web.xml, jetty-web.xml or web-jetty.xml
|
||||
* Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jettyX-web.xml, jetty-web.xml or web-jetty.xml
|
||||
*
|
||||
*
|
||||
*
|
||||
|
|
|
@ -0,0 +1,911 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MetaData
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MetaData
|
||||
{
|
||||
public static final String METADATA = "org.eclipse.jetty.metaData";
|
||||
public static final String METADATA_COMPLETE = "org.eclipse.jetty.metadataComplete";
|
||||
public static final String WEBXML_MAJOR_VERSION = "org.eclipse.jetty.webXmlMajorVersion";
|
||||
public static final String WEBXML_MINOR_VERSION = "org.eclipse.jetty.webXmlMinorVersion";
|
||||
public static final String WEBXML_CLASSNAMES = "org.eclipse.jetty.webXmlClassNames";
|
||||
public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
|
||||
|
||||
public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation};
|
||||
|
||||
protected WebAppContext _context;
|
||||
protected Map<String, OriginInfo> _origins = new HashMap<String,OriginInfo>();
|
||||
protected Descriptor _webDefaultsRoot;
|
||||
protected Descriptor _webXmlRoot;
|
||||
protected Descriptor _webOverrideRoot;
|
||||
protected List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
|
||||
protected List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
|
||||
protected List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
|
||||
protected Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
|
||||
protected Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
|
||||
protected Map<Resource, List<DiscoveredAnnotation>> _webFragmentAnnotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
|
||||
protected List<Resource> _orderedResources;
|
||||
protected Ordering _ordering;//can be set to RelativeOrdering by web-default.xml, web.xml, web-override.xml
|
||||
protected StandardDescriptorProcessor _standardDescriptorProcessor;
|
||||
|
||||
|
||||
public static class OriginInfo
|
||||
{
|
||||
protected String name;
|
||||
protected Origin origin;
|
||||
protected Descriptor descriptor;
|
||||
|
||||
public OriginInfo (String n, Descriptor d)
|
||||
{
|
||||
name = n;
|
||||
descriptor = d;
|
||||
if (d == null)
|
||||
throw new IllegalArgumentException("No descriptor");
|
||||
if (d instanceof FragmentDescriptor)
|
||||
origin = Origin.WebFragment;
|
||||
if (d instanceof OverrideDescriptor)
|
||||
origin = Origin.WebOverride;
|
||||
if (d instanceof DefaultsDescriptor)
|
||||
origin = Origin.WebDefaults;
|
||||
origin = Origin.WebXml;
|
||||
}
|
||||
|
||||
public OriginInfo (String n)
|
||||
{
|
||||
name = n;
|
||||
origin = Origin.Annotation;
|
||||
}
|
||||
|
||||
public OriginInfo(String n, Origin o)
|
||||
{
|
||||
name = n;
|
||||
origin = o;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public Origin getOriginType()
|
||||
{
|
||||
return origin;
|
||||
}
|
||||
|
||||
public Descriptor getDescriptor()
|
||||
{
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ordering
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface Ordering
|
||||
{
|
||||
public List<Resource> order(List<Resource> fragments);
|
||||
public boolean isAbsolute ();
|
||||
public boolean hasOther();
|
||||
}
|
||||
|
||||
/**
|
||||
* AbsoluteOrdering
|
||||
*
|
||||
* An <absolute-order> element in web.xml
|
||||
*/
|
||||
public class AbsoluteOrdering implements Ordering
|
||||
{
|
||||
public static final String OTHER = "@@-OTHER-@@";
|
||||
protected List<String> _order = new ArrayList<String>();
|
||||
protected boolean _hasOther = false;
|
||||
|
||||
/**
|
||||
* Order the list of jars in WEB-INF/lib according to the ordering declarations in the descriptors
|
||||
* @see org.eclipse.jetty.webapp.MetaData.Ordering#order(java.util.List)
|
||||
*/
|
||||
public List<Resource> order(List<Resource> jars)
|
||||
{
|
||||
List<Resource> orderedList = new ArrayList<Resource>();
|
||||
List<Resource> tmp = new ArrayList<Resource>(jars);
|
||||
|
||||
//1. put everything into the list of named others, and take the named ones out of there,
|
||||
//assuming we will want to use the <other> clause
|
||||
Map<String,FragmentDescriptor> others = new HashMap(getNamedFragments());
|
||||
|
||||
//2. for each name, take out of the list of others, add to tail of list
|
||||
int index = -1;
|
||||
for (String item:_order)
|
||||
{
|
||||
if (!item.equals(OTHER))
|
||||
{
|
||||
FragmentDescriptor f = others.remove(item);
|
||||
if (f != null)
|
||||
{
|
||||
Resource jar = getJarForFragment(item);
|
||||
orderedList.add(jar); //take from others and put into final list in order, ignoring duplicate names
|
||||
//remove resource from list for resource matching name of descriptor
|
||||
tmp.remove(jar);
|
||||
}
|
||||
}
|
||||
else
|
||||
index = orderedList.size(); //remember the index at which we want to add in all the others
|
||||
}
|
||||
|
||||
//3. if <other> was specified, insert rest of the fragments
|
||||
if (_hasOther)
|
||||
{
|
||||
orderedList.addAll((index < 0? 0: index), tmp);
|
||||
}
|
||||
|
||||
return orderedList;
|
||||
}
|
||||
|
||||
public boolean isAbsolute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void add (String name)
|
||||
{
|
||||
_order.add(name);
|
||||
}
|
||||
|
||||
public void addOthers ()
|
||||
{
|
||||
if (_hasOther)
|
||||
throw new IllegalStateException ("Duplicate <other> element in absolute ordering");
|
||||
|
||||
_hasOther = true;
|
||||
_order.add(OTHER);
|
||||
}
|
||||
|
||||
public boolean hasOther ()
|
||||
{
|
||||
return _hasOther;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* RelativeOrdering
|
||||
*
|
||||
* A set of <order> elements in web-fragment.xmls.
|
||||
*/
|
||||
public class RelativeOrdering implements Ordering
|
||||
{
|
||||
protected LinkedList<Resource> _beforeOthers = new LinkedList<Resource>();
|
||||
protected LinkedList<Resource> _afterOthers = new LinkedList<Resource>();
|
||||
protected LinkedList<Resource> _noOthers = new LinkedList<Resource>();
|
||||
|
||||
/**
|
||||
* Order the list of jars according to the ordering declared
|
||||
* in the various web-fragment.xml files.
|
||||
* @see org.eclipse.jetty.webapp.MetaData.Ordering#order(java.util.List)
|
||||
*/
|
||||
public List<Resource> order(List<Resource> jars)
|
||||
{
|
||||
//for each jar, put it into the ordering according to the fragment ordering
|
||||
for (Resource jar:jars)
|
||||
{
|
||||
//check if the jar has a fragment descriptor
|
||||
FragmentDescriptor descriptor = _webFragmentResourceMap.get(jar);
|
||||
if (descriptor != null)
|
||||
{
|
||||
switch (descriptor.getOtherType())
|
||||
{
|
||||
case None:
|
||||
{
|
||||
((RelativeOrdering)_ordering).addNoOthers(jar);
|
||||
break;
|
||||
}
|
||||
case Before:
|
||||
{
|
||||
((RelativeOrdering)_ordering).addBeforeOthers(jar);
|
||||
break;
|
||||
}
|
||||
case After:
|
||||
{
|
||||
((RelativeOrdering)_ordering).addAfterOthers(jar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//jar fragment has no descriptor, but there is a relative ordering in place, so it must be part of the others
|
||||
((RelativeOrdering)_ordering).addNoOthers(jar);
|
||||
}
|
||||
}
|
||||
|
||||
//now apply the ordering
|
||||
List<Resource> orderedList = new ArrayList<Resource>();
|
||||
int maxIterations = 2;
|
||||
boolean done = false;
|
||||
do
|
||||
{
|
||||
//1. order the before-others according to any explicit before/after relationships
|
||||
boolean changesBefore = orderList(_beforeOthers);
|
||||
|
||||
//2. order the after-others according to any explicit before/after relationships
|
||||
boolean changesAfter = orderList(_afterOthers);
|
||||
|
||||
//3. order the no-others according to their explicit before/after relationships
|
||||
boolean changesNone = orderList(_noOthers);
|
||||
|
||||
//we're finished on a clean pass through with no ordering changes
|
||||
done = (!changesBefore && !changesAfter && !changesNone);
|
||||
}
|
||||
while (!done && (--maxIterations >0));
|
||||
|
||||
//4. merge before-others + no-others +after-others
|
||||
if (!done)
|
||||
throw new IllegalStateException("Circular references for fragments");
|
||||
|
||||
for (Resource r: _beforeOthers)
|
||||
orderedList.add(r);
|
||||
for (Resource r: _noOthers)
|
||||
orderedList.add(r);
|
||||
for(Resource r: _afterOthers)
|
||||
orderedList.add(r);
|
||||
|
||||
return orderedList;
|
||||
}
|
||||
|
||||
public boolean isAbsolute ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasOther ()
|
||||
{
|
||||
return !_beforeOthers.isEmpty() || !_afterOthers.isEmpty();
|
||||
}
|
||||
|
||||
public void addBeforeOthers (Resource r)
|
||||
{
|
||||
_beforeOthers.addLast(r);
|
||||
}
|
||||
|
||||
public void addAfterOthers (Resource r)
|
||||
{
|
||||
_afterOthers.addLast(r);
|
||||
}
|
||||
|
||||
public void addNoOthers (Resource r)
|
||||
{
|
||||
_noOthers.addLast(r);
|
||||
}
|
||||
|
||||
protected boolean orderList (LinkedList<Resource> list)
|
||||
{
|
||||
//Take a copy of the list so we can iterate over it and at the same time do random insertions
|
||||
boolean changes = false;
|
||||
List<Resource> iterable = new ArrayList(list);
|
||||
Iterator<Resource> itor = iterable.iterator();
|
||||
|
||||
while (itor.hasNext())
|
||||
{
|
||||
Resource r = itor.next();
|
||||
FragmentDescriptor f = getFragment(r);
|
||||
if (f == null)
|
||||
{
|
||||
//no fragment for this resource so cannot have any ordering directives
|
||||
continue;
|
||||
}
|
||||
|
||||
//Handle any explicit <before> relationships for the fragment we're considering
|
||||
List<String> befores = f.getBefores();
|
||||
if (befores != null && !befores.isEmpty())
|
||||
{
|
||||
for (String b: befores)
|
||||
{
|
||||
//Fragment we're considering must be before b
|
||||
//Check that we are already before it, if not, move us so that we are.
|
||||
//If the name does not exist in our list, then get it out of the no-other list
|
||||
if (!isBefore(list, f.getName(), b))
|
||||
{
|
||||
//b is not already before name, move it so that it is
|
||||
int idx1 = getIndexOf(list, f.getName());
|
||||
int idx2 = getIndexOf(list, b);
|
||||
|
||||
//if b is not in the same list
|
||||
if (idx2 < 0)
|
||||
{
|
||||
changes = true;
|
||||
// must be in the noOthers list or it would have been an error
|
||||
Resource bResource = getJarForFragment(b);
|
||||
if (bResource != null)
|
||||
{
|
||||
//If its in the no-others list, insert into this list so that we are before it
|
||||
if (_noOthers.remove(bResource))
|
||||
{
|
||||
insert(list, idx1+1, b);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//b is in the same list but b is before name, so swap it around
|
||||
list.remove(idx1);
|
||||
insert(list, idx2, f.getName());
|
||||
changes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Handle any explicit <after> relationships
|
||||
List<String> afters = f.getAfters();
|
||||
if (afters != null && !afters.isEmpty())
|
||||
{
|
||||
for (String a: afters)
|
||||
{
|
||||
//Check that fragment we're considering is after a, moving it if possible if its not
|
||||
if (!isAfter(list, f.getName(), a))
|
||||
{
|
||||
//name is not after a, move it
|
||||
int idx1 = getIndexOf(list, f.getName());
|
||||
int idx2 = getIndexOf(list, a);
|
||||
|
||||
//if a is not in the same list as name
|
||||
if (idx2 < 0)
|
||||
{
|
||||
changes = true;
|
||||
//take it out of the noOthers list and put it in the right place in this list
|
||||
Resource aResource = getJarForFragment(a);
|
||||
if (aResource != null)
|
||||
{
|
||||
if (_noOthers.remove(aResource))
|
||||
{
|
||||
insert(list,idx1, aResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//a is in the same list as name, but in the wrong place, so move it
|
||||
list.remove(idx2);
|
||||
insert(list,idx1, a);
|
||||
changes = true;
|
||||
}
|
||||
}
|
||||
//Name we're considering must be after this name
|
||||
//Check we're already after it, if not, move us so that we are.
|
||||
//If the name does not exist in our list, then get it out of the no-other list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is fragment with name a before fragment with name b?
|
||||
* @param list
|
||||
* @param fragNameA
|
||||
* @param fragNameB
|
||||
* @return
|
||||
*/
|
||||
protected boolean isBefore (List<Resource> list, String fragNameA, String fragNameB)
|
||||
{
|
||||
//check if a and b are already in the same list, and b is already
|
||||
//before a
|
||||
int idxa = getIndexOf(list, fragNameA);
|
||||
int idxb = getIndexOf(list, fragNameB);
|
||||
|
||||
|
||||
if (idxb >=0 && idxb < idxa)
|
||||
{
|
||||
//a and b are in the same list but a is not before b
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idxb < 0)
|
||||
{
|
||||
//a and b are not in the same list, but it is still possible that a is before
|
||||
//b, depending on which list we're examining
|
||||
if (list == _beforeOthers)
|
||||
{
|
||||
//The list we're looking at is the beforeOthers.If b is in the _afterOthers or the _noOthers, then by
|
||||
//definition a is before it
|
||||
return true;
|
||||
}
|
||||
else if (list == _afterOthers)
|
||||
{
|
||||
//The list we're looking at is the afterOthers, then a will be the tail of
|
||||
//the final list. If b is in the beforeOthers list, then b will be before a and an error.
|
||||
if (_beforeOthers.contains(fragNameB))
|
||||
throw new IllegalStateException("Incorrect relationship: "+fragNameA+" before "+fragNameB);
|
||||
else
|
||||
return false; //b could be moved to the list
|
||||
}
|
||||
}
|
||||
|
||||
//a and b are in the same list and a is already before b
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is fragment name "a" after fragment name "b"?
|
||||
* @param list
|
||||
* @param fragNameA
|
||||
* @param fragNameB
|
||||
* @return
|
||||
*/
|
||||
protected boolean isAfter(List<Resource> list, String fragNameA, String fragNameB)
|
||||
{
|
||||
int idxa = getIndexOf(list, fragNameA);
|
||||
int idxb = getIndexOf(list, fragNameB);
|
||||
|
||||
if (idxb >=0 && idxa < idxb)
|
||||
{
|
||||
//a and b are both in the same list, but a is before b
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idxb < 0)
|
||||
{
|
||||
//a and b are in different lists. a could still be after b depending on which list it is in.
|
||||
|
||||
if (list == _afterOthers)
|
||||
{
|
||||
//The list we're looking at is the afterOthers. If b is in the beforeOthers or noOthers then
|
||||
//by definition a is after b because a is in the afterOthers list.
|
||||
return true;
|
||||
}
|
||||
else if (list == _beforeOthers)
|
||||
{
|
||||
//The list we're looking at is beforeOthers, and contains a and will be before
|
||||
//everything else in the final ist. If b is in the afterOthers list, then a cannot be before b.
|
||||
if (_afterOthers.contains(fragNameB))
|
||||
throw new IllegalStateException("Incorrect relationship: "+fragNameB+" after "+fragNameA);
|
||||
else
|
||||
return false; //b could be moved from noOthers list
|
||||
}
|
||||
}
|
||||
|
||||
return true; //a and b in the same list, a is after b
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the resource matching the fragName into the list of resources
|
||||
* at the location indicated by index.
|
||||
*
|
||||
* @param list
|
||||
* @param index
|
||||
* @param fragName
|
||||
*/
|
||||
protected void insert(List<Resource> list, int index, String fragName)
|
||||
{
|
||||
Resource jar = getJarForFragment(fragName);
|
||||
if (jar == null)
|
||||
throw new IllegalStateException("No jar for insertion");
|
||||
|
||||
insert(list, index, jar);
|
||||
}
|
||||
|
||||
protected void insert(List<Resource> list, int index, Resource resource)
|
||||
{
|
||||
if (list == null)
|
||||
throw new IllegalStateException("List is null for insertion");
|
||||
|
||||
//add it at the end
|
||||
if (index > list.size())
|
||||
list.add(resource);
|
||||
else
|
||||
list.add(index, resource);
|
||||
}
|
||||
|
||||
protected void remove (List<Resource> resources, Resource r)
|
||||
{
|
||||
if (resources == null)
|
||||
return;
|
||||
resources.remove(r);
|
||||
}
|
||||
|
||||
protected int getIndexOf(List<Resource> resources, String fragmentName)
|
||||
{
|
||||
FragmentDescriptor fd = getFragment(fragmentName);
|
||||
if (fd == null)
|
||||
return -1;
|
||||
|
||||
|
||||
Resource r = getJarForFragment(fragmentName);
|
||||
if (r == null)
|
||||
return -1;
|
||||
|
||||
return resources.indexOf(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public MetaData (WebAppContext context) throws ClassNotFoundException
|
||||
{
|
||||
_context = context;
|
||||
|
||||
}
|
||||
|
||||
public WebAppContext getContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setDefaults (Resource webDefaults)
|
||||
throws Exception
|
||||
{
|
||||
_webDefaultsRoot = new DefaultsDescriptor(webDefaults, this);
|
||||
_webDefaultsRoot.parse();
|
||||
if (_webDefaultsRoot.isOrdered())
|
||||
{
|
||||
if (_ordering == null)
|
||||
_ordering = new AbsoluteOrdering();
|
||||
|
||||
List<String> order = _webDefaultsRoot.getOrdering();
|
||||
for (String s:order)
|
||||
{
|
||||
if (s.equalsIgnoreCase("others"))
|
||||
((AbsoluteOrdering)_ordering).addOthers();
|
||||
else
|
||||
((AbsoluteOrdering)_ordering).add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setWebXml (Resource webXml)
|
||||
throws Exception
|
||||
{
|
||||
_webXmlRoot = new Descriptor(webXml, this);
|
||||
_webXmlRoot.parse();
|
||||
if (_webXmlRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.True)
|
||||
_context.setAttribute(METADATA_COMPLETE, Boolean.TRUE);
|
||||
else
|
||||
_context.setAttribute(METADATA_COMPLETE, Boolean.FALSE);
|
||||
|
||||
_context.setAttribute(WEBXML_CLASSNAMES, _webXmlRoot.getClassNames());
|
||||
|
||||
if (_webXmlRoot.isOrdered())
|
||||
{
|
||||
if (_ordering == null)
|
||||
_ordering = new AbsoluteOrdering();
|
||||
|
||||
List<String> order = _webXmlRoot.getOrdering();
|
||||
for (String s:order)
|
||||
{
|
||||
if (s.equalsIgnoreCase("others"))
|
||||
((AbsoluteOrdering)_ordering).addOthers();
|
||||
else
|
||||
((AbsoluteOrdering)_ordering).add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOverride (Resource override)
|
||||
throws Exception
|
||||
{
|
||||
_webOverrideRoot = new OverrideDescriptor(override, this);
|
||||
_webOverrideRoot.setValidating(false);
|
||||
_webOverrideRoot.parse();
|
||||
if (_webOverrideRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.True)
|
||||
_context.setAttribute(METADATA_COMPLETE, Boolean.TRUE);
|
||||
else if (_webOverrideRoot.getMetaDataComplete() == Descriptor.MetaDataComplete.False)
|
||||
_context.setAttribute(METADATA_COMPLETE, Boolean.FALSE);
|
||||
|
||||
if (_webOverrideRoot.isOrdered())
|
||||
{
|
||||
if (_ordering == null)
|
||||
_ordering = new AbsoluteOrdering();
|
||||
|
||||
List<String> order = _webOverrideRoot.getOrdering();
|
||||
for (String s:order)
|
||||
{
|
||||
if (s.equalsIgnoreCase("others"))
|
||||
((AbsoluteOrdering)_ordering).addOthers();
|
||||
else
|
||||
((AbsoluteOrdering)_ordering).add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a web-fragment.xml
|
||||
*
|
||||
* @param jarResource the jar the fragment is contained in
|
||||
* @param xmlResource the resource representing the xml file
|
||||
* @throws Exception
|
||||
*/
|
||||
public void addFragment (Resource jarResource, Resource xmlResource)
|
||||
throws Exception
|
||||
{
|
||||
Boolean metaComplete = (Boolean)_context.getAttribute(METADATA_COMPLETE);
|
||||
if (metaComplete != null && metaComplete.booleanValue())
|
||||
return; //do not process anything else if web.xml/web-override.xml set metadata-complete
|
||||
|
||||
//Metadata-complete is not set, or there is no web.xml
|
||||
FragmentDescriptor descriptor = new FragmentDescriptor(xmlResource, this);
|
||||
_webFragmentResourceMap.put(jarResource, descriptor);
|
||||
_webFragmentRoots.add(descriptor);
|
||||
|
||||
descriptor.parse();
|
||||
|
||||
if (descriptor.getName() != null)
|
||||
_webFragmentNameMap.put(descriptor.getName(), descriptor);
|
||||
|
||||
//If web.xml has specified an absolute ordering, ignore any relative ordering in the fragment
|
||||
if (_ordering != null && _ordering.isAbsolute())
|
||||
return;
|
||||
|
||||
if (_ordering == null && descriptor.isOrdered())
|
||||
_ordering = new RelativeOrdering();
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotations not associated with a WEB-INF/lib fragment jar.
|
||||
* These are from WEB-INF/classes or the ??container path??
|
||||
* @param annotations
|
||||
*/
|
||||
public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
|
||||
{
|
||||
_annotations.addAll(annotations);
|
||||
}
|
||||
|
||||
public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
|
||||
{
|
||||
_webFragmentAnnotations.put(resource, new ArrayList<DiscoveredAnnotation>(annotations));
|
||||
}
|
||||
|
||||
public void addDescriptorProcessor(DescriptorProcessor p)
|
||||
{
|
||||
_descriptorProcessors.add(p);
|
||||
}
|
||||
|
||||
public void orderFragments ()
|
||||
{
|
||||
//if we have already ordered them don't do it again
|
||||
if (_orderedResources != null)
|
||||
return;
|
||||
|
||||
if (_ordering != null)
|
||||
{
|
||||
//Get the jars in WEB-INF/lib according to the order specified
|
||||
_orderedResources = _ordering.order((List<Resource>)_context.getAttribute(WebInfConfiguration.WEB_INF_JAR_RESOURCES));
|
||||
|
||||
_context.setAttribute(WebInfConfiguration.WEB_INF_ORDERED_JAR_RESOURCES, _orderedResources);
|
||||
List<String> orderedJars = new ArrayList<String>();
|
||||
|
||||
for (Resource webInfJar:_orderedResources)
|
||||
{
|
||||
//get just the name of the jar file
|
||||
String fullname = webInfJar.getName();
|
||||
int i = fullname.indexOf(".jar");
|
||||
int j = fullname.lastIndexOf("/", i);
|
||||
orderedJars.add(fullname.substring(j+1,i+4));
|
||||
}
|
||||
|
||||
_context.setAttribute(ORDERED_LIBS, orderedJars);
|
||||
}
|
||||
else
|
||||
_orderedResources = new ArrayList<Resource>((List<Resource>)_context.getAttribute(WebInfConfiguration.WEB_INF_JAR_RESOURCES));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve all servlet/filter/listener metadata from all sources: descriptors and annotations.
|
||||
*
|
||||
*/
|
||||
public void resolve ()
|
||||
throws Exception
|
||||
{
|
||||
//TODO - apply all descriptors and annotations in order:
|
||||
//apply descriptorProcessors to web-defaults.xml
|
||||
//apply descriptorProcessors to web.xml
|
||||
//apply descriptorProcessors to web-override.xml
|
||||
//apply discovered annotations from container path
|
||||
//apply discovered annotations from WEB-INF/classes
|
||||
//for the ordering of the jars in WEB-INF/lib:
|
||||
// +apply descriptorProcessors to web-fragment.xml
|
||||
// +apply discovered annotations
|
||||
|
||||
for (DescriptorProcessor p:_descriptorProcessors)
|
||||
{
|
||||
p.process(getWebDefault());
|
||||
p.process(getWebXml());
|
||||
p.process(getOverrideWeb());
|
||||
}
|
||||
|
||||
for (DiscoveredAnnotation a:_annotations)
|
||||
a.apply();
|
||||
|
||||
|
||||
List<Resource> resources = getOrderedResources();
|
||||
for (Resource r:resources)
|
||||
{
|
||||
FragmentDescriptor fd = _webFragmentResourceMap.get(r);
|
||||
if (fd != null)
|
||||
{
|
||||
for (DescriptorProcessor p:_descriptorProcessors)
|
||||
{
|
||||
p.process(fd);
|
||||
}
|
||||
}
|
||||
|
||||
List<DiscoveredAnnotation> fragAnnotations = _webFragmentAnnotations.get(r);
|
||||
if (fragAnnotations != null)
|
||||
{
|
||||
for (DiscoveredAnnotation a:fragAnnotations)
|
||||
a.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDistributable ()
|
||||
{
|
||||
boolean distributable = (
|
||||
(_webDefaultsRoot != null && _webDefaultsRoot.isDistributable())
|
||||
|| (_webXmlRoot != null && _webXmlRoot.isDistributable())
|
||||
|| (_webOverrideRoot != null && _webOverrideRoot.isDistributable()));
|
||||
|
||||
List<Resource> orderedResources = getOrderedResources();
|
||||
for (Resource r: orderedResources)
|
||||
{
|
||||
FragmentDescriptor d = _webFragmentResourceMap.get(r);
|
||||
if (d!=null)
|
||||
distributable = distributable && d.isDistributable();
|
||||
}
|
||||
return distributable;
|
||||
}
|
||||
|
||||
|
||||
public Descriptor getWebXml ()
|
||||
{
|
||||
return _webXmlRoot;
|
||||
}
|
||||
|
||||
public Descriptor getOverrideWeb ()
|
||||
{
|
||||
return _webOverrideRoot;
|
||||
}
|
||||
|
||||
public Descriptor getWebDefault ()
|
||||
{
|
||||
return _webDefaultsRoot;
|
||||
}
|
||||
|
||||
public List<FragmentDescriptor> getFragments ()
|
||||
{
|
||||
return _webFragmentRoots;
|
||||
}
|
||||
|
||||
public List<Resource> getOrderedResources ()
|
||||
{
|
||||
return _orderedResources;
|
||||
}
|
||||
|
||||
public List<FragmentDescriptor> getOrderedFragments ()
|
||||
{
|
||||
List<FragmentDescriptor> list = new ArrayList<FragmentDescriptor>();
|
||||
if (_orderedResources == null)
|
||||
return list;
|
||||
|
||||
for (Resource r:_orderedResources)
|
||||
{
|
||||
FragmentDescriptor fd = _webFragmentResourceMap.get(r);
|
||||
if (fd != null)
|
||||
list.add(fd);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Ordering getOrdering()
|
||||
{
|
||||
return _ordering;
|
||||
}
|
||||
|
||||
public void setOrdering (Ordering o)
|
||||
{
|
||||
_ordering = o;
|
||||
}
|
||||
|
||||
public FragmentDescriptor getFragment (Resource jar)
|
||||
{
|
||||
return _webFragmentResourceMap.get(jar);
|
||||
}
|
||||
|
||||
public FragmentDescriptor getFragment(String name)
|
||||
{
|
||||
return _webFragmentNameMap.get(name);
|
||||
}
|
||||
|
||||
public Resource getJarForFragment (String name)
|
||||
{
|
||||
FragmentDescriptor f = getFragment(name);
|
||||
if (f == null)
|
||||
return null;
|
||||
|
||||
Resource jar = null;
|
||||
for (Resource r: _webFragmentResourceMap.keySet())
|
||||
{
|
||||
if (_webFragmentResourceMap.get(r).equals(f))
|
||||
jar = r;
|
||||
}
|
||||
return jar;
|
||||
}
|
||||
|
||||
public Map<String,FragmentDescriptor> getNamedFragments ()
|
||||
{
|
||||
return Collections.unmodifiableMap(_webFragmentNameMap);
|
||||
}
|
||||
|
||||
|
||||
public Origin getOrigin (String name)
|
||||
{
|
||||
OriginInfo x = _origins.get(name);
|
||||
if (x == null)
|
||||
return Origin.NotSet;
|
||||
|
||||
return x.getOriginType();
|
||||
}
|
||||
|
||||
|
||||
public Descriptor getOriginDescriptor (String name)
|
||||
{
|
||||
OriginInfo o = _origins.get(name);
|
||||
if (o == null)
|
||||
return null;
|
||||
return o.getDescriptor();
|
||||
}
|
||||
|
||||
public void setOrigin (String name, Descriptor d)
|
||||
{
|
||||
OriginInfo x = new OriginInfo (name, d);
|
||||
_origins.put(name, x);
|
||||
}
|
||||
|
||||
public void setOrigin (String name)
|
||||
{
|
||||
if (name == null)
|
||||
return;
|
||||
|
||||
OriginInfo x = new OriginInfo (name, Origin.Annotation);
|
||||
_origins.put(name, x);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* OverrideDescriptor
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class OverrideDescriptor extends Descriptor
|
||||
{
|
||||
public OverrideDescriptor(Resource xml, MetaData processor)
|
||||
{
|
||||
super(xml, processor);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -45,7 +45,8 @@ import org.eclipse.jetty.xml.XmlParser;
|
|||
* </bile>
|
||||
*
|
||||
*
|
||||
*
|
||||
* TODO - this has been superceded by the new TldScanner in jasper which uses ServletContainerInitializer to
|
||||
* find all the listeners in tag libs and register them.
|
||||
*/
|
||||
public class TagLibConfiguration implements Configuration
|
||||
{
|
||||
|
|
|
@ -371,11 +371,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
|
||||
|
||||
// Prepare for configuration
|
||||
// Prepare for configuration
|
||||
//Make a new MetaData to hold descriptor and annotation metadata
|
||||
MetaData metadata = new MetaData(this);
|
||||
setAttribute(MetaData.METADATA, metadata);
|
||||
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].preConfigure(this);
|
||||
|
||||
super.doStart();
|
||||
|
||||
|
||||
// Clean up after configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
|
@ -986,12 +991,12 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
protected void startContext()
|
||||
throws Exception
|
||||
{
|
||||
|
||||
|
||||
// Configure webapp
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].configure(this);
|
||||
|
||||
|
||||
//resolve the metadata
|
||||
((MetaData)getAttribute(MetaData.METADATA)).resolve();
|
||||
|
||||
super.startContext();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public class WebInfConfiguration implements Configuration
|
|||
public static final String TEMPDIR_CREATED = "org.eclipse.jetty.tmpdirCreated";
|
||||
public static final String CONTAINER_JAR_RESOURCES = "org.eclipse.jetty.containerJars";
|
||||
public static final String WEB_INF_JAR_RESOURCES = "org.eclipse.jetty.webInfJars";
|
||||
public static final String WEB_INF_ORDERED_JAR_RESOURCES = "org.eclipse.jetty.webInfOrderedJars";
|
||||
public static final String CONTAINER_JAR_PATTERN = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
|
||||
public static final String WEBINF_JAR_PATTERN = "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern";
|
||||
|
||||
|
@ -96,6 +97,7 @@ public class WebInfConfiguration implements Configuration
|
|||
}
|
||||
};
|
||||
List<Resource> jars = findJars(context);
|
||||
|
||||
//Convert to uris for matching
|
||||
URI[] uris = null;
|
||||
if (jars != null)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// Copyright (c) 2003-2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
|
@ -34,52 +34,50 @@ public class WebXmlConfiguration implements Configuration
|
|||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Process webdefaults.xml
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void preConfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
// cannot configure if the context is already started
|
||||
if (context.isStarted())
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
{
|
||||
Log.debug("Cannot configure webapp after it is started");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//Get or create a processor to handle webdefaults, web.xml and the fragments
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
|
||||
}
|
||||
|
||||
//handle webdefault.xml
|
||||
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException("No metadata");
|
||||
|
||||
|
||||
//parse webdefault.xml
|
||||
String defaultsDescriptor = context.getDefaultsDescriptor();
|
||||
if (defaultsDescriptor != null && defaultsDescriptor.length() > 0)
|
||||
{
|
||||
Resource dftResource = Resource.newSystemResource(defaultsDescriptor);
|
||||
if (dftResource == null)
|
||||
dftResource = context.newResource(defaultsDescriptor);
|
||||
processor.parseDefaults (dftResource);
|
||||
processor.processDefaults();
|
||||
metaData.setDefaults (dftResource);
|
||||
|
||||
}
|
||||
|
||||
//parse, but don't process web.xml
|
||||
Resource webxml = findWebXml(context);
|
||||
if (webxml != null)
|
||||
{
|
||||
processor.parseWebXml(webxml);
|
||||
metaData.setWebXml(webxml);
|
||||
}
|
||||
|
||||
//parse but don't process override-web.xml
|
||||
String overrideDescriptor = context.getOverrideDescriptor();
|
||||
if (overrideDescriptor != null && overrideDescriptor.length() > 0)
|
||||
{
|
||||
Resource orideResource = Resource.newSystemResource(overrideDescriptor);
|
||||
if (orideResource == null)
|
||||
orideResource = context.newResource(overrideDescriptor);
|
||||
metaData.setOverride(orideResource);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Process web.xml, web-fragment.xml(s), override-web.xml
|
||||
* Process web-default.xml, web.xml, override-web.xml
|
||||
*
|
||||
*/
|
||||
public void configure (WebAppContext context) throws Exception
|
||||
|
@ -90,35 +88,35 @@ public class WebXmlConfiguration implements Configuration
|
|||
if (Log.isDebugEnabled()) Log.debug("Cannot configure webapp after it is started");
|
||||
return;
|
||||
}
|
||||
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
|
||||
}
|
||||
|
||||
//process web.xml (the effective web.xml???)
|
||||
processor.processWebXml();
|
||||
MetaData metaData = (MetaData)context.getAttribute(MetaData.METADATA);
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException("No metadata");
|
||||
|
||||
metaData.addDescriptorProcessor(new StandardDescriptorProcessor());
|
||||
|
||||
//process override-web.xml
|
||||
String overrideDescriptor = context.getOverrideDescriptor();
|
||||
if (overrideDescriptor != null && overrideDescriptor.length() > 0)
|
||||
/*
|
||||
StandardDescriptorProcessor descriptorProcessor = (StandardDescriptorProcessor)context.getAttribute(StandardDescriptorProcessor.STANDARD_PROCESSOR);
|
||||
if (descriptorProcessor == null)
|
||||
{
|
||||
Resource orideResource = Resource.newSystemResource(overrideDescriptor);
|
||||
if (orideResource == null)
|
||||
orideResource = context.newResource(overrideDescriptor);
|
||||
processor.parseOverride(orideResource);
|
||||
processor.processOverride();
|
||||
descriptorProcessor = new StandardDescriptorProcessor(metaData);
|
||||
context.setAttribute(StandardDescriptorProcessor.STANDARD_PROCESSOR, descriptorProcessor);
|
||||
}
|
||||
|
||||
//process web-default.xml
|
||||
descriptorProcessor.process(metaData.getWebDefault());
|
||||
|
||||
//process web.xml
|
||||
descriptorProcessor.process(metaData.getWebXml());
|
||||
|
||||
//process override-web.xml
|
||||
descriptorProcessor.process(metaData.getOverrideWeb());
|
||||
*/
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, null);
|
||||
context.setAttribute(WebXmlProcessor.METADATA_COMPLETE, null);
|
||||
context.setAttribute(WebXmlProcessor.WEBXML_VERSION, null);
|
||||
context.setAttribute(WebXmlProcessor.WEBXML_CLASSNAMES, null);
|
||||
context.setAttribute(MetaData.WEBXML_CLASSNAMES, null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,939 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.MetaData.AbsoluteOrdering;
|
||||
import org.eclipse.jetty.webapp.MetaData.RelativeOrdering;
|
||||
|
||||
/**
|
||||
* OrderingTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class OrderingTest extends TestCase
|
||||
{
|
||||
public class TestResource extends Resource
|
||||
{
|
||||
public String _name;
|
||||
|
||||
public TestResource (String name)
|
||||
{
|
||||
_name =name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#addPath(java.lang.String)
|
||||
*/
|
||||
public Resource addPath(String path) throws IOException, MalformedURLException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#delete()
|
||||
*/
|
||||
public boolean delete() throws SecurityException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#exists()
|
||||
*/
|
||||
public boolean exists()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#getFile()
|
||||
*/
|
||||
public File getFile() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#getName()
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#getOutputStream()
|
||||
*/
|
||||
public OutputStream getOutputStream() throws IOException, SecurityException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#getURL()
|
||||
*/
|
||||
public URL getURL()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#isContainedIn(org.eclipse.jetty.util.resource.Resource)
|
||||
*/
|
||||
public boolean isContainedIn(Resource r) throws MalformedURLException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#isDirectory()
|
||||
*/
|
||||
public boolean isDirectory()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#lastModified()
|
||||
*/
|
||||
public long lastModified()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#length()
|
||||
*/
|
||||
public long length()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#list()
|
||||
*/
|
||||
public String[] list()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.resource.Resource#renameTo(org.eclipse.jetty.util.resource.Resource)
|
||||
*/
|
||||
public boolean renameTo(Resource dest) throws SecurityException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testRelativeOrdering0 ()
|
||||
throws Exception
|
||||
{
|
||||
//Example from ServletSpec p.70
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//A: after others, after C
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1, f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.After;
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(r1);
|
||||
f1._afters.add("C");
|
||||
|
||||
//B: before others
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2, f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.Before;
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(r2);
|
||||
|
||||
//C: after others
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3, f3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.After;
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(r3);
|
||||
|
||||
//D: no ordering
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4, f4);
|
||||
f4._otherType = FragmentDescriptor.OtherType.None;
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(r4);
|
||||
|
||||
//E: no ordering
|
||||
TestResource jar5 = new TestResource("E");
|
||||
resources.add(jar5);
|
||||
TestResource r5 = new TestResource("E/web-fragment.xml");
|
||||
FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
|
||||
f5._name="E";
|
||||
metaData._webFragmentNameMap.put(f5._name, f5);
|
||||
metaData._webFragmentResourceMap.put(jar5, f5);
|
||||
f5._otherType = FragmentDescriptor.OtherType.None;
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(r5);
|
||||
|
||||
//F: before others, before B
|
||||
TestResource jar6 = new TestResource("F");
|
||||
resources.add(jar6);
|
||||
TestResource r6 = new TestResource("F/web-fragment.xml");
|
||||
FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
|
||||
f6._name="F";
|
||||
metaData._webFragmentNameMap.put(f6._name, f6);
|
||||
metaData._webFragmentResourceMap.put(jar6,f6);
|
||||
f6._otherType = FragmentDescriptor.OtherType.Before;
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(r6);
|
||||
f6._befores.add("B");
|
||||
|
||||
//
|
||||
// p.70 outcome: F, B, D, E, C, A
|
||||
//
|
||||
String[] outcomes = {"FBDECA"};
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
|
||||
String result = "";
|
||||
for (Resource r:orderedList)
|
||||
result+=(((TestResource)r)._name);
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail("No outcome matched "+result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void testRelativeOrdering1 ()
|
||||
throws Exception
|
||||
{
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//Example from ServletSpec p.70-71
|
||||
//No name: after others, before C
|
||||
TestResource jar1 = new TestResource("plain");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("plain/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = FragmentDescriptor.NAMELESS+"1";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1,f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.After;
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
|
||||
f1._befores.add("C");
|
||||
|
||||
//B: before others
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2,f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.Before;
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
|
||||
|
||||
//C: no ordering
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.None;
|
||||
|
||||
//D: after others
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4,f4);
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(f4);
|
||||
f4._otherType = FragmentDescriptor.OtherType.After;
|
||||
|
||||
//E: before others
|
||||
TestResource jar5 = new TestResource("E");
|
||||
resources.add(jar5);
|
||||
TestResource r5 = new TestResource("E/web-fragment.xml");
|
||||
FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
|
||||
f5._name="E";
|
||||
metaData._webFragmentNameMap.put(f5._name, f5);
|
||||
metaData._webFragmentResourceMap.put(jar5,f5);
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(f5);
|
||||
f5._otherType = FragmentDescriptor.OtherType.Before;
|
||||
|
||||
//F: no ordering
|
||||
TestResource jar6 = new TestResource("F");
|
||||
resources.add(jar6);
|
||||
TestResource r6 = new TestResource("F/web-fragment.xml");
|
||||
FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
|
||||
f6._name="F";
|
||||
metaData._webFragmentNameMap.put(f6._name, f6);
|
||||
metaData._webFragmentResourceMap.put(jar6,f6);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f6);
|
||||
f6._otherType = FragmentDescriptor.OtherType.None;
|
||||
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
|
||||
// p.70-71 Possible outcomes are:
|
||||
// B, E, F, noname, C, D
|
||||
// B, E, F, noname, D, C
|
||||
// E, B, F, noname, C, D
|
||||
// E, B, F, noname, D, C
|
||||
// E, B, F, D, noname, C
|
||||
//
|
||||
String[] outcomes = {"BEFplainCD",
|
||||
"BEFplainDC",
|
||||
"EBFplainCD",
|
||||
"EBFplainDC",
|
||||
"EBFDplain"};
|
||||
|
||||
String orderedNames = "";
|
||||
for (Resource r:orderedList)
|
||||
orderedNames+=(((TestResource)r)._name);
|
||||
|
||||
if (!checkResult(orderedNames, outcomes))
|
||||
fail("No outcome matched "+orderedNames);
|
||||
}
|
||||
|
||||
|
||||
public void testRelativeOrdering2 ()
|
||||
throws Exception
|
||||
{
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//Example from Spec p. 71-72
|
||||
|
||||
//A: after B
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1, f1);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.None;
|
||||
f1._afters.add("B");
|
||||
|
||||
//B: no order
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2, f2);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.None;
|
||||
|
||||
//C: before others
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(f3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.Before;
|
||||
|
||||
//D: no order
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4, f4);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f4);
|
||||
f4._otherType = FragmentDescriptor.OtherType.None;
|
||||
//
|
||||
// p.71-72 possible outcomes are:
|
||||
// C,B,D,A
|
||||
// C,D,B,A
|
||||
// C,B,A,D
|
||||
//
|
||||
String[] outcomes = {"CBDA",
|
||||
"CDBA",
|
||||
"CBAD"};
|
||||
|
||||
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
String result = "";
|
||||
for (Resource r:orderedList)
|
||||
result+=(((TestResource)r)._name);
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail ("No outcome matched "+result);
|
||||
}
|
||||
|
||||
|
||||
public void testRelativeOrdering3 ()
|
||||
throws Exception
|
||||
{
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//A: after others, before C
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1, f1);
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.After;
|
||||
f1._befores.add("C");
|
||||
|
||||
//B: before others, before C
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2,f2);
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.Before;
|
||||
f2._befores.add("C");
|
||||
|
||||
//C: no ordering
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.None;
|
||||
|
||||
//result: BAC
|
||||
String[] outcomes = {"BAC"};
|
||||
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
String result = "";
|
||||
for (Resource r:orderedList)
|
||||
result+=(((TestResource)r)._name);
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail ("No outcome matched "+result);
|
||||
}
|
||||
|
||||
public void testCircular1 ()
|
||||
throws Exception
|
||||
{
|
||||
|
||||
//A: after B
|
||||
//B: after A
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//A: after B
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1, f1);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.None;
|
||||
f1._afters.add("B");
|
||||
|
||||
//B: after A
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2, f2);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.None;
|
||||
f2._afters.add("A");
|
||||
|
||||
try
|
||||
{
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
fail("No circularity detected");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
assertTrue (e instanceof IllegalStateException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void testInvalid1 ()
|
||||
throws Exception
|
||||
{
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//A: after others, before C
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1,f1);
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(r1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.After;
|
||||
f1._befores.add("C");
|
||||
|
||||
//B: before others, after C
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2,f2);
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(r2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.Before;
|
||||
f2._afters.add("C");
|
||||
|
||||
//C: no ordering
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(r3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.None;
|
||||
|
||||
try
|
||||
{
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
String result = "";
|
||||
for (Resource r:orderedList)
|
||||
result +=((TestResource)r)._name;
|
||||
System.err.println("Invalid Result = "+result);
|
||||
fail("A and B have an impossible relationship to C");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
assertTrue (e instanceof IllegalStateException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testAbsoluteOrdering1 ()
|
||||
throws Exception
|
||||
{
|
||||
//
|
||||
// A,B,C,others
|
||||
//
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new AbsoluteOrdering();
|
||||
((AbsoluteOrdering)metaData._ordering).add("A");
|
||||
((AbsoluteOrdering)metaData._ordering).add("B");
|
||||
((AbsoluteOrdering)metaData._ordering).add("C");
|
||||
((AbsoluteOrdering)metaData._ordering).addOthers();
|
||||
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1,f1);
|
||||
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2, f2);
|
||||
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3, f3);
|
||||
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4, f4);
|
||||
|
||||
TestResource jar5 = new TestResource("E");
|
||||
resources.add(jar5);
|
||||
TestResource r5 = new TestResource("E/web-fragment.xml");
|
||||
FragmentDescriptor f5 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f5._name="E";
|
||||
metaData._webFragmentNameMap.put(f5._name, f5);
|
||||
metaData._webFragmentResourceMap.put(jar5, f5);
|
||||
|
||||
TestResource jar6 = new TestResource("plain");
|
||||
resources.add(jar6);
|
||||
TestResource r6 = new TestResource ("plain/web-fragment.xml");
|
||||
FragmentDescriptor f6 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f6._name=FragmentDescriptor.NAMELESS+"1";
|
||||
metaData._webFragmentNameMap.put(f6._name, f6);
|
||||
metaData._webFragmentResourceMap.put(jar6, f6);
|
||||
|
||||
List<Resource> list = metaData._ordering.order(resources);
|
||||
|
||||
String[] outcomes = {"ABCDEplain"};
|
||||
String result = "";
|
||||
for (Resource r:list)
|
||||
result += ((TestResource)r)._name;
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail("No outcome matched "+result);
|
||||
}
|
||||
|
||||
|
||||
public void testAbsoluteOrdering2 ()
|
||||
throws Exception
|
||||
{
|
||||
// C,B,A
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new AbsoluteOrdering();
|
||||
((AbsoluteOrdering)metaData._ordering).add("C");
|
||||
((AbsoluteOrdering)metaData._ordering).add("B");
|
||||
((AbsoluteOrdering)metaData._ordering).add("A");
|
||||
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1,f1);
|
||||
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2,f2);
|
||||
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor(r4, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4,f4);
|
||||
|
||||
TestResource jar5 = new TestResource("E");
|
||||
resources.add(jar5);
|
||||
TestResource r5 = new TestResource("E/web-fragment.xml");
|
||||
FragmentDescriptor f5 = new FragmentDescriptor(r5, metaData);
|
||||
f5._name="E";
|
||||
metaData._webFragmentNameMap.put(f5._name, f5);
|
||||
metaData._webFragmentResourceMap.put(jar5,f5);
|
||||
|
||||
TestResource jar6 = new TestResource("plain");
|
||||
resources.add(jar6);
|
||||
TestResource r6 = new TestResource("plain/web-fragment.xml");
|
||||
FragmentDescriptor f6 = new FragmentDescriptor(r6, metaData);
|
||||
f6._name=FragmentDescriptor.NAMELESS+"1";
|
||||
metaData._webFragmentNameMap.put(f6._name, f6);
|
||||
metaData._webFragmentResourceMap.put(jar6,f6);
|
||||
|
||||
List<Resource> list = metaData._ordering.order(resources);
|
||||
String[] outcomes = {"CBA"};
|
||||
String result = "";
|
||||
for (Resource r:list)
|
||||
result += ((TestResource)r)._name;
|
||||
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail("No outcome matched "+result);
|
||||
}
|
||||
|
||||
public void testAbsoluteOrdering3 ()
|
||||
throws Exception
|
||||
{
|
||||
//empty <absolute-ordering>
|
||||
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new AbsoluteOrdering();
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
|
||||
resources.add(new TestResource("A"));
|
||||
resources.add(new TestResource("B"));
|
||||
|
||||
List<Resource> list = metaData._ordering.order(resources);
|
||||
assertTrue(list.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
public void testRelativeOrderingWithPlainJars ()
|
||||
throws Exception
|
||||
{
|
||||
//B,A,C other jars with no fragments
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new RelativeOrdering();
|
||||
|
||||
//A: after others, before C
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1, f1);
|
||||
//((RelativeOrdering)metaData._ordering).addAfterOthers(f1);
|
||||
f1._otherType = FragmentDescriptor.OtherType.After;
|
||||
f1._befores.add("C");
|
||||
|
||||
//B: before others, before C
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2,f2);
|
||||
//((RelativeOrdering)metaData._ordering).addBeforeOthers(f2);
|
||||
f2._otherType = FragmentDescriptor.OtherType.Before;
|
||||
f2._befores.add("C");
|
||||
|
||||
//C: after A
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3,f3);
|
||||
//((RelativeOrdering)metaData._ordering).addNoOthers(f3);
|
||||
f3._otherType = FragmentDescriptor.OtherType.None;
|
||||
f3._afters.add("A");
|
||||
|
||||
//No fragment jar 1
|
||||
TestResource r4 = new TestResource("plain1");
|
||||
resources.add(r4);
|
||||
|
||||
//No fragment jar 2
|
||||
TestResource r5 = new TestResource("plain2");
|
||||
resources.add(r5);
|
||||
|
||||
//result: BAC
|
||||
String[] outcomes = {"Bplain1plain2AC"};
|
||||
|
||||
List<Resource> orderedList = metaData._ordering.order(resources);
|
||||
String result = "";
|
||||
for (Resource r:orderedList)
|
||||
result+=(((TestResource)r)._name);
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail ("No outcome matched "+result);
|
||||
}
|
||||
|
||||
public void testAbsoluteOrderingWithPlainJars()
|
||||
throws Exception
|
||||
{
|
||||
//
|
||||
// A,B,C,others
|
||||
//
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
MetaData metaData = new MetaData(wac);
|
||||
metaData._ordering = metaData.new AbsoluteOrdering();
|
||||
((AbsoluteOrdering)metaData._ordering).add("A");
|
||||
((AbsoluteOrdering)metaData._ordering).add("B");
|
||||
((AbsoluteOrdering)metaData._ordering).add("C");
|
||||
((AbsoluteOrdering)metaData._ordering).addOthers();
|
||||
|
||||
TestResource jar1 = new TestResource("A");
|
||||
resources.add(jar1);
|
||||
TestResource r1 = new TestResource("A/web-fragment.xml");
|
||||
FragmentDescriptor f1 = new FragmentDescriptor(r1, metaData);
|
||||
f1._name = "A";
|
||||
metaData._webFragmentNameMap.put(f1._name, f1);
|
||||
metaData._webFragmentResourceMap.put(jar1,f1);
|
||||
|
||||
TestResource jar2 = new TestResource("B");
|
||||
resources.add(jar2);
|
||||
TestResource r2 = new TestResource("B/web-fragment.xml");
|
||||
FragmentDescriptor f2 = new FragmentDescriptor(r2, metaData);
|
||||
f2._name="B";
|
||||
metaData._webFragmentNameMap.put(f2._name, f2);
|
||||
metaData._webFragmentResourceMap.put(jar2, f2);
|
||||
|
||||
TestResource jar3 = new TestResource("C");
|
||||
resources.add(jar3);
|
||||
TestResource r3 = new TestResource("C/web-fragment.xml");
|
||||
FragmentDescriptor f3 = new FragmentDescriptor(r3, metaData);
|
||||
f3._name="C";
|
||||
metaData._webFragmentNameMap.put(f3._name, f3);
|
||||
metaData._webFragmentResourceMap.put(jar3, f3);
|
||||
|
||||
TestResource jar4 = new TestResource("D");
|
||||
resources.add(jar4);
|
||||
TestResource r4 = new TestResource("D/web-fragment.xml");
|
||||
FragmentDescriptor f4 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f4._name="D";
|
||||
metaData._webFragmentNameMap.put(f4._name, f4);
|
||||
metaData._webFragmentResourceMap.put(jar4, f4);
|
||||
|
||||
TestResource jar5 = new TestResource("E");
|
||||
resources.add(jar5);
|
||||
TestResource r5 = new TestResource("E/web-fragment.xml");
|
||||
FragmentDescriptor f5 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f5._name="E";
|
||||
metaData._webFragmentNameMap.put(f5._name, f5);
|
||||
metaData._webFragmentResourceMap.put(jar5, f5);
|
||||
|
||||
TestResource jar6 = new TestResource("plain");
|
||||
resources.add(jar6);
|
||||
TestResource r6 = new TestResource("plain/web-fragment.xml");
|
||||
FragmentDescriptor f6 = new FragmentDescriptor((Resource)null, metaData);
|
||||
f6._name=FragmentDescriptor.NAMELESS+"1";
|
||||
metaData._webFragmentNameMap.put(f6._name, f6);
|
||||
metaData._webFragmentResourceMap.put(jar6, f6);
|
||||
|
||||
//plain jar
|
||||
TestResource r7 = new TestResource("plain1");
|
||||
resources.add(r7);
|
||||
|
||||
TestResource r8 = new TestResource("plain2");
|
||||
resources.add(r8);
|
||||
|
||||
List<Resource> list = metaData._ordering.order(resources);
|
||||
|
||||
String[] outcomes = {"ABCDEplainplain1plain2"};
|
||||
String result = "";
|
||||
for (Resource r:list)
|
||||
result += ((TestResource)r)._name;
|
||||
|
||||
if (!checkResult(result, outcomes))
|
||||
fail("No outcome matched "+result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean checkResult (String result, String[] outcomes)
|
||||
{
|
||||
boolean matched = false;
|
||||
for (String s:outcomes)
|
||||
{
|
||||
if (s.equals(result))
|
||||
matched = true;
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue