389452 if web-fragment metadata-complete==true still scan its related jar if there there is a ServletContainerInitializer

Also some refactoring to simplify scanning for annotations/classes.
This commit is contained in:
Jan Bartel 2012-09-14 16:51:53 +10:00
parent 944b23240e
commit 394c478b19
17 changed files with 611 additions and 170 deletions

View File

@ -22,7 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
@ -34,13 +34,32 @@ import org.eclipse.jetty.webapp.WebAppContext;
public abstract class AbstractDiscoverableAnnotationHandler implements DiscoverableAnnotationHandler
{
protected WebAppContext _context;
protected List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
protected List<DiscoveredAnnotation> _annotations;
protected Resource _resource;
public AbstractDiscoverableAnnotationHandler(WebAppContext context)
{
this(context, null);
}
public AbstractDiscoverableAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list)
{
_context = context;
if (list == null)
_annotations = new ArrayList<DiscoveredAnnotation>();
else
_annotations = list;
}
public Resource getResource()
{
return _resource;
}
public void setResource(Resource resource)
{
_resource = resource;
}
public List<DiscoveredAnnotation> getAnnotationList ()
{

View File

@ -33,6 +33,7 @@ import javax.servlet.annotation.HandlesTypes;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@ -55,12 +56,22 @@ public class AnnotationConfiguration extends AbstractConfiguration
private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
protected ClassInheritanceHandler _classInheritanceHandler;
protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
public void preConfigure(final WebAppContext context) throws Exception
{
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void configure(WebAppContext context) throws Exception
{
@ -75,10 +86,9 @@ public class AnnotationConfiguration extends AbstractConfiguration
//If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations
if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
{
parser = createAnnotationParser();
parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", new WebServletAnnotationHandler(context));
parser.registerAnnotationHandler("javax.servlet.annotation.WebFilter", new WebFilterAnnotationHandler(context));
parser.registerAnnotationHandler("javax.servlet.annotation.WebListener", new WebListenerAnnotationHandler(context));
_discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
_discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
_discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
}
}
else
@ -88,11 +98,11 @@ public class AnnotationConfiguration extends AbstractConfiguration
//Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, then we need to scan all the
//classes so we can call their onStartup() methods correctly
List<ServletContainerInitializer> nonExcludedInitializers = getNonExcludedInitializers(context);
parser = registerServletContainerInitializerAnnotationHandlers(context, parser, nonExcludedInitializers);
createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
if (parser != null)
if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
{
parser = createAnnotationParser();
if (LOG.isDebugEnabled()) LOG.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered());
parseContainerPath(context, parser);
//email from Rajiv Mordani jsrs 315 7 April 2010
@ -102,11 +112,36 @@ public class AnnotationConfiguration extends AbstractConfiguration
// WEB-INF/classes + order of the elements.
parseWebInfClasses(context, parser);
parseWebInfLib (context, parser);
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
context.getMetaData().addDiscoveredAnnotations(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
}
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void postConfigure(WebAppContext context) throws Exception
{
MultiMap map = (MultiMap)context.getAttribute(CLASS_INHERITANCE_MAP);
if (map != null)
map.clear();
List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
if (initializers != null)
initializers.clear();
if (_discoverableAnnotationHandlers != null)
_discoverableAnnotationHandlers.clear();
_discoverableAnnotationHandlers = null;
_classInheritanceHandler = null;
if (_containerInitializerAnnotationHandlers != null)
_containerInitializerAnnotationHandlers.clear();
_containerInitializerAnnotationHandlers = null;
super.postConfigure(context);
}
/**
* @return a new AnnotationParser. This method can be overridden to use a different impleemntation of
* the AnnotationParser. Note that this is considered internal API.
@ -116,6 +151,9 @@ public class AnnotationConfiguration extends AbstractConfiguration
return new AnnotationParser();
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#cloneConfigure(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
{
@ -123,32 +161,21 @@ public class AnnotationConfiguration extends AbstractConfiguration
}
public AnnotationParser registerServletContainerInitializerAnnotationHandlers (WebAppContext context, AnnotationParser parser, List<ServletContainerInitializer> scis)
/**
* @param context
* @param scis
* @throws Exception
*/
public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
throws Exception
{
//TODO verify my interpretation of the spec. That is, that metadata-complete has nothing
//to do with finding the ServletContainerInitializers, classes designated to be of interest to them,
//or even calling them on startup.
//Get all ServletContainerInitializers, and check them for HandlesTypes annotations.
//For each class in the HandlesTypes value, if it IS an annotation, register a handler
//that will record the classes that have that annotation.
//If it is NOT an annotation, then we will interrogate the type hierarchy discovered during
//parsing later on to find the applicable classes.
{
if (scis == null || scis.isEmpty())
return parser; // nothing to do
ServletContainerInitializerListener listener = new ServletContainerInitializerListener();
listener.setWebAppContext(context);
context.addEventListener(listener);
//may need to add a listener
return; // nothing to do
ArrayList<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
context.setAttribute(CONTAINER_INITIALIZERS, initializers);
for (ServletContainerInitializer service : scis)
@ -164,18 +191,14 @@ public class AnnotationConfiguration extends AbstractConfiguration
if (classes != null)
{
initializer.setInterestedTypes(classes);
//We need to create a parser if we haven't already
if (parser == null)
parser = createAnnotationParser();
//If we haven't already done so, we need to register a handler that will
//process the whole class hierarchy
//process the whole class hierarchy to satisfy the ServletContainerInitializer
if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
{
ClassInheritanceHandler classHandler = new ClassInheritanceHandler();
context.setAttribute(CLASS_INHERITANCE_MAP, classHandler.getMap());
parser.registerClassHandler(classHandler);
MultiMap map = new MultiMap();
context.setAttribute(CLASS_INHERITANCE_MAP, map);
_classInheritanceHandler = new ClassInheritanceHandler(map);
}
for (Class c: classes)
@ -186,7 +209,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
{
if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
parser.registerAnnotationHandler(c.getName(), new ContainerInitializerAnnotationHandler(initializer, c));
_containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
}
}
}
@ -197,15 +220,15 @@ public class AnnotationConfiguration extends AbstractConfiguration
if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass());
}
//return the parser in case we lazily created it
return parser;
//add a listener which will call the servletcontainerinitializers when appropriate
ServletContainerInitializerListener listener = new ServletContainerInitializerListener();
listener.setWebAppContext(context);
context.addEventListener(listener);
}
/**
* Check to see if the ServletContainerIntializer loaded via the ServiceLoader came
* from a jar that is excluded by the fragment ordering. See ServletSpec 3.0 p.85.
@ -248,7 +271,12 @@ public class AnnotationConfiguration extends AbstractConfiguration
public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
/**
* @param context
* @return
* @throws Exception
*/
public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
throws Exception
{
List<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
@ -270,14 +298,29 @@ public class AnnotationConfiguration extends AbstractConfiguration
/**
* Scan jars on container path.
*
* @param context
* @param parser
* @throws Exception
*/
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");
//clear any previously discovered annotations
clearAnnotationList(parser.getAnnotationHandlers());
//always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotations
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
//Convert from Resource to URI
ArrayList<URI> containerUris = new ArrayList<URI>();
@ -304,16 +347,19 @@ public class AnnotationConfiguration extends AbstractConfiguration
return true;
return false;
}
});
});
//gather together all annotations discovered
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations(annotations);
}
/**
* Scan jars in WEB-INF/lib
*
* @param context
* @param parser
* @throws Exception
*/
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
@ -332,17 +378,34 @@ public class AnnotationConfiguration extends AbstractConfiguration
for (Resource r : jars)
{
//clear any previously discovered annotations from handlers
clearAnnotationList(parser.getAnnotationHandlers());
//for each jar, we decide which set of annotations we need to parse for
parser.clearHandlers();
URI uri = r.getURI();
FragmentDescriptor f = getFragmentFromJar(r, frags);
//if a jar has no web-fragment.xml we scan it (because it is not exluded by the ordering)
//if its from a fragment jar that is metadata complete, we should skip scanning for @webservlet etc
// but yet we still need to do the scanning for the classes on behalf of the servletcontainerinitializers
//if a jar has no web-fragment.xml we scan it (because it is not excluded by the ordering)
//or if it has a fragment we scan it if it is not metadata complete
if (f == null || !isMetaDataComplete(f))
if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
{
//register the classinheritance handler if there is one
parser.registerHandler(_classInheritanceHandler);
//register the handlers for the @HandlesTypes values that are themselves annotations if there are any
parser.registerHandlers(_containerInitializerAnnotationHandlers);
//only register the discoverable annotation handlers if this fragment is not metadata complete, or has no fragment descriptor
if (f == null || !isMetaDataComplete(f))
{
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(r);
}
parser.registerHandlers(_discoverableAnnotationHandlers);
}
parser.parse(uri,
new ClassNameResolver()
{
@ -360,14 +423,18 @@ public class AnnotationConfiguration extends AbstractConfiguration
return false;
return true;
}
});
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations(r, annotations);
});
}
}
}
/**
* Scan classes in WEB-INF/classes
*
* @param context
* @param parser
* @throws Exception
*/
public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
@ -377,7 +444,16 @@ public class AnnotationConfiguration extends AbstractConfiguration
Resource classesDir = context.getWebInf().addPath("classes/");
if (classesDir.exists())
{
clearAnnotationList(parser.getAnnotationHandlers());
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
parser.parse(classesDir,
new ClassNameResolver()
{
@ -396,17 +472,20 @@ public class AnnotationConfiguration extends AbstractConfiguration
return true;
}
});
//TODO - where to set the annotations discovered from WEB-INF/classes?
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations (annotations);
}
}
}
/**
* Get the web-fragment.xml from a jar
*
* @param jar
* @param frags
* @return
* @throws Exception
*/
public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
throws Exception
{
@ -428,25 +507,4 @@ public class AnnotationConfiguration extends AbstractConfiguration
{
return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
}
protected void clearAnnotationList (List<DiscoverableAnnotationHandler> handlers)
{
if (handlers == null)
return;
for (DiscoverableAnnotationHandler h:handlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).resetList();
}
}
protected void gatherAnnotations (List<DiscoveredAnnotation> annotations, List<DiscoverableAnnotationHandler> handlers)
{
for (DiscoverableAnnotationHandler h:handlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
annotations.addAll(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
}
}
}

