diff options
author | Jan Bartel | 2013-09-26 08:26:13 +0000 |
---|---|---|
committer | Jan Bartel | 2013-09-30 03:27:05 +0000 |
commit | 04002898263b3d408f7f4851906dfcb7185902ee (patch) | |
tree | 47886b39b850fb96f7c1a5872eb964556590001b /jetty-annotations/src | |
parent | 0fd656dcbe0102c7e9deecaac9ac4de1a5016c62 (diff) | |
download | org.eclipse.jetty.project-04002898263b3d408f7f4851906dfcb7185902ee.tar.gz org.eclipse.jetty.project-04002898263b3d408f7f4851906dfcb7185902ee.tar.xz org.eclipse.jetty.project-04002898263b3d408f7f4851906dfcb7185902ee.zip |
417561 Refactor annotation related code - make annotation phase able to be multithreaded
Diffstat (limited to 'jetty-annotations/src')
12 files changed, 429 insertions, 223 deletions
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java index b46a053a6e..f81110252c 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.annotations; -import java.util.List; - import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler; import org.eclipse.jetty.webapp.DiscoveredAnnotation; import org.eclipse.jetty.webapp.WebAppContext; @@ -37,15 +35,9 @@ public abstract class AbstractDiscoverableAnnotationHandler extends AbstractHand public AbstractDiscoverableAnnotationHandler(WebAppContext context) { - this(context, null); - } - - public AbstractDiscoverableAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list) - { _context = context; - } - + public void addAnnotation (DiscoveredAnnotation a) { diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java index f7f17b25ab..d38673c65e 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java @@ -20,18 +20,28 @@ package org.eclipse.jetty.annotations; import java.net.URI; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import javax.servlet.ServletContainerInitializer; import javax.servlet.annotation.HandlesTypes; +import org.eclipse.jetty.annotations.AnnotationParser.Handler; import org.eclipse.jetty.plus.annotation.ContainerInitializer; -import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.ConcurrentHashSet; +import org.eclipse.jetty.util.MultiException; 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.util.thread.QueuedThreadPool; import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.FragmentDescriptor; import org.eclipse.jetty.webapp.MetaDataComplete; @@ -46,16 +56,50 @@ import org.eclipse.jetty.webapp.WebDescriptor; 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"; public static final String CONTAINER_INITIALIZER_STARTER = "org.eclipse.jetty.containerInitializerStarter"; - + public static final String MULTI_THREADED = "org.eclipse.jetty.annotations.multiThreaded"; + public static final String MAX_SCAN_WAIT = "org.eclipse.jetty.annotations.maxWait"; + + public static final int DEFAULT_MAX_SCAN_WAIT = 60; /* time in sec */ protected List<AbstractDiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<AbstractDiscoverableAnnotationHandler>(); protected ClassInheritanceHandler _classInheritanceHandler; protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>(); + protected List<ParserTask> _parserTasks; + protected WebAppClassNameResolver _webAppClassNameResolver; + protected ContainerClassNameResolver _containerClassNameResolver; + + + public class ParserTask implements Callable<Void> + { + protected Exception _exception; + protected final AnnotationParser _parser; + protected final Set<? extends Handler> _handlers; + protected final ClassNameResolver _resolver; + protected final Resource _resource; + + + public ParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver) + { + _parser = parser; + _handlers = handlers; + _resolver = resolver; + _resource = resource; + } + + public Void call() throws Exception + { + if (_parser != null) + _parser.parse(_handlers, _resource, _resolver); + return null; + } + } + /** * WebAppClassNameResolver * @@ -134,6 +178,8 @@ public class AnnotationConfiguration extends AbstractConfiguration @Override public void preConfigure(final WebAppContext context) throws Exception { + _webAppClassNameResolver = new WebAppClassNameResolver(context); + _containerClassNameResolver = new ContainerClassNameResolver(context); } @@ -166,7 +212,7 @@ public class AnnotationConfiguration extends AbstractConfiguration //Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are any - AnnotationParser parser = null; + if (!metadataComplete) { //If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations @@ -187,18 +233,8 @@ public class AnnotationConfiguration extends AbstractConfiguration createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context)); 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 - // If there is a <others/> then the ordering should be - // WEB-INF/classes the order of the declared elements + others. - // In case there is no others then it is - // WEB-INF/classes + order of the elements. - parseWebInfClasses(context, parser); - parseWebInfLib (context, parser); - } + scanForAnnotations(context); + } @@ -209,7 +245,7 @@ public class AnnotationConfiguration extends AbstractConfiguration @Override public void postConfigure(WebAppContext context) throws Exception { - MultiMap<String> classMap = (MultiMap<String>)context.getAttribute(CLASS_INHERITANCE_MAP); + ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap = (ConcurrentHashMap<String, ConcurrentHashSet<String>>)context.getAttribute(CLASS_INHERITANCE_MAP); List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS); context.removeAttribute(CLASS_INHERITANCE_MAP); @@ -222,14 +258,118 @@ public class AnnotationConfiguration extends AbstractConfiguration if (_discoverableAnnotationHandlers != null) _discoverableAnnotationHandlers.clear(); - + _classInheritanceHandler = null; if (_containerInitializerAnnotationHandlers != null) _containerInitializerAnnotationHandlers.clear(); - + + if (_parserTasks != null) + { + _parserTasks.clear(); + _parserTasks = null; + } + super.postConfigure(context); } + + + + /** + * Perform scanning of classes for annotations + * + * @param context + * @throws Exception + */ + protected void scanForAnnotations (WebAppContext context) + throws Exception + { + AnnotationParser parser = createAnnotationParser(); + boolean multiThreadedScan = isUseMultiThreading(context); + int maxThreads = 0; + int maxScanWait = 0; + if (multiThreadedScan) + { + _parserTasks = new ArrayList<ParserTask>(); + maxScanWait = getMaxScanWait(context); + } + + long start = 0; + + if (LOG.isDebugEnabled()) + { + start = System.nanoTime(); + LOG.debug("Scanning for annotations: webxml={}, configurationDiscovered={}, multiThreaded={}, threads={}", + context.getServletContext().getEffectiveMajorVersion(), + context.isConfigurationDiscovered(), + multiThreadedScan, maxThreads); + } + + parseContainerPath(context, parser); + //email from Rajiv Mordani jsrs 315 7 April 2010 + // If there is a <others/> then the ordering should be + // WEB-INF/classes the order of the declared elements + others. + // In case there is no others then it is + // WEB-INF/classes + order of the elements. + parseWebInfClasses(context, parser); + parseWebInfLib (context, parser); + + if (!multiThreadedScan) + { + if (LOG.isDebugEnabled()) + { + long end = System.nanoTime(); + LOG.debug("Annotation parsing millisec={}",(TimeUnit.MILLISECONDS.convert(end-start, TimeUnit.NANOSECONDS))); + } + return; + } + + if (LOG.isDebugEnabled()) + start = System.nanoTime(); + + //execute scan asynchronously using jetty's thread pool + final CountDownLatch latch = new CountDownLatch(_parserTasks.size()); + final MultiException me = new MultiException(); + final Semaphore task_limit=new Semaphore(Runtime.getRuntime().availableProcessors()); + for (final ParserTask p:_parserTasks) + { + task_limit.acquire(); + context.getServer().getThreadPool().execute(new Runnable() + { + @Override + public void run() + { + try + { + p.call(); + } + catch (Exception e) + { + me.add(e); + } + finally + { + task_limit.release(); + latch.countDown(); + } + } + }); + } + + boolean timeout = !latch.await(maxScanWait, TimeUnit.SECONDS); + + if (LOG.isDebugEnabled()) + { + long end = System.nanoTime(); + LOG.debug("Annotation parsing millisec={}",(TimeUnit.MILLISECONDS.convert(end-start, TimeUnit.NANOSECONDS))); + } + + if (timeout) + me.add(new Exception("Timeout scanning annotations")); + me.ifExceptionThrow(); + } + + /** * @return a new AnnotationParser. This method can be overridden to use a different implementation of * the AnnotationParser. Note that this is considered internal API. @@ -238,7 +378,60 @@ public class AnnotationConfiguration extends AbstractConfiguration { return new AnnotationParser(); } + + /** + * Check if we should use multiple threads to scan for annotations or not + * @param context + * @return + */ + protected boolean isUseMultiThreading(WebAppContext context) + { + //try context attribute to see if we should use multithreading + Object o = context.getAttribute(MULTI_THREADED); + if (o instanceof Boolean) + { + if (((Boolean)o).booleanValue()) + return true; + } + //try server attribute to see if we should use multithreading + o = context.getServer().getAttribute(MULTI_THREADED); + if (o instanceof Boolean) + { + if (((Boolean)o).booleanValue()) + return true; + } + //try system property to see if we should use multithreading + return Boolean.getBoolean(MULTI_THREADED); + } + + + /** + * Work out how long we should wait for the async scanning to occur. + * + * @param context + * @return + */ + protected int getMaxScanWait (WebAppContext context) + { + //try context attribute to get max time in sec to wait for scan completion + Object o = context.getAttribute(MAX_SCAN_WAIT); + if (o != null && o instanceof Number) + { + return ((Number)o).intValue(); + } + //try server attribute to get max time in sec to wait for scan completion + o = context.getServer().getAttribute(MAX_SCAN_WAIT); + if (o != null && o instanceof Number) + { + return ((Number)o).intValue(); + } + //try system property to get max time in sec to wait for scan completion + return Integer.getInteger(MAX_SCAN_WAIT, DEFAULT_MAX_SCAN_WAIT).intValue(); + } + + + /** * @see org.eclipse.jetty.webapp.AbstractConfiguration#cloneConfigure(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.WebAppContext) */ @@ -267,23 +460,21 @@ public class AnnotationConfiguration extends AbstractConfiguration for (ServletContainerInitializer service : scis) { HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class); - ContainerInitializer initializer = new ContainerInitializer(); - initializer.setTarget(service); - initializers.add(initializer); + ContainerInitializer initializer = null; if (annotation != null) - { + { //There is a HandlesTypes annotation on the on the ServletContainerInitializer Class[] classes = annotation.value(); if (classes != null) { - initializer.setInterestedTypes(classes); - + initializer = new ContainerInitializer(service, classes); //If we haven't already done so, we need to register a handler that will //process the whole class hierarchy to satisfy the ServletContainerInitializer if (context.getAttribute(CLASS_INHERITANCE_MAP) == null) { - MultiMap<String> map = new MultiMap<>(); + //MultiMap<String> map = new MultiMap<>(); + ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ConcurrentHashMap<String, ConcurrentHashSet<String>>(); context.setAttribute(CLASS_INHERITANCE_MAP, map); _classInheritanceHandler = new ClassInheritanceHandler(map); } @@ -300,12 +491,21 @@ public class AnnotationConfiguration extends AbstractConfiguration } } else + { + initializer = new ContainerInitializer(service, null); if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass()); + } } else + { + initializer = new ContainerInitializer(service, null); if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass()); + } + + initializers.add(initializer); } + //add a bean to the context which will call the servletcontainerinitializers when appropriate ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER); if (starter != null) @@ -370,8 +570,13 @@ public class AnnotationConfiguration extends AbstractConfiguration List<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>(); //We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspect + long start = 0; + if (LOG.isDebugEnabled()) + start = System.nanoTime(); ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader()); - + if (LOG.isDebugEnabled()) + LOG.debug("Service loaders found in {}ms", (TimeUnit.MILLISECONDS.convert((System.nanoTime()-start), TimeUnit.NANOSECONDS))); + if (loadedInitializers != null) { for (ServletContainerInitializer service : loadedInitializers) @@ -393,28 +598,27 @@ public class AnnotationConfiguration extends AbstractConfiguration * @param parser * @throws Exception */ - public void parseContainerPath (final WebAppContext context, final AnnotationParser 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"); - + LOG.debug("Scanning container jars"); + //always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotations - parser.clearHandlers(); - parser.registerHandlers(_discoverableAnnotationHandlers); - parser.registerHandler(_classInheritanceHandler); - parser.registerHandlers(_containerInitializerAnnotationHandlers); + final Set<Handler> handlers = new HashSet<Handler>(); + handlers.addAll(_discoverableAnnotationHandlers); + handlers.addAll(_containerInitializerAnnotationHandlers); + if (_classInheritanceHandler != null) + handlers.add(_classInheritanceHandler); - //Convert from Resource to URI - ArrayList<URI> containerUris = new ArrayList<URI>(); for (Resource r : context.getMetaData().getContainerResources()) { - URI uri = r.getURI(); - containerUris.add(uri); - } - - parser.parse (containerUris.toArray(new URI[containerUris.size()]), - new ContainerClassNameResolver (context)); + //queue it up for scanning if using multithreaded mode + if (_parserTasks != null) + _parserTasks.add(new ParserTask(parser, handlers, r, _containerClassNameResolver)); + else + //just scan it now + parser.parse(handlers, r, _containerClassNameResolver); + } } @@ -425,9 +629,10 @@ public class AnnotationConfiguration extends AbstractConfiguration * @param parser * @throws Exception */ - public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) - throws Exception - { + public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) throws Exception + { + LOG.debug("Scanning WEB-INF/lib jars"); + List<FragmentDescriptor> frags = context.getMetaData().getFragments(); //email from Rajiv Mordani jsrs 315 7 April 2010 @@ -444,9 +649,8 @@ public class AnnotationConfiguration extends AbstractConfiguration for (Resource r : jars) { //for each jar, we decide which set of annotations we need to parse for - parser.clearHandlers(); + final Set<Handler> handlers = new HashSet<Handler>(); - URI uri = r.getURI(); FragmentDescriptor f = getFragmentFromJar(r, frags); //if its from a fragment jar that is metadata complete, we should skip scanning for @webservlet etc @@ -456,20 +660,26 @@ public class AnnotationConfiguration extends AbstractConfiguration if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty()) { //register the classinheritance handler if there is one - parser.registerHandler(_classInheritanceHandler); - + if (_classInheritanceHandler != null) + handlers.add(_classInheritanceHandler); + //register the handlers for the @HandlesTypes values that are themselves annotations if there are any - parser.registerHandlers(_containerInitializerAnnotationHandlers); - + handlers.addAll(_containerInitializerAnnotationHandlers); + //only register the discoverable annotation handlers if this fragment is not metadata complete, or has no fragment descriptor if (f == null || !isMetaDataComplete(f)) - parser.registerHandlers(_discoverableAnnotationHandlers); + handlers.addAll(_discoverableAnnotationHandlers); - parser.parse(uri, new WebAppClassNameResolver(context)); + if (_parserTasks != null) + _parserTasks.add (new ParserTask(parser, handlers,r, _webAppClassNameResolver)); + else + parser.parse(handlers, r, _webAppClassNameResolver); } } + } + /** * Scan classes in WEB-INF/classes * @@ -480,22 +690,26 @@ public class AnnotationConfiguration extends AbstractConfiguration public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser) throws Exception { - LOG.debug("Scanning classes in WEB-INF/classes"); - - parser.clearHandlers(); - parser.registerHandlers(_discoverableAnnotationHandlers); - parser.registerHandler(_classInheritanceHandler); - parser.registerHandlers(_containerInitializerAnnotationHandlers); + LOG.debug("Scanning WEB-INF/classes"); + + Set<Handler> handlers = new HashSet<Handler>(); + handlers.addAll(_discoverableAnnotationHandlers); + if (_classInheritanceHandler != null) + handlers.add(_classInheritanceHandler); + handlers.addAll(_containerInitializerAnnotationHandlers); for (Resource dir : context.getMetaData().getWebInfClassesDirs()) { - parser.parseDir(dir, new WebAppClassNameResolver(context)); + if (_parserTasks != null) + _parserTasks.add(new ParserTask(parser, handlers, dir, _webAppClassNameResolver)); + else + parser.parse(handlers, dir, _webAppClassNameResolver); } } - /** + /** * Get the web-fragment.xml from a jar * * @param jar diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java index 4a182694e2..201533fdb6 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java @@ -26,10 +26,14 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.jar.JarEntry; +import java.util.jar.JarFile; import java.util.jar.JarInputStream; import org.eclipse.jetty.util.ConcurrentHashSet; @@ -69,7 +73,7 @@ public class AnnotationParser private static final Logger LOG = Log.getLogger(AnnotationParser.class); protected Set<String> _parsedClassNames = new ConcurrentHashSet<String>(); - protected Set<Handler> _handlers = new ConcurrentHashSet<Handler>(); + /** * Convert internal name to simple name @@ -363,6 +367,7 @@ public class AnnotationParser public class MyMethodVisitor extends MethodVisitor { final MethodInfo _mi; + final Set<? extends Handler> _handlers; /** @@ -373,7 +378,7 @@ public class AnnotationParser * @param signature * @param exceptions */ - public MyMethodVisitor( + public MyMethodVisitor(final Set<? extends Handler> handlers, final ClassInfo classInfo, final int access, final String name, @@ -382,6 +387,7 @@ public class AnnotationParser final String[] exceptions) { super(Opcodes.ASM4); + _handlers = handlers; _mi = new MethodInfo(classInfo, name, access, methodDesc,signature, exceptions); } @@ -413,12 +419,14 @@ public class AnnotationParser public class MyFieldVisitor extends FieldVisitor { final FieldInfo _fieldInfo; + final Set<? extends Handler> _handlers; /** * @param classname */ - public MyFieldVisitor(final ClassInfo classInfo, + public MyFieldVisitor(final Set<? extends Handler> handlers, + final ClassInfo classInfo, final int access, final String fieldName, final String fieldType, @@ -426,6 +434,7 @@ public class AnnotationParser final Object value) { super(Opcodes.ASM4); + _handlers = handlers; _fieldInfo = new FieldInfo(classInfo, fieldName, access, fieldType, signature, value); } @@ -458,11 +467,13 @@ public class AnnotationParser { final Resource _containingResource; + final Set<? extends Handler> _handlers; ClassInfo _ci; - public MyClassVisitor(Resource containingResource) + public MyClassVisitor(Set<? extends Handler> handlers, Resource containingResource) { super(Opcodes.ASM4); + _handlers = handlers; _containingResource = containingResource; } @@ -513,7 +524,7 @@ public class AnnotationParser final String[] exceptions) { - return new MyMethodVisitor(_ci, access, name, methodDesc, signature, exceptions); + return new MyMethodVisitor(_handlers, _ci, access, name, methodDesc, signature, exceptions); } /** @@ -528,57 +539,11 @@ public class AnnotationParser final String signature, final Object value) { - return new MyFieldVisitor(_ci, access, fieldName, fieldType, signature, value); + return new MyFieldVisitor(_handlers, _ci, access, fieldName, fieldType, signature, value); } } - /** - * 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 - */ - 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 @@ -598,7 +563,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (String className, ClassNameResolver resolver) + public void parse (Set<? extends Handler> handlers, String className, ClassNameResolver resolver) throws Exception { if (className == null) @@ -613,7 +578,7 @@ public class AnnotationParser if (resource!= null) { Resource r = Resource.newResource(resource); - scanClass(null, r.getInputStream()); + scanClass(handlers, null, r.getInputStream()); } } } @@ -629,7 +594,7 @@ public class AnnotationParser * @param visitSuperClasses * @throws Exception */ - public void parse (Class<?> clazz, ClassNameResolver resolver, boolean visitSuperClasses) + public void parse (Set<? extends Handler> handlers, Class<?> clazz, ClassNameResolver resolver, boolean visitSuperClasses) throws Exception { Class<?> cz = clazz; @@ -644,7 +609,7 @@ public class AnnotationParser if (resource!= null) { Resource r = Resource.newResource(resource); - scanClass(null, r.getInputStream()); + scanClass(handlers, null, r.getInputStream()); } } } @@ -664,13 +629,13 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (String[] classNames, ClassNameResolver resolver) + public void parse (Set<? extends Handler> handlers, String[] classNames, ClassNameResolver resolver) throws Exception { if (classNames == null) return; - parse(Arrays.asList(classNames), resolver); + parse(handlers, Arrays.asList(classNames), resolver); } @@ -681,7 +646,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (List<String> classNames, ClassNameResolver resolver) + public void parse (Set<? extends Handler> handlers, List<String> classNames, ClassNameResolver resolver) throws Exception { for (String s:classNames) @@ -693,7 +658,7 @@ public class AnnotationParser if (resource!= null) { Resource r = Resource.newResource(resource); - scanClass(null, r.getInputStream()); + scanClass(handlers, null, r.getInputStream()); } } } @@ -707,7 +672,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - protected void parseDir (Resource dir, ClassNameResolver resolver) + protected void parseDir (Set<? extends Handler> handlers, Resource dir, ClassNameResolver resolver) throws Exception { //skip dirs whose name start with . (ie hidden) @@ -723,7 +688,7 @@ public class AnnotationParser { Resource res = dir.addPath(files[f]); if (res.isDirectory()) - parseDir(res, resolver); + parseDir(handlers, res, resolver); else { //we've already verified the directories, so just verify the class file name @@ -741,7 +706,7 @@ public class AnnotationParser { Resource r = Resource.newResource(res.getURL()); if (LOG.isDebugEnabled()) {LOG.debug("Scanning class {}", r);}; - scanClass(dir, r.getInputStream()); + scanClass(handlers, dir, r.getInputStream()); } } @@ -765,7 +730,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver) + public void parse (final Set<? extends Handler> handlers, ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver) throws Exception { if (loader==null) @@ -781,7 +746,7 @@ public class AnnotationParser { try { - parseJarEntry(Resource.newResource(jarUri), entry, resolver); + parseJarEntry(handlers, Resource.newResource(jarUri), entry, resolver); } catch (Exception e) { @@ -802,7 +767,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (URI[] uris, final ClassNameResolver resolver) + public void parse (final Set<? extends Handler> handlers, final URI[] uris, final ClassNameResolver resolver) throws Exception { if (uris==null) @@ -812,7 +777,7 @@ public class AnnotationParser { try { - parse(uri, resolver); + parse(handlers, uri, resolver); } catch (Exception e) { @@ -828,13 +793,13 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (URI uri, final ClassNameResolver resolver) + public void parse (final Set<? extends Handler> handlers, URI uri, final ClassNameResolver resolver) throws Exception { if (uri == null) return; - parse (Resource.newResource(uri), resolver); + parse (handlers, Resource.newResource(uri), resolver); } @@ -846,7 +811,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - public void parse (Resource r, final ClassNameResolver resolver) + public void parse (final Set<? extends Handler> handlers, Resource r, final ClassNameResolver resolver) throws Exception { if (r == null) @@ -854,20 +819,20 @@ public class AnnotationParser if (r.exists() && r.isDirectory()) { - parseDir(r, resolver); + parseDir(handlers, r, resolver); return; } String fullname = r.toString(); if (fullname.endsWith(".jar")) { - parseJar(r, resolver); + parseJar(handlers, r, resolver); return; } if (fullname.endsWith(".class")) { - scanClass(null, r.getInputStream()); + scanClass(handlers, null, r.getInputStream()); return; } @@ -884,29 +849,56 @@ public class AnnotationParser * @param resolver * @throws Exception */ - protected void parseJar (Resource jarResource, final ClassNameResolver resolver) + protected void parseJar (Set<? extends Handler> handlers, Resource jarResource, final ClassNameResolver resolver) throws Exception { if (jarResource == null) return; - if (jarResource.toString().endsWith(".jar")) { if (LOG.isDebugEnabled()) {LOG.debug("Scanning jar {}", jarResource);}; - - //treat it as a jar that we need to open and scan all entries from + + //treat it as a jar that we need to open and scan all entries from + //TODO alternative impl + /* + Collection<Resource> resources = Resource.newResource("jar:"+jarResource+"!/").getAllResources(); + for (Resource r:resources) + { + //skip directories + if (r.isDirectory()) + continue; + + String name = r.getName(); + name = name.substring(name.indexOf("!/")+2); + + //check file is a valid class file name + if (isValidClassFileName(name) && isValidClassFilePath(name)) + { + + String shortName = name.replace('/', '.').substring(0,name.length()-6); + + if ((resolver == null) + || + (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName)))) + { + if (LOG.isDebugEnabled()) {LOG.debug("Scanning class from jar {}", r);}; + scanClass(handlers, jarResource, r.getInputStream()); + } + } + }*/ + InputStream in = jarResource.getInputStream(); if (in==null) return; - + JarInputStream jar_in = new JarInputStream(in); try { JarEntry entry = jar_in.getNextJarEntry(); while (entry!=null) { - parseJarEntry(jarResource, entry, resolver); + parseJarEntry(handlers, jarResource, entry, resolver); entry = jar_in.getNextJarEntry(); } } @@ -924,7 +916,7 @@ public class AnnotationParser * @param resolver * @throws Exception */ - protected void parseJarEntry (Resource jar, JarEntry entry, final ClassNameResolver resolver) + protected void parseJarEntry (Set<? extends Handler> handlers, Resource jar, JarEntry entry, final ClassNameResolver resolver) throws Exception { if (jar == null || entry == null) @@ -947,7 +939,7 @@ public class AnnotationParser { Resource clazz = Resource.newResource("jar:"+jar.getURI()+"!/"+name); if (LOG.isDebugEnabled()) {LOG.debug("Scanning class from jar {}", clazz);}; - scanClass(jar, clazz.getInputStream()); + scanClass(handlers, jar, clazz.getInputStream()); } } } @@ -961,11 +953,11 @@ public class AnnotationParser * @param is * @throws IOException */ - protected void scanClass (Resource containingResource, InputStream is) + protected void scanClass (Set<? extends Handler> handlers, Resource containingResource, InputStream is) throws IOException { ClassReader reader = new ClassReader(is); - reader.accept(new MyClassVisitor(containingResource), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES); + reader.accept(new MyClassVisitor(handlers, containingResource), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES); } /** diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java index a5cfa20e37..14f1198af8 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java @@ -19,9 +19,13 @@ package org.eclipse.jetty.annotations; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler; import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo; +import org.eclipse.jetty.util.ConcurrentHashSet; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -35,10 +39,10 @@ public class ClassInheritanceHandler extends AbstractHandler { private static final Logger LOG = Log.getLogger(ClassInheritanceHandler.class); - MultiMap<String> _inheritanceMap; + ConcurrentHashMap<String, ConcurrentHashSet<String>> _inheritanceMap; - public ClassInheritanceHandler(MultiMap<String> map) + public ClassInheritanceHandler(ConcurrentHashMap<String, ConcurrentHashSet<String>> map) { _inheritanceMap = map; } @@ -49,15 +53,37 @@ public class ClassInheritanceHandler extends AbstractHandler { for (int i=0; classInfo.getInterfaces() != null && i < classInfo.getInterfaces().length;i++) { - _inheritanceMap.add (classInfo.getInterfaces()[i], classInfo.getClassName()); + addToInheritanceMap(classInfo.getInterfaces()[i], classInfo.getClassName()); + //_inheritanceMap.add (classInfo.getInterfaces()[i], classInfo.getClassName()); } //To save memory, we don't record classes that only extend Object, as that can be assumed if (!"java.lang.Object".equals(classInfo.getSuperName())) - _inheritanceMap.add(classInfo.getSuperName(), classInfo.getClassName()); + { + addToInheritanceMap(classInfo.getSuperName(), classInfo.getClassName()); + //_inheritanceMap.add(classInfo.getSuperName(), classInfo.getClassName()); + } } catch (Exception e) { LOG.warn(e); } } + + private void addToInheritanceMap (String interfaceOrSuperClassName, String implementingOrExtendingClassName) + { + + //As it is likely that the interfaceOrSuperClassName is already in the map, try getting it first + ConcurrentHashSet<String> implementingClasses = _inheritanceMap.get(interfaceOrSuperClassName); + //If it isn't in the map, then add it in, but test to make sure that someone else didn't get in + //first and add it + if (implementingClasses == null) + { + implementingClasses = new ConcurrentHashSet<String>(); + ConcurrentHashSet<String> tmp = _inheritanceMap.putIfAbsent(interfaceOrSuperClassName, implementingClasses); + if (tmp != null) + implementingClasses = tmp; + } + + implementingClasses.add(implementingOrExtendingClassName); + } } diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java index d912cdc34e..6eff325a92 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java @@ -39,8 +39,8 @@ import org.eclipse.jetty.plus.annotation.ContainerInitializer; */ public class ContainerInitializerAnnotationHandler extends AbstractHandler { - ContainerInitializer _initializer; - Class _annotation; + final ContainerInitializer _initializer; + final Class _annotation; public ContainerInitializerAnnotationHandler (ContainerInitializer initializer, Class annotation) { diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java index a7e5304adb..1fde73510c 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java @@ -21,8 +21,10 @@ package org.eclipse.jetty.annotations; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jetty.plus.annotation.ContainerInitializer; +import org.eclipse.jetty.util.ConcurrentHashSet; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; @@ -60,11 +62,11 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle if (initializers == null) return; - MultiMap classMap = (MultiMap)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP); + ConcurrentHashMap<String, ConcurrentHashSet<String>> map = ( ConcurrentHashMap<String, ConcurrentHashSet<String>>)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP); for (ContainerInitializer i : initializers) { - configureHandlesTypes(_context, i, classMap); + configureHandlesTypes(_context, i, map); //instantiate ServletContainerInitializers, call doStart try @@ -80,13 +82,13 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle } - private void configureHandlesTypes (WebAppContext context, ContainerInitializer initializer, MultiMap<String> classMap) + private void configureHandlesTypes (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap) { doHandlesTypesAnnotations(context, initializer, classMap); doHandlesTypesClasses(context, initializer, classMap); } - private void doHandlesTypesAnnotations(WebAppContext context, ContainerInitializer initializer, MultiMap<String> classMap) + private void doHandlesTypesAnnotations(WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap) { if (initializer == null) return; @@ -96,26 +98,26 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle //We have already found the classes that directly have an annotation that was in the HandlesTypes //annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance //hierarchy to find classes that extend or implement them. - if (initializer.getAnnotatedTypeNames() != null) + Set<String> annotatedClassNames = initializer.getAnnotatedTypeNames(); + if (annotatedClassNames != null && !annotatedClassNames.isEmpty()) { if (classMap == null) throw new IllegalStateException ("No class hierarchy"); - Set<String> annotatedClassNames = new HashSet<String>(initializer.getAnnotatedTypeNames()); for (String name : annotatedClassNames) { //add the class that has the annotation initializer.addApplicableTypeName(name); //find and add the classes that inherit the annotation - addInheritedTypes(classMap, initializer, (List<String>)classMap.getValues(name)); + addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(name)); } } } - private void doHandlesTypesClasses (WebAppContext context, ContainerInitializer initializer, MultiMap<String> classMap) + private void doHandlesTypesClasses (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap) { if (initializer == null) return; @@ -135,14 +137,14 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle { //find and add the classes that implement or extend the class. //but not including the class itself - addInheritedTypes(classMap, initializer, (List<String>)classMap.getValues(c.getName())); + addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(c.getName())); } } } } - private void addInheritedTypes (MultiMap classMap, ContainerInitializer initializer, List<String> names) + private void addInheritedTypes (ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap, ContainerInitializer initializer, ConcurrentHashSet<String> names) { if (names == null || names.isEmpty()) return; @@ -153,7 +155,7 @@ public class ServletContainerInitializersStarter extends AbstractLifeCycle initializer.addApplicableTypeName(s); //walk the hierarchy and find all types that extend or implement the class - addInheritedTypes(classMap, initializer, (List<String>)classMap.getValues(s)); + addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(s)); } } } diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java index ffe5597c27..fe5cc277e3 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java @@ -18,14 +18,11 @@ package org.eclipse.jetty.annotations; -import java.util.List; - import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo; import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo; import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo; 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; /** @@ -41,11 +38,7 @@ public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHa { super(context); } - - public WebFilterAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list) - { - super(context, list); - } + @Override public void handle(ClassInfo info, String annotationName) diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java index 396eaea1d8..5ba94dd723 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java @@ -18,14 +18,11 @@ package org.eclipse.jetty.annotations; -import java.util.List; - import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo; import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo; import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo; 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 @@ -37,11 +34,7 @@ public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotation super(context); } - public WebListenerAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list) - { - super(context, list); - } - + /** * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handle(ClassAnnotationInfo) */ diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java index ea300925ae..6a675a33c7 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java @@ -43,11 +43,6 @@ public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationH super(context); } - public WebServletAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list) - { - super(context, list); - } - /** * Handle discovering a WebServlet annotation. diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java index 7d5d902444..fddde8a956 100644 --- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java +++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java @@ -24,8 +24,10 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.naming.Context; import javax.naming.InitialContext; @@ -34,6 +36,7 @@ import org.eclipse.jetty.annotations.AnnotationParser.AbstractHandler; import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo; import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo; import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo; +import org.eclipse.jetty.util.ConcurrentHashSet; import org.eclipse.jetty.util.MultiMap; import org.junit.After; import org.junit.Test; @@ -92,8 +95,7 @@ public class TestAnnotationInheritance SampleHandler handler = new SampleHandler(); AnnotationParser parser = new AnnotationParser(); - parser.registerHandler(handler); - parser.parse(classNames, new ClassNameResolver () + parser.parse(Collections.singleton(handler), classNames, new ClassNameResolver () { public boolean isExcluded(String name) { @@ -129,8 +131,7 @@ public class TestAnnotationInheritance { SampleHandler handler = new SampleHandler(); AnnotationParser parser = new AnnotationParser(); - parser.registerHandler(handler); - parser.parse(ClassB.class, new ClassNameResolver () + parser.parse(Collections.singleton(handler), ClassB.class, new ClassNameResolver () { public boolean isExcluded(String name) { @@ -166,8 +167,7 @@ public class TestAnnotationInheritance { AnnotationParser parser = new AnnotationParser(); SampleHandler handler = new SampleHandler(); - parser.registerHandler(handler); - parser.parse(ClassA.class.getName(), new ClassNameResolver() + parser.parse(Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver() { public boolean isExcluded(String name) { @@ -187,7 +187,7 @@ public class TestAnnotationInheritance handler.annotatedFields.clear(); handler.annotatedMethods.clear(); - parser.parse (ClassA.class.getName(), new ClassNameResolver() + parser.parse (Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver() { public boolean isExcluded(String name) { @@ -205,11 +205,10 @@ public class TestAnnotationInheritance @Test public void testTypeInheritanceHandling() throws Exception { - MultiMap map = new MultiMap(); + ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ConcurrentHashMap<String, ConcurrentHashSet<String>>(); AnnotationParser parser = new AnnotationParser(); ClassInheritanceHandler handler = new ClassInheritanceHandler(map); - parser.registerHandler(handler); class Foo implements InterfaceD { @@ -221,21 +220,22 @@ public class TestAnnotationInheritance classNames.add(InterfaceD.class.getName()); classNames.add(Foo.class.getName()); - parser.parse(classNames, null); + parser.parse(Collections.singleton(handler), classNames, null); 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]); + + + assertTrue (map.keySet().contains("org.eclipse.jetty.annotations.ClassA")); + assertTrue (map.keySet().contains("org.eclipse.jetty.annotations.InterfaceD")); + ConcurrentHashSet<String> classes = map.get("org.eclipse.jetty.annotations.ClassA"); + assertEquals(1, classes.size()); + assertEquals ("org.eclipse.jetty.annotations.ClassB", classes.iterator().next()); + + classes = map.get("org.eclipse.jetty.annotations.InterfaceD"); + assertEquals(2, classes.size()); + assertTrue(classes.contains("org.eclipse.jetty.annotations.ClassB")); + assertTrue(classes.contains(Foo.class.getName())); } } diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java index 0b46345cb8..1f0eafcd6f 100644 --- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java +++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java @@ -31,12 +31,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo; import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo; +import org.eclipse.jetty.annotations.AnnotationParser.Handler; import org.eclipse.jetty.annotations.AnnotationParser.MethodInfo; import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.IO; @@ -108,10 +110,8 @@ public class TestAnnotationParser } } - parser.registerHandler(new SampleAnnotationHandler()); - //long start = System.currentTimeMillis(); - parser.parse(classNames,new ClassNameResolver() + parser.parse(Collections.singleton(new SampleAnnotationHandler()), classNames,new ClassNameResolver() { public boolean isExcluded(String name) { @@ -162,8 +162,7 @@ public class TestAnnotationParser } } - parser.registerHandler(new MultiAnnotationHandler()); - parser.parse(classNames,null); + parser.parse(Collections.singleton(new MultiAnnotationHandler()), classNames,null); } @Test @@ -171,7 +170,8 @@ public class TestAnnotationParser { File badClassesJar = MavenTestingUtils.getTestResourceFile("bad-classes.jar"); AnnotationParser parser = new AnnotationParser(); - parser.parse(badClassesJar.toURI(),null); + Set<Handler> emptySet = Collections.emptySet(); + parser.parse(emptySet, badClassesJar.toURI(),null); // only the valid classes inside bad-classes.jar should be parsed. If any invalid classes are parsed and exception would be thrown here } @@ -194,10 +194,9 @@ public class TestAnnotationParser // Setup annotation scanning AnnotationParser parser = new AnnotationParser(); - parser.registerHandler(tracker); // Parse - parser.parse(basedir.toURI(),null); + parser.parse(Collections.singleton(tracker), basedir.toURI(),null); // Validate Assert.assertThat("Found Class", tracker.foundClasses, contains(ClassA.class.getName())); diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java index d6614ed239..e1f5a989fd 100644 --- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java +++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -74,9 +75,8 @@ public class TestServletAnnotations List<DiscoveredAnnotation> results = new ArrayList<DiscoveredAnnotation>(); TestWebServletAnnotationHandler handler = new TestWebServletAnnotationHandler(wac, results); - parser.registerHandler(handler); - - parser.parse(classes, new ClassNameResolver () + + parser.parse(Collections.singleton(handler), classes, new ClassNameResolver () { public boolean isExcluded(String name) { |