Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2013-09-26 08:26:13 +0000
committerJan Bartel2013-09-30 03:27:05 +0000
commit04002898263b3d408f7f4851906dfcb7185902ee (patch)
tree47886b39b850fb96f7c1a5872eb964556590001b
parent0fd656dcbe0102c7e9deecaac9ac4de1a5016c62 (diff)
downloadorg.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
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java10
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java336
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java158
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java34
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java4
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java24
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java9
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java9
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java5
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java42
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java15
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java6
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenAnnotationConfiguration.java40
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java64
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java36
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java15
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java2
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java34
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java30
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java16
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java113
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java8
24 files changed, 633 insertions, 401 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)
{
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenAnnotationConfiguration.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenAnnotationConfiguration.java
index a16c4dbcc3..3f15a59b32 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenAnnotationConfiguration.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenAnnotationConfiguration.java
@@ -19,10 +19,12 @@
package org.eclipse.jetty.maven.plugin;
import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
-import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.AnnotationParser;
+import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -50,10 +52,11 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
if (metaData == null)
throw new IllegalStateException ("No metadata");
- parser.clearHandlers();
- parser.registerHandlers(_discoverableAnnotationHandlers);
- parser.registerHandler(_classInheritanceHandler);
- parser.registerHandlers(_containerInitializerAnnotationHandlers);
+ Set<Handler> handlers = new HashSet<Handler>();
+ handlers.addAll(_discoverableAnnotationHandlers);
+ if (_classInheritanceHandler != null)
+ handlers.add(_classInheritanceHandler);
+ handlers.addAll(_containerInitializerAnnotationHandlers);
for (File f:jwac.getClassPathFiles())
@@ -61,7 +64,7 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
//scan the equivalent of the WEB-INF/classes directory that has been synthesised by the plugin
if (f.isDirectory() && f.exists())
{
- doParse(context, parser, Resource.newResource(f.toURI()));
+ doParse(handlers, context, parser, Resource.newResource(f.toURI()));
}
}
@@ -72,32 +75,19 @@ public class MavenAnnotationConfiguration extends AnnotationConfiguration
Resource classesDir = context.getWebInf().addPath("classes/");
if (classesDir.exists())
{
- doParse(context, parser, classesDir);
+ doParse(handlers, context, parser, classesDir);
}
}
}
}
- public void doParse (final WebAppContext context, final AnnotationParser parser, Resource resource)
+ public void doParse (final Set<? extends Handler> handlers, final WebAppContext context, final AnnotationParser parser, Resource resource)
throws Exception
{
- parser.parse(resource, new ClassNameResolver()
- {
- public boolean isExcluded (String name)
- {
- if (context.isSystemClass(name)) return true;
- if (context.isServerClass(name)) return false;
- return false;
- }
-
- public boolean shouldOverride (String name)
- {
- //looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
- if (context.isParentLoaderPriority())
- return false;
- return true;
- }
- });
+ if (_parserTasks != null)
+ _parserTasks.add(new ParserTask(parser, handlers, resource, _webAppClassNameResolver));
+ else
+ parser.parse(handlers, resource, _webAppClassNameResolver);
}
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
index e5d2d2cf13..d70d1ea797 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
@@ -18,7 +18,10 @@
package org.eclipse.jetty.osgi.annotations;
-import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
@@ -34,7 +37,27 @@ import org.osgi.framework.Constants;
*/
public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration
{
+ public class BundleParserTask extends ParserTask
+ {
+
+ public BundleParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
+ {
+ super(parser, handlers, resource, resolver);
+ }
+ public Void call() throws Exception
+ {
+ if (_parser != null)
+ {
+ org.eclipse.jetty.osgi.annotations.AnnotationParser osgiAnnotationParser = (org.eclipse.jetty.osgi.annotations.AnnotationParser)_parser;
+ Bundle bundle = osgiAnnotationParser.getBundle(_resource);
+ osgiAnnotationParser.parse(_handlers, bundle, _resolver);
+ }
+ return null;
+ }
+ }
+
+
/**
* This parser scans the bundles using the OSGi APIs instead of assuming a jar.
*/
@@ -64,7 +87,7 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle);
if (fragAndRequiredBundles != null)
{
- //index:
+ //index and scan fragments
for (Bundle bundle : fragAndRequiredBundles)
{
Resource bundleRes = oparser.indexBundle(bundle);
@@ -72,19 +95,16 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
{
context.getMetaData().addWebInfJar(bundleRes);
}
- }
-
- //scan the fragments
- for (Bundle fragmentBundle : fragAndRequiredBundles)
- {
- if (fragmentBundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
+
+ if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
{
//a fragment indeed:
- parseFragmentBundle(context,oparser,webbundle,fragmentBundle);
+ parseFragmentBundle(context,oparser,webbundle,bundle);
}
}
}
//scan ourselves
+ oparser.indexBundle(webbundle);
parseWebBundle(context,oparser,webbundle);
//scan the WEB-INF/lib
@@ -146,17 +166,21 @@ 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();
- parser.registerHandlers(_discoverableAnnotationHandlers);
- parser.registerHandler(_classInheritanceHandler);
- parser.registerHandlers(_containerInitializerAnnotationHandlers);
-
- parser.parse(bundle,createClassNameResolver(context));
+ Bundle webbundle, Bundle bundle) throws Exception
+ {
+
+ Resource bundleRes = parser.getResource(bundle);
+ Set<Handler> handlers = new HashSet<Handler>();
+ handlers.addAll(_discoverableAnnotationHandlers);
+ if (_classInheritanceHandler != null)
+ handlers.add(_classInheritanceHandler);
+ handlers.addAll(_containerInitializerAnnotationHandlers);
+
+ ClassNameResolver classNameResolver = createClassNameResolver(context);
+ if (_parserTasks != null)
+ _parserTasks.add(new BundleParserTask(parser, handlers, bundleRes, classNameResolver));
+ else
+ parser.parse(handlers, bundle, classNameResolver);
}
/**
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
index c2c14e3ed7..e502435dac 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
@@ -29,9 +29,11 @@ import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
+import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.resource.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@@ -41,11 +43,12 @@ import org.osgi.framework.Constants;
*/
public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser
{
- private Set<URI> _alreadyParsed = new HashSet<URI>();
+ private Set<URI> _alreadyParsed = new ConcurrentHashSet<URI>();
- private Map<URI,Bundle> _uriToBundle = new HashMap<URI, Bundle>();
- private Map<Bundle,Resource> _resourceToBundle = new HashMap<Bundle,Resource>();
- private Map<Bundle,URI> _bundleToUri = new HashMap<Bundle, URI>();
+ private ConcurrentHashMap<URI,Bundle> _uriToBundle = new ConcurrentHashMap<URI, Bundle>();
+ private ConcurrentHashMap<Bundle,Resource> _bundleToResource = new ConcurrentHashMap<Bundle,Resource>();
+ private ConcurrentHashMap<Resource, Bundle> _resourceToBundle = new ConcurrentHashMap<Resource, Bundle>();
+ private ConcurrentHashMap<Bundle,URI> _bundleToUri = new ConcurrentHashMap<Bundle, URI>();
/**
* Keep track of a jetty URI Resource and its associated OSGi bundle.
@@ -58,9 +61,10 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
File bundleFile = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation(bundle);
Resource resource = Resource.newResource(bundleFile.toURI());
URI uri = resource.getURI();
- _uriToBundle.put(uri,bundle);
- _bundleToUri.put(bundle,uri);
- _resourceToBundle.put(bundle,resource);
+ _uriToBundle.putIfAbsent(uri,bundle);
+ _bundleToUri.putIfAbsent(bundle,uri);
+ _bundleToResource.putIfAbsent(bundle,resource);
+ _resourceToBundle.putIfAbsent(resource,bundle);
return resource;
}
protected URI getURI(Bundle bundle)
@@ -69,13 +73,19 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
}
protected Resource getResource(Bundle bundle)
{
- return _resourceToBundle.get(bundle);
+ return _bundleToResource.get(bundle);
}
+ protected Bundle getBundle (Resource resource)
+ {
+ return _resourceToBundle.get(resource);
+ }
+
+
/**
*
*/
@Override
- public void parse (URI[] uris, ClassNameResolver resolver)
+ public void parse (Set<? extends Handler> handlers, URI[] uris, ClassNameResolver resolver)
throws Exception
{
for (URI uri : uris)
@@ -89,16 +99,16 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
}
//a jar in WEB-INF/lib or the WEB-INF/classes
//use the behavior of the super class for a standard jar.
- super.parse(new URI[] {uri},resolver);
+ super.parse(handlers, new URI[] {uri},resolver);
}
else
{
- parse(associatedBundle,resolver);
+ parse(handlers, associatedBundle,resolver);
}
}
}
- protected void parse(Bundle bundle, ClassNameResolver resolver)
+ protected void parse(Set<? extends Handler> handlers, Bundle bundle, ClassNameResolver resolver)
throws Exception
{
URI uri = _bundleToUri.get(bundle);
@@ -190,7 +200,7 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
//transform into a classname to pass to the resolver
String shortName = name.replace('/', '.').substring(0,name.length()-6);
if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
- scanClass(getResource(bundle), classUrl.openStream());
+ scanClass(handlers, getResource(bundle), classUrl.openStream());
}
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
index 197ee2cb2c..b47b8ac908 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
@@ -21,7 +21,11 @@ package org.eclipse.jetty.osgi.boot;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
@@ -53,8 +57,8 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
- List<Resource> frags = (List<Resource>) context.getAttribute(METAINF_FRAGMENTS);
- List<Resource> resfrags = (List<Resource>) context.getAttribute(METAINF_RESOURCES);
+ Map<Resource, Resource> frags = (Map<Resource, Resource>) context.getAttribute(METAINF_FRAGMENTS);
+ Set<Resource> resfrags = (Set<Resource>) context.getAttribute(METAINF_RESOURCES);
List<Resource> tldfrags = (List<Resource>) context.getAttribute(METAINF_TLDS);
Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
@@ -73,10 +77,11 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
if (frags == null)
{
- frags = new ArrayList<Resource>();
+ frags = new HashMap<Resource,Resource>();
context.setAttribute(METAINF_FRAGMENTS, frags);
}
- frags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()));
+ frags.put(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()),
+ Resource.newResource(webFrag));
}
if (resEnum != null && resEnum.hasMoreElements())
{
@@ -92,7 +97,7 @@ public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
if (resfrags == null)
{
- resfrags = new ArrayList<Resource>();
+ resfrags = new HashSet<Resource>();
context.setAttribute(METAINF_RESOURCES, resfrags);
}
resfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(resourcesEntry)));
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
index b606db40fa..75d79a8fad 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
@@ -212,7 +212,7 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
}
}
if (!appendedResourcesPath.isEmpty())
- context.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
+ context.setAttribute(WebInfConfiguration.RESOURCE_DIRS, new HashSet<Resource>(appendedResourcesPath.values()));
}
}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
index 6ac2102db4..dcdda325b0 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
@@ -18,26 +18,28 @@
package org.eclipse.jetty.plus.annotation;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
-import javax.servlet.ServletContextListener;
+import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
public class ContainerInitializer
{
- protected ServletContainerInitializer _target;
- protected Class[] _interestedTypes;
- protected Set<String> _applicableTypeNames;
- protected Set<String> _annotatedTypeNames;
+ final protected ServletContainerInitializer _target;
+ final protected Class[] _interestedTypes;
+ protected Set<String> _applicableTypeNames = new ConcurrentHashSet<String>();
+ protected Set<String> _annotatedTypeNames = new ConcurrentHashSet<String>();
- public void setTarget (ServletContainerInitializer target)
+ public ContainerInitializer (ServletContainerInitializer target, Class[] classes)
{
_target = target;
+ _interestedTypes = classes;
}
public ServletContainerInitializer getTarget ()
@@ -50,10 +52,6 @@ public class ContainerInitializer
return _interestedTypes;
}
- public void setInterestedTypes (Class[] interestedTypes)
- {
- _interestedTypes = interestedTypes;
- }
/**
* A class has been found that has an annotation of interest
@@ -62,26 +60,22 @@ public class ContainerInitializer
*/
public void addAnnotatedTypeName (String className)
{
- if (_annotatedTypeNames == null)
- _annotatedTypeNames = new HashSet<String>();
_annotatedTypeNames.add(className);
}
public Set<String> getAnnotatedTypeNames ()
{
- return _annotatedTypeNames;
+ return Collections.unmodifiableSet(_annotatedTypeNames);
}
public void addApplicableTypeName (String className)
{
- if (_applicableTypeNames == null)
- _applicableTypeNames = new HashSet<String>();
_applicableTypeNames.add(className);
}
public Set<String> getApplicableTypeNames ()
{
- return _applicableTypeNames;
+ return Collections.unmodifiableSet(_applicableTypeNames);
}
@@ -97,11 +91,9 @@ public class ContainerInitializer
try
{
- if (_applicableTypeNames != null)
- {
- for (String s : _applicableTypeNames)
- classes.add(Loader.loadClass(context.getClass(), s));
- }
+ for (String s : _applicableTypeNames)
+ classes.add(Loader.loadClass(context.getClass(), s));
+
context.getServletContext().setExtendedListenerTypes(true);
_target.onStartup(classes, context.getServletContext());
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
index 7b9b9bbaae..536b780ab4 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
@@ -29,7 +29,9 @@ import java.net.URI;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.text.DateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import org.eclipse.jetty.util.B64Code;
@@ -663,6 +665,34 @@ public abstract class Resource implements ResourceFactory, Closeable
}
/* ------------------------------------------------------------ */
+ public Collection<Resource> getAllResources()
+ {
+ try
+ {
+ ArrayList<Resource> deep=new ArrayList<>();
+ {
+ String[] list=list();
+ if (list!=null)
+ {
+ for (String i:list)
+ {
+ Resource r=addPath(i);
+ if (r.isDirectory())
+ deep.addAll(r.getAllResources());
+ else
+ deep.add(r);
+ }
+ }
+ }
+ return deep;
+ }
+ catch(Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
/** Generate a properly encoded URL from a {@link File} instance.
* @param file Target file.
* @return URL of the target file.
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
index c811daa764..6fd85423b3 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
@@ -30,9 +30,9 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
-
import java.util.zip.ZipFile;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@@ -297,10 +297,20 @@ public class ResourceTest
assertTrue(entries.contains("numbers"));
IO.delete(extract);
-
-
}
+ /* ------------------------------------------------------------ */
+ @Test
+ public void testJarFileGetAllResoures()
+ throws Exception
+ {
+ String s = "jar:"+__userURL+"TestData/test.zip!/subdir/";
+ Resource r = Resource.newResource(s);
+ Collection<Resource> deep=r.getAllResources();
+
+ assertEquals(4, deep.size());
+ }
+
@Test
public void testJarFileIsContainedIn ()
throws Exception
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
index eb8129228f..ff28d0562a 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java
@@ -19,7 +19,7 @@
package org.eclipse.jetty.webapp;
-import java.util.List;
+import java.util.Map;
import org.eclipse.jetty.util.resource.Resource;
@@ -70,18 +70,18 @@ public class FragmentConfiguration extends AbstractConfiguration
public void findWebFragments (final WebAppContext context, final MetaData metaData) throws Exception
{
@SuppressWarnings("unchecked")
- List<Resource> frags = (List<Resource>)context.getAttribute(FRAGMENT_RESOURCES);
+ Map<Resource, Resource> frags = (Map<Resource,Resource>)context.getAttribute(FRAGMENT_RESOURCES);
if (frags!=null)
{
- for (Resource frag : frags)
+ for (Resource key : frags.keySet())
{
- if (frag.isDirectory()) //tolerate the case where the library is a directory, not a jar. useful for OSGi for example
+ if (key.isDirectory()) //tolerate the case where the library is a directory, not a jar. useful for OSGi for example
{
- metaData.addFragment(frag, Resource.newResource(frag.getURL()+"/META-INF/web-fragment.xml"));
+ metaData.addFragment(key, frags.get(key));
}
else //the standard case: a jar most likely inside WEB-INF/lib
{
- metaData.addFragment(frag, Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
+ metaData.addFragment(key, frags.get(key));
}
}
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
index 7c476586a9..1bd781e873 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
@@ -288,7 +288,17 @@ public class MetaData
}
}
- public void addDiscoveredAnnotation (DiscoveredAnnotation annotation)
+
+ /**
+ * Add an annotation that has been discovered on a class, method or field within a resource
+ * eg a jar or dir.
+ *
+ * This method is synchronized as it is anticipated that it may be called by many threads
+ * during the annotation scanning phase.
+ *
+ * @param annotation
+ */
+ public synchronized void addDiscoveredAnnotation (DiscoveredAnnotation annotation)
{
if (annotation == null)
return;
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
index df913b508d..b7c4e0f0b2 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
@@ -21,8 +21,13 @@ package org.eclipse.jetty.webapp;
import java.net.URI;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
import java.util.jar.JarEntry;
import org.eclipse.jetty.util.log.Log;
@@ -45,57 +50,51 @@ public class MetaInfConfiguration extends AbstractConfiguration
public static final String METAINF_TLDS = TagLibConfiguration.TLD_RESOURCES;
public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES;
- public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_URLS;
+ public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS;
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
- //Merge all container and webinf lib jars to look for META-INF resources
-
+ //Merge all container and webinf lib jars to look for META-INF resources
ArrayList<Resource> jars = new ArrayList<Resource>();
jars.addAll(context.getMetaData().getContainerResources());
jars.addAll(context.getMetaData().getWebInfJars());
- JarScanner scanner = new JarScanner()
+ //Scan jars for META-INF information
+ if (jars != null)
{
- public void processEntry(URI jarUri, JarEntry entry)
+ for (Resource r : jars)
{
- try
+ URI uri = r.getURI();
+ Resource fragXml = Resource.newResource("jar:"+uri+"!/META-INF/web-fragment.xml");
+ if (fragXml.exists())
{
- MetaInfConfiguration.this.processEntry(context,jarUri,entry);
+ //add mapping for resource->fragment
+ Map<Resource, Resource> fragments = (Map<Resource,Resource>)context.getAttribute(METAINF_FRAGMENTS);
+ if (fragments == null)
+ {
+ fragments = new HashMap<Resource, Resource>();
+ context.setAttribute(METAINF_FRAGMENTS, fragments);
+ }
+ fragments.put(r, fragXml);
}
- catch (Exception e)
+
+ Resource resourcesDir = Resource.newResource("jar:"+uri+"!/META-INF/resources");
+ if (resourcesDir.exists())
{
- LOG.warn("Problem processing jar entry " + entry, e);
+ //add resources dir
+ Set<Resource> dirs = (Set<Resource>)context.getAttribute(METAINF_RESOURCES);
+ if (dirs == null)
+ {
+ dirs = new HashSet<Resource>();
+ context.setAttribute(METAINF_RESOURCES, dirs);
+ }
+ dirs.add(resourcesDir);
}
}
- };
-
-
- //Scan jars for META-INF information
- if (jars != null)
- {
- URI[] uris = new URI[jars.size()];
- int i=0;
- for (Resource r : jars)
- {
- uris[i++] = r.getURI();
- }
- scanner.scan(null, uris, true);
}
}
- @Override
- public void configure(WebAppContext context) throws Exception
- {
-
- }
-
- @Override
- public void deconfigure(WebAppContext context) throws Exception
- {
-
- }
-
+
@Override
public void postConfigure(WebAppContext context) throws Exception
{
@@ -103,50 +102,4 @@ public class MetaInfConfiguration extends AbstractConfiguration
context.setAttribute(METAINF_RESOURCES, null);
context.setAttribute(METAINF_TLDS, null);
}
-
- public void addResource (WebAppContext context, String attribute, Resource jar)
- {
- @SuppressWarnings("unchecked")
- List<Resource> list = (List<Resource>)context.getAttribute(attribute);
- if (list==null)
- {
- list=new ArrayList<Resource>();
- context.setAttribute(attribute,list);
- }
- if (!list.contains(jar))
- list.add(jar);
- }
-
-
- protected void processEntry(WebAppContext context, URI jarUri, JarEntry entry)
- {
- String name = entry.getName();
-
- if (!name.startsWith("META-INF/"))
- return;
-
- try
- {
- if (name.equals("META-INF/web-fragment.xml") && context.isConfigurationDiscovered())
- {
- addResource(context,METAINF_FRAGMENTS,Resource.newResource(jarUri));
- }
- else if (name.equals("META-INF/resources/") && context.isConfigurationDiscovered())
- {
- addResource(context,METAINF_RESOURCES,Resource.newResource("jar:"+jarUri+"!/META-INF/resources"));
- }
- else
- {
- String lcname = name.toLowerCase(Locale.ENGLISH);
- if (lcname.endsWith(".tld"))
- {
- addResource(context,METAINF_TLDS,Resource.newResource("jar:"+jarUri+"!/"+name));
- }
- }
- }
- catch(Exception e)
- {
- context.getServletContext().log(jarUri+"!/"+name,e);
- }
- }
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
index d0d4085161..d9ebc2fb9e 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
@@ -27,7 +27,9 @@ import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import java.util.StringTokenizer;
+import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.eclipse.jetty.server.Connector;
@@ -54,7 +56,7 @@ public class WebInfConfiguration extends AbstractConfiguration
* If set, to a list of URLs, these resources are added to the context
* resource base as a resource collection.
*/
- public static final String RESOURCE_URLS = "org.eclipse.jetty.resources";
+ public static final String RESOURCE_DIRS = "org.eclipse.jetty.resources";
protected Resource _preUnpackBaseResource;
@@ -140,7 +142,7 @@ public class WebInfConfiguration extends AbstractConfiguration
}
}
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
-
+
//No pattern to appy to classes, just add to metadata
context.getMetaData().setWebInfClassesDirs(findClassDirs(context));
}
@@ -175,7 +177,7 @@ public class WebInfConfiguration extends AbstractConfiguration
// Look for extra resource
@SuppressWarnings("unchecked")
- List<Resource> resources = (List<Resource>)context.getAttribute(RESOURCE_URLS);
+ Set<Resource> resources = (Set<Resource>)context.getAttribute(RESOURCE_DIRS);
if (resources!=null)
{
Resource[] collection=new Resource[resources.size()+1];

Back to the top