View File

@ -53,11 +53,8 @@ public class AnnotationParser
{
private static final Logger LOG = Log.getLogger(AnnotationParser.class);
protected List<String> _parsedClassNames = new ArrayList<String>();
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>();
protected List<String> _parsedClassNames = new ArrayList<String>();
protected List<Handler> _handlers = new ArrayList<Handler>();
public static String normalize (String name)
{
@ -168,37 +165,122 @@ public class AnnotationParser
public interface DiscoverableAnnotationHandler
/**
* Handler
*
* Signature for all handlers that respond to parsing class files.
*/
public interface Handler
{
}
/**
* DiscoverableAnnotationHandler
*
* Processes an annotation when it is discovered on a class.
*/
public interface DiscoverableAnnotationHandler extends Handler
{
/**
* Process an annotation that was discovered on a class
* @param className
* @param version
* @param access
* @param signature
* @param superName
* @param interfaces
* @param annotation
* @param values
*/
public void handleClass (String className, int version, int access,
String signature, String superName, String[] interfaces,
String annotation, List<Value>values);
/**
* Process an annotation that was discovered on a method
* @param className
* @param methodName
* @param access
* @param desc
* @param signature
* @param exceptions
* @param annotation
* @param values
*/
public void handleMethod (String className, String methodName, int access,
String desc, String signature,String[] exceptions,
String annotation, List<Value>values);
/**
* Process an annotation that was discovered on a field
* @param className
* @param fieldName
* @param access
* @param fieldType
* @param signature
* @param value
* @param annotation
* @param values
*/
public void handleField (String className, String fieldName, int access,
String fieldType, String signature, Object value,
String annotation, List<Value>values);
/**
* Get the name of the annotation processed by this handler. Can be null
*
* @return
*/
public String getAnnotationName();
}
public interface ClassHandler
/**
* ClassHandler
*
* Responds to finding a Class
*/
public interface ClassHandler extends Handler
{
public void handle (String className, int version, int access, String signature, String superName, String[] interfaces);
}
public interface MethodHandler
/**
* MethodHandler
*
* Responds to finding a Method
*/
public interface MethodHandler extends Handler
{
public void handle (String className, String methodName, int access, String desc, String signature,String[] exceptions);
}
public interface FieldHandler
/**
* FieldHandler
*
* Responds to finding a Field
*/
public interface FieldHandler extends Handler
{
public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value);
}
/**
* MyAnnotationVisitor
*
* ASM Visitor for Annotations
*/
public class MyAnnotationVisitor implements AnnotationVisitor
{
List<Value> _annotationValues;
@ -307,10 +389,13 @@ public class AnnotationParser
for (String s : interfaces)
normalizedInterfaces[i++] = normalize(s);
}
for (ClassHandler h : AnnotationParser.this._classHandlers)
for (Handler h : AnnotationParser.this._handlers)
{
h.handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
if (h instanceof ClassHandler)
{
((ClassHandler)h).handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
}
}
}
@ -323,12 +408,13 @@ public class AnnotationParser
super.visitEnd();
//call all AnnotationHandlers with classname, annotation name + values
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
if (handlers != null)
for (Handler h : AnnotationParser.this._handlers)
{
for (DiscoverableAnnotationHandler h:handlers)
if (h instanceof DiscoverableAnnotationHandler)
{
h.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
dah.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
}
}
}
@ -354,12 +440,13 @@ public class AnnotationParser
{
super.visitEnd();
//call all AnnotationHandlers with classname, method, annotation name + values
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
if (handlers != null)
for (Handler h : AnnotationParser.this._handlers)
{
for (DiscoverableAnnotationHandler h:handlers)
if (h instanceof DiscoverableAnnotationHandler)
{
h.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
dah.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
}
}
}
@ -386,12 +473,13 @@ public class AnnotationParser
public void visitEnd()
{
super.visitEnd();
List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
if (handlers != null)
for (Handler h : AnnotationParser.this._handlers)
{
for (DiscoverableAnnotationHandler h:handlers)
if (h instanceof DiscoverableAnnotationHandler)
{
h.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
dah.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
}
}
}
@ -407,46 +495,130 @@ public class AnnotationParser
* Register a handler that will be called back when the named annotation is
* encountered on a class.
*
* @deprecated see registerHandler(Handler)
* @param annotationName
* @param handler
*/
public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
{
List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
if (handlers == null)
{
handlers = new ArrayList<DiscoverableAnnotationHandler>();
_annotationHandlers.put(annotationName, handlers);
}
handlers.add(handler);
_handlers.add(handler);
}
/**
* @deprecated
* @param annotationName
* @return
*/
public List<DiscoverableAnnotationHandler> getAnnotationHandlers(String annotationName)
{
List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
if (handlers == null)
return Collections.emptyList();
return new ArrayList<DiscoverableAnnotationHandler>();
List<DiscoverableAnnotationHandler> handlers = new ArrayList<DiscoverableAnnotationHandler>();
for (Handler h:_handlers)
{
if (h instanceof DiscoverableAnnotationHandler)
{
DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
if (annotationName.equals(dah.getAnnotationName()))
handlers.add(dah);
}
}
return handlers;
}
/**
* @deprecated
* @return
*/
public List<DiscoverableAnnotationHandler> getAnnotationHandlers()
{
List<DiscoverableAnnotationHandler> allHandlers = new ArrayList<DiscoverableAnnotationHandler>();
for (List<DiscoverableAnnotationHandler> list:_annotationHandlers.values())
allHandlers.addAll(list);
return allHandlers;
List<DiscoverableAnnotationHandler> allAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
for (Handler h:_handlers)
{
if (h instanceof DiscoverableAnnotationHandler)
allAnnotationHandlers.add((DiscoverableAnnotationHandler)h);
}
return allAnnotationHandlers;
}
/**
* @deprecated see registerHandler(Handler)
* @param handler
*/
public void registerClassHandler (ClassHandler handler)
{
_classHandlers.add(handler);
_handlers.add(handler);
}
/**
* Add a particular handler
*
* @param h
*/
public void registerHandler(Handler h)
{
if (h == null)
return;
_handlers.add(h);
}
/**
* Add a list of handlers
*
* @param handlers
*/
public void registerHandlers(List<? extends Handler> handlers)
{
if (handlers == null)
return;
_handlers.addAll(handlers);
}
/**
* Remove a particular handler
*
* @param h
* @return
*/
public boolean deregisterHandler(Handler h)
{
return _handlers.remove(h);
}
/**
* Remove all registered handlers
*/
public void clearHandlers()
{
_handlers.clear();
}
/**
* True if the class has already been processed, false otherwise
* @param className
* @return
*/
public boolean isParsed (String className)
{
return _parsedClassNames.contains(className);
}
/**
* Parse a given class
*
* @param className
* @param resolver
* @throws Exception
*/
public void parse (String className, ClassNameResolver resolver)
throws Exception
{
@ -468,6 +640,16 @@ public class AnnotationParser
}
}
/**
* Parse the given class, optionally walking its inheritance hierarchy
*
* @param clazz
* @param resolver
* @param visitSuperClasses
* @throws Exception
*/
public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses)
throws Exception
{
@ -494,6 +676,15 @@ public class AnnotationParser
}
}
/**
* Parse the given classes
*
* @param classNames
* @param resolver
* @throws Exception
*/
public void parse (String[] classNames, ClassNameResolver resolver)
throws Exception
{
@ -503,6 +694,14 @@ public class AnnotationParser
parse(Arrays.asList(classNames), resolver);
}
/**
* Parse the given classes
*
* @param classNames
* @param resolver
* @throws Exception
*/
public void parse (List<String> classNames, ClassNameResolver resolver)
throws Exception
{
@ -521,6 +720,14 @@ public class AnnotationParser
}
}
/**
* Parse all classes in a directory
*
* @param dir
* @param resolver
* @throws Exception
*/
public void parse (Resource dir, ClassNameResolver resolver)
throws Exception
{
@ -556,8 +763,9 @@ public class AnnotationParser
/**
* Find annotations on classes in the supplied classloader.
* Parse classes in the supplied classloader.
* Only class files in jar files will be scanned.
*
* @param loader
* @param visitParents
* @param nullInclusive
@ -606,7 +814,8 @@ public class AnnotationParser
/**
* Find annotations in classes in the supplied url of jar files.
* Parse classes in the supplied url of jar files.
*
* @param uris
* @param resolver
* @throws Exception
@ -648,6 +857,12 @@ public class AnnotationParser
scanner.scan(null, uris, true);
}
/**
* Parse a particular resource
* @param uri
* @param resolver
* @throws Exception
*/
public void parse (URI uri, final ClassNameResolver resolver)
throws Exception
{
@ -657,6 +872,14 @@ public class AnnotationParser
parse(uris, resolver);
}
/**
* Use ASM on a class
*
* @param is
* @throws IOException
*/
protected void scanClass (InputStream is)
throws IOException
{

View File

@ -35,10 +35,16 @@ public class ClassInheritanceHandler implements ClassHandler
private static final Logger LOG = Log.getLogger(ClassInheritanceHandler.class);
MultiMap _inheritanceMap = new MultiMap();
MultiMap _inheritanceMap;
public ClassInheritanceHandler()
{
_inheritanceMap = new MultiMap();
}
public ClassInheritanceHandler(MultiMap map)
{
_inheritanceMap = map;
}
public void handle(String className, int version, int access, String signature, String superName, String[] interfaces)

View File

@ -69,4 +69,15 @@ public class ContainerInitializerAnnotationHandler implements DiscoverableAnnota
_initializer.addAnnotatedTypeName(className);
}
@Override
public String getAnnotationName()
{
return _annotation.getName();
}
public ContainerInitializer getContainerInitializer()
{
return _initializer;
}
}

View File

@ -28,6 +28,8 @@ import javax.servlet.ServletContextListener;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -37,7 +39,8 @@ import org.eclipse.jetty.webapp.WebAppContext;
*/
public class ServletContainerInitializerListener implements ServletContextListener
{
WebAppContext _context = null;
private static final Logger LOG = Log.getLogger(ServletContainerInitializerListener.class);
protected WebAppContext _context = null;
public void setWebAppContext (WebAppContext context)
@ -105,16 +108,11 @@ public class ServletContainerInitializerListener implements ServletContextListen
}
catch (Exception e)
{
//OK, how do I throw an exception such that it really stops the startup sequence?
e.printStackTrace();
LOG.warn(e);
throw new RuntimeException(e);
}
}
//Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
//called, need to check to see if there are any ServletRegistrations remaining
//that are "preliminary" and fail the deployment if so. Implemented in ServletHolder.doStart().
}
}
}
@ -138,8 +136,7 @@ public class ServletContainerInitializerListener implements ServletContextListen
*/
public void contextDestroyed(ServletContextEvent sce)
{
// TODO Auto-generated method stub
}
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
@ -53,6 +54,11 @@ public class WebFilterAnnotation extends DiscoveredAnnotation
{
super(context, className);
}
public WebFilterAnnotation(WebAppContext context, String className, Resource resource)
{
super(context, className, resource);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()

View File

@ -40,11 +40,16 @@ public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHa
{
super(context);
}
public WebFilterAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className);
WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className, _resource);
addAnnotation(wfAnnotation);
}
@ -60,4 +65,10 @@ public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHa
LOG.warn ("@WebFilter not applicable for methods: "+className+"."+methodName+" "+signature);
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebFilter";
}
}

View File

@ -27,6 +27,7 @@ import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
@ -49,6 +50,11 @@ public class WebListenerAnnotation extends DiscoveredAnnotation
{
super(context, className);
}
public WebListenerAnnotation(WebAppContext context, String className, Resource resource)
{
super(context, className, resource);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()

View File

@ -23,6 +23,7 @@ import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotationHandler
@ -34,13 +35,18 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
super(context);
}
public WebListenerAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
/**
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className);
WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className, _resource);
addAnnotation(wlAnnotation);
}
@ -56,4 +62,10 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation
LOG.warn ("@WebListener is not applicable to methods: "+className+"."+methodName+" "+signature);
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebListener";
}
}

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
@ -48,7 +49,13 @@ public class WebServletAnnotation extends DiscoveredAnnotation
{
super(context, className);
}
public WebServletAnnotation (WebAppContext context, String className, Resource resource)
{
super(context, className, resource);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
*/

View File

@ -42,6 +42,11 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH
super(context);
}
public WebServletAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
{
super(context, list);
}
/**
* Handle discovering a WebServlet annotation.
@ -55,7 +60,7 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH
if (!"javax.servlet.annotation.WebServlet".equals(annotationName))
return;
WebServletAnnotation annotation = new WebServletAnnotation (_context, className);
WebServletAnnotation annotation = new WebServletAnnotation (_context, className, _resource);
addAnnotation(annotation);
}
@ -69,5 +74,12 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH
List<Value> values)
{
LOG.warn ("@WebServlet annotation not supported for methods");
}
@Override
public String getAnnotationName()
{
return "javax.servlet.annotation.WebServlet";
}
}

View File

@ -66,6 +66,12 @@ public class TestAnnotationInheritance
{
annotatedMethods.add(className+"."+methodName);
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Sample";
}
}
@After
@ -85,7 +91,7 @@ public class TestAnnotationInheritance
SampleHandler handler = new SampleHandler();
AnnotationParser parser = new AnnotationParser();
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
parser.registerHandler(handler);
parser.parse(classNames, new ClassNameResolver ()
{
public boolean isExcluded(String name)

View File

@ -41,6 +41,9 @@ public class TestAnnotationParser
{
private List<String> methods = Arrays.asList("a", "b", "c", "d", "l");
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
@ -81,9 +84,15 @@ public class TestAnnotationParser
assertTrue(methods.contains(methodName));
assertEquals("org.eclipse.jetty.annotations.Sample", annotation);
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Sample";
}
}
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", new SampleAnnotationHandler());
parser.registerHandler(new SampleAnnotationHandler());
long start = System.currentTimeMillis();
parser.parse(classNames, new ClassNameResolver ()
@ -140,9 +149,17 @@ public class TestAnnotationParser
System.err.println(anv.toString());
}
}
@Override
public String getAnnotationName()
{
return "org.eclipse.jetty.annotations.Multi";
}
}
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Multi", new MultiAnnotationHandler());
parser.registerHandler(new MultiAnnotationHandler());
parser.parse(classNames, null);
}
}

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.osgi.annotations;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
@ -151,20 +153,25 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
protected void parseBundle(WebAppContext context, AnnotationParser parser,
Bundle webbundle, Bundle bundle) throws Exception
{
Resource bundleRes = parser.getResource(bundle);
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
{
if (webbundle == bundle)
((AbstractDiscoverableAnnotationHandler)h).setResource(null);
else
((AbstractDiscoverableAnnotationHandler)h).setResource(bundleRes);
}
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
parser.parse(bundle,createClassNameResolver(context));
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
if (webbundle == bundle)
{
//just like the super with its question about annotations in WEB-INF/classes:
//"TODO - where to set the annotations discovered from WEB-INF/classes?"
context.getMetaData().addDiscoveredAnnotations(annotations);
}
else
{
context.getMetaData().addDiscoveredAnnotations(bundleRes, annotations);
}
}
/**

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.webapp;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
/**
* DiscoveredAnnotation
@ -36,16 +37,28 @@ public abstract class DiscoveredAnnotation
protected WebAppContext _context;
protected String _className;
protected Class<?> _clazz;
protected Resource _resource; //resource it was discovered on, can be null (eg from WEB-INF/classes)
public abstract void apply();
public DiscoveredAnnotation (WebAppContext context, String className)
{
_context = context;
_className = className;
this(context,className, null);
}
public DiscoveredAnnotation(WebAppContext context, String className, Resource resource)
{
_context = context;
_className = className;
_resource = resource;
}
public Resource getResource ()
{
return _resource;
}
public Class<?> getTargetClass()
{
if (_clazz != null)

View File

@ -271,12 +271,42 @@ public class MetaData
*/
public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
{
_annotations.addAll(annotations);
if (annotations == null)
return;
for (DiscoveredAnnotation a:annotations)
{
Resource r = a.getResource();
if (r == null || !_webInfJars.contains(r))
_annotations.add(a);
else
addDiscoveredAnnotation(a.getResource(), a);
}
}
public void addDiscoveredAnnotation(Resource resource, DiscoveredAnnotation annotation)
{
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
}
list.add(annotation);
}
public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
{
_webFragmentAnnotations.put(resource, new ArrayList<DiscoveredAnnotation>(annotations));
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
}
list.addAll(annotations);
}
public void addDescriptorProcessor(DescriptorProcessor p)