Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
//// ========================================================================// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.// ------------------------------------------------------------------------// All rights reserved. This program and the accompanying materials// are made available under the terms of the Eclipse Public License v1.0// and Apache License v2.0 which accompanies this distribution.//// The Eclipse Public License is available at// http://www.eclipse.org/legal/epl-v10.html//// The Apache License v2.0 is available at// http://www.opensource.org/licenses/apache2.0.php//// You may elect to redistribute this code under either of these licenses.// ========================================================================//package org.eclipse.jetty.annotations;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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.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.statistic.CounterStatistic;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.MetaDataComplete;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebDescriptor;
/**
* Configuration for Annotations
*
*
*/publicclassAnnotationConfigurationextendsAbstractConfiguration{
privatestaticfinal Logger LOG = Log.getLogger(AnnotationConfiguration.class);
publicstaticfinal String SERVLET_CONTAINER_INITIALIZER_ORDER = "org.eclipse.jetty.containerInitializerOrder";
publicstaticfinal String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
publicstaticfinal String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
publicstaticfinal String CONTAINER_INITIALIZER_STARTER = "org.eclipse.jetty.containerInitializerStarter";
publicstaticfinal String MULTI_THREADED = "org.eclipse.jetty.annotations.multiThreaded";
publicstaticfinal String MAX_SCAN_WAIT = "org.eclipse.jetty.annotations.maxWait";
publicstaticfinalint DEFAULT_MAX_SCAN_WAIT = 60; /* time in sec */publicstaticfinalboolean DEFAULT_MULTI_THREADED = true;
protected List _discoverableAnnotationHandlers = new ArrayList();
protected ClassInheritanceHandler _classInheritanceHandler;
protected List _containerInitializerAnnotationHandlers = new ArrayList();
protected List _parserTasks;
protected WebAppClassNameResolver _webAppClassNameResolver;
protected ContainerClassNameResolver _containerClassNameResolver;
protected CounterStatistic _containerPathStats;
protected CounterStatistic _webInfLibStats;
protected CounterStatistic _webInfClassesStats;
/**
* TimeStatistic
*
* Simple class to capture elapsed time of an operation.
*
*/publicclassTimeStatistic{
publiclong _start = 0;
publiclong _end = 0;
publicvoidstart(){
_start = System.nanoTime();
}
publicvoidend(){
_end = System.nanoTime();
}
publiclonggetStart(){
return _start;
}
publiclonggetEnd(){
return _end;
}
publiclonggetElapsed(){
return (_end > _start?(_end-_start):0);
}
}
/**
* ParserTask
*
* Task to executing scanning of a resource for annotations.
*
*/publicclassParserTaskimplementsCallable{
protected Exception _exception;
protectedfinal AnnotationParser _parser;
protectedfinal Set _handlers;
protectedfinal ClassNameResolver _resolver;
protectedfinal Resource _resource;
protected TimeStatistic _stat;
publicParserTask(AnnotationParser parser, Sethandlers, Resource resource, ClassNameResolver resolver){
_parser = parser;
_handlers = handlers;
_resolver = resolver;
_resource = resource;
}
publicvoidsetStatistic(TimeStatistic stat){
_stat = stat;
}
public Void call()throws Exception
{
if (_stat != null)
_stat.start();
if (_parser != null)
_parser.parse(_handlers, _resource, _resolver);
if (_stat != null)
_stat.end();
returnnull;
}
public TimeStatistic getStatistic(){
return _stat;
}
public Resource getResource(){
return _resource;
}
}
/**
* WebAppClassNameResolver
*
* Checks to see if a classname belongs to hidden or visible packages when scanning,
* and whether a classname that is a duplicate should override a previously
* scanned classname.
*
* This is analogous to the management of classes that the WebAppClassLoader is doing,
* however we don't want to load the classes at this point so we are doing it on
* the name only.
*
*/publicclassWebAppClassNameResolverimplementsClassNameResolver{
private WebAppContext _context;
publicWebAppClassNameResolver(WebAppContext context){
_context = context;
}
publicbooleanisExcluded(String name){
if (_context.isSystemClass(name)) returntrue;
if (_context.isServerClass(name)) returnfalse;
returnfalse;
}
publicbooleanshouldOverride(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())
returnfalse;
returntrue;
}
}
/**
* ContainerClassNameResolver
*
* Checks to see if a classname belongs to a hidden or visible package
* when scanning for annotations and thus whether it should be excluded from
* consideration or not.
*
* This is analogous to the management of classes that the WebAppClassLoader is doing,
* however we don't want to load the classes at this point so we are doing it on
* the name only.
*
*/publicclassContainerClassNameResolverimplementsClassNameResolver{
private WebAppContext _context;
publicContainerClassNameResolver(WebAppContext context){
_context = context;
}
publicbooleanisExcluded(String name){
if (_context.isSystemClass(name)) returnfalse;
if (_context.isServerClass(name)) returntrue;
returnfalse;
}
publicbooleanshouldOverride(String name){
//visiting the container classpath, if (_context.isParentLoaderPriority())
returntrue;
returnfalse;
}
}
/**
* ServletContainerInitializerOrdering
*
* A list of classnames of ServletContainerInitializers in the order in which
* they are to be called back. One name only in the list can be "*", which is a
* wildcard which matches any other ServletContainerInitializer name not already
* matched.
*/publicclassServletContainerInitializerOrdering{
private Map _indexMap = new HashMap();
private Integer _star = null;
private String _ordering = null;
publicServletContainerInitializerOrdering(String ordering){
if (ordering != null)
{
_ordering = ordering;
String[] tmp = ordering.split(",");
for (int i=0; i
{
private ServletContainerInitializerOrdering _ordering;
publicServletContainerInitializerComparator(ServletContainerInitializerOrdering ordering){
_ordering = ordering;
}
@Overridepublicintcompare(ServletContainerInitializer sci1, ServletContainerInitializer sci2){
String c1 = (sci1 != null? sci1.getClass().getName() : null);
String c2 = (sci2 != null? sci2.getClass().getName() : null);
if (c1 == null && c2 == null)
return0;
int i1 = _ordering.getIndexOf(c1);
if (i1 < 0 && _ordering.hasWildcard())
i1 = _ordering.getWildcardIndex();
int i2 = _ordering.getIndexOf(c2);
if (i2 < 0 && _ordering.hasWildcard())
i2 = _ordering.getWildcardIndex();
return Integer.compare(i1, i2);
}
}
@OverridepublicvoidpreConfigure(final WebAppContext context)throws Exception
{
_webAppClassNameResolver = new WebAppClassNameResolver(context);
_containerClassNameResolver = new ContainerClassNameResolver(context);
}
publicvoidaddDiscoverableAnnotationHandler(AbstractDiscoverableAnnotationHandler handler){
_discoverableAnnotationHandlers.add(handler);
}
@Overridepublicvoiddeconfigure(WebAppContext context)throws Exception
{
context.removeAttribute(CLASS_INHERITANCE_MAP);
context.removeAttribute(CONTAINER_INITIALIZERS);
ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
if (starter != null)
{
context.removeBean(starter);
context.removeAttribute(CONTAINER_INITIALIZER_STARTER);
}
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/@Overridepublicvoidconfigure(WebAppContext context)throws Exception
{
context.addDecorator(new AnnotationDecorator(context));
//Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are anyif (!context.getMetaData().isMetaDataComplete())
{
//If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotationsif (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
{
_discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
_discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
_discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
}
}
//Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, then we need to scan all the//classes so we can call their onStartup() methods correctly
createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
scanForAnnotations(context);
// Resolve container initializers
List initializers =
(List)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
if (initializers != null && initializers.size()>0)
{
Map> map = ( Map>) context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
if (map == null)
LOG.warn ("ServletContainerInitializers: detected. Class hierarchy: empty");
for (ContainerInitializer i : initializers)
i.resolveClasses(context,map);
}
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/@OverridepublicvoidpostConfigure(WebAppContext context)throws Exception
{
ConcurrentHashMap> classMap = (ClassInheritanceMap)context.getAttribute(CLASS_INHERITANCE_MAP);
List initializers = (List)context.getAttribute(CONTAINER_INITIALIZERS);
context.removeAttribute(CLASS_INHERITANCE_MAP);
if (classMap != null)
classMap.clear();
context.removeAttribute(CONTAINER_INITIALIZERS);
if (initializers != null)
initializers.clear();
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
*/protectedvoidscanForAnnotations(WebAppContext context)throws Exception
{
AnnotationParser parser = createAnnotationParser();
_parserTasks = new ArrayList();
long start = 0;
if (LOG.isDebugEnabled())
LOG.debug("Annotation scanning commencing: webxml={}, metadatacomplete={}, configurationDiscovered={}, multiThreaded={}, maxScanWait={}",
context.getServletContext().getEffectiveMajorVersion(),
context.getMetaData().isMetaDataComplete(),
context.isConfigurationDiscovered(),
isUseMultiThreading(context),
getMaxScanWait(context));
parseContainerPath(context, parser);
//email from Rajiv Mordani jsrs 315 7 April 2010// If there is a 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);
start = System.nanoTime();
//execute scan, either effectively synchronously (1 thread only), or asynchronously (limited by number of processors available) final Semaphore task_limit = (isUseMultiThreading(context)? new Semaphore(Runtime.getRuntime().availableProcessors()):new Semaphore(1));
final CountDownLatch latch = new CountDownLatch(_parserTasks.size());
final MultiException me = new MultiException();
for (final ParserTask p:_parserTasks)
{
task_limit.acquire();
context.getServer().getThreadPool().execute(new Runnable()
{
@Overridepublicvoidrun(){
try
{
p.call();
}
catch (Exception e)
{
me.add(e);
}
finally
{
task_limit.release();
latch.countDown();
}
}
});
}
boolean timeout = !latch.await(getMaxScanWait(context), TimeUnit.SECONDS);
if (LOG.isDebugEnabled())
{
for (ParserTask p:_parserTasks)
LOG.debug("Scanned {} in {}ms", p.getResource(), TimeUnit.MILLISECONDS.convert(p.getStatistic().getElapsed(), TimeUnit.NANOSECONDS));
}
LOG.debug("Scanned {} container path jars, {} WEB-INF/lib jars, {} WEB-INF/classes dirs in {}ms for context {}",
_containerPathStats.getTotal(), _webInfLibStats.getTotal(), _webInfClassesStats.getTotal(),
(TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)),
context);
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.
*/protected AnnotationParser createAnnotationParser(){
returnnew AnnotationParser();
}
/**
* Check if we should use multiple threads to scan for annotations or not
* @param context
* @return
*/protectedbooleanisUseMultiThreading(WebAppContext context){
//try context attribute to see if we should use multithreading
Object o = context.getAttribute(MULTI_THREADED);
if (o instanceof Boolean)
{
return ((Boolean)o).booleanValue();
}
//try server attribute to see if we should use multithreading
o = context.getServer().getAttribute(MULTI_THREADED);
if (o instanceof Boolean)
{
return ((Boolean)o).booleanValue();
}
//try system property to see if we should use multithreadingreturn Boolean.valueOf(System.getProperty(MULTI_THREADED, Boolean.toString(DEFAULT_MULTI_THREADED)));
}
/**
* Work out how long we should wait for the async scanning to occur.
*
* @param context
* @return
*/protectedintgetMaxScanWait(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 completionreturn 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)
*/@OverridepublicvoidcloneConfigure(WebAppContext template, WebAppContext context)throws Exception
{
context.addDecorator(new AnnotationDecorator(context));
}
/**
* @param context
* @param scis
* @throws Exception
*/publicvoidcreateServletContainerInitializerAnnotationHandlers(WebAppContext context, List scis)throws Exception
{
if (scis == null || scis.isEmpty())
return; // nothing to do
List initializers = new ArrayList();
context.setAttribute(CONTAINER_INITIALIZERS, initializers);
for (ServletContainerInitializer service : scis)
{
HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
ContainerInitializer initializer = null;
if (annotation != null)
{
//There is a HandlesTypes annotation on the on the ServletContainerInitializer
Class[] classes = annotation.value();
if (classes != null)
{
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 ServletContainerInitializerif (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
{
//MultiMap map = new MultiMap<>();
ConcurrentHashMap> map = new ClassInheritanceMap();
context.setAttribute(CLASS_INHERITANCE_MAP, map);
_classInheritanceHandler = new ClassInheritanceHandler(map);
}
for (Class c: classes)
{
//The value of one of the HandlesTypes classes is actually an Annotation itself so//register a handler for itif (c.isAnnotation())
{
if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
_containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
}
}
}
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)
thrownew IllegalStateException("ServletContainerInitializersStarter already exists");
starter = new ServletContainerInitializersStarter(context);
context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter);
context.addBean(starter, true);
}
public Resource getJarFor(ServletContainerInitializer service)throws MalformedURLException, IOException
{
String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString();
int i = loadingJarName.indexOf(".jar");
if (i < 0)
returnnull; //not from a jar
loadingJarName = loadingJarName.substring(0,i+4);
loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
return Resource.newResource(loadingJarName);
}
/**
* Check to see if the ServletContainerIntializer loaded via the ServiceLoader came
* from a jar that is excluded by the fragment ordering. See ServletSpec 3.0 p.85.
* @param context
* @param sci
* @return true if excluded
*/publicbooleanisFromExcludedJar(WebAppContext context, ServletContainerInitializer sci, Resource sciResource)throws Exception
{
if (sci == null)
thrownew IllegalArgumentException("ServletContainerInitializer null");
if (context == null)
thrownew IllegalArgumentException("WebAppContext null");
//A ServletContainerInitializer that came from the container's classpath cannot be excluded by an ordering//of WEB-INF/lib jarsif (sci.getClass().getClassLoader()==context.getClassLoader().getParent())
returnfalse;
List orderedJars = context.getMetaData().getOrderedWebInfJars();
//If no ordering, nothing is excludedif (context.getMetaData().getOrdering() == null)
returnfalse;
//there is an ordering, but there are no jars resulting from the ordering, everything excludedif (orderedJars.isEmpty())
returntrue;
if (sciResource == null)
returnfalse; //not from a jar therefore not from WEB-INF so not excludable
URI loadingJarURI = sciResource.getURI();
boolean found = false;
Iterator itor = orderedJars.iterator();
while (!found && itor.hasNext())
{
Resource r = itor.next();
found = r.getURI().equals(loadingJarURI);
}
return !found;
}
/**
* @param context
* @return list of non-excluded {@link ServletContainerInitializer}s
* @throws Exception
*/public ListgetNonExcludedInitializers(WebAppContext context)throws Exception
{
ArrayList nonExcludedInitializers = new ArrayList();
//We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspectlong start = 0;
ClassLoader old = Thread.currentThread().getContextClassLoader();
ServiceLoader loadedInitializers = null;
try
{
if (LOG.isDebugEnabled())
start = System.nanoTime();
Thread.currentThread().setContextClassLoader(context.getClassLoader());
loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
if (LOG.isDebugEnabled())
LOG.debug("Service loaders found in {}ms", (TimeUnit.MILLISECONDS.convert((System.nanoTime()-start), TimeUnit.NANOSECONDS)));
ServletContainerInitializerOrdering initializerOrdering = getInitializerOrdering(context);
if (initializerOrdering != null && !initializerOrdering.isDefaultOrder())
{
if (LOG.isDebugEnabled())
LOG.debug("Ordering ServletContainerInitializers with "+initializerOrdering);
//There is an ordering that is not just "*".//Arrange ServletContainerInitializers according to the ordering of classnames given, irrespective of coming from container or webapp classpathsfor (ServletContainerInitializer sci:loadedInitializers)
{
Resource sciResource = getJarFor(sci);
if (!isFromExcludedJar(context, sci, sciResource))
{
String name = sci.getClass().getName();
if (initializerOrdering.getIndexOf(name) >= 0 || initializerOrdering.hasWildcard())
nonExcludedInitializers.add(sci);
}
}
//apply the ordering
Collections.sort(nonExcludedInitializers, new ServletContainerInitializerComparator(initializerOrdering));
}
else
{
//No ordering specified, or just the wildcard value "*" specified.//Fallback to ordering the ServletContainerInitializers according to://container classpath first, WEB-INF/clases then WEB-INF/lib (obeying any web.xml jar ordering)if (LOG.isDebugEnabled())
LOG.debug("Ordering ServletContainerInitializers as container path, webapp path");
Map webappPathInitializerResourceMap = new HashMap();
for (ServletContainerInitializer sci : loadedInitializers)
{
//if its on the container's classpath then add itif (sci.getClass().getClassLoader() == context.getClassLoader().getParent())
{
nonExcludedInitializers.add(sci);
}
else
{
//if on the webapp's classpath then check the containing jar is not excluded from consideration
Resource sciResource = getJarFor(sci);
if (!isFromExcludedJar(context, sci, sciResource))
{
webappPathInitializerResourceMap.put(sci, sciResource);
}
}
}
//add the webapp classpath ones according to any web.xml orderingif (context.getMetaData().getOrdering() == null)
nonExcludedInitializers.addAll(webappPathInitializerResourceMap.keySet()); //no ordering, just add themelse
{
//add in any ServletContainerInitializers which are not in a jar, as they must be from WEB-INF/classesfor (Map.Entry entry:webappPathInitializerResourceMap.entrySet())
{
if (entry.getValue() == null)
nonExcludedInitializers.add(entry.getKey());
}
//add ServletContainerInitializers according to the ordering of its containing jarfor (Resource webInfJar:context.getMetaData().getOrderedWebInfJars())
{
for (Map.Entry entry:webappPathInitializerResourceMap.entrySet())
{
if (webInfJar.equals(entry.getValue()))
nonExcludedInitializers.add(entry.getKey());
}
}
}
}
return nonExcludedInitializers;
}
/**
* Jetty-specific extension that allows an ordering to be applied across ALL ServletContainerInitializers.
*
* @return
*/public ServletContainerInitializerOrdering getInitializerOrdering(WebAppContext context){
if (context == null)
returnnull;
String tmp = (String)context.getAttribute(SERVLET_CONTAINER_INITIALIZER_ORDER);
if (tmp == null || "".equals(tmp.trim()))
returnnull;
returnnew ServletContainerInitializerOrdering(tmp);
}
/**
* Scan jars on container path.
*
* @param context
* @param parser
* @throws Exception
*/publicvoidparseContainerPath(final WebAppContext context, final AnnotationParser parser)throws Exception
{
//always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotationsfinal Set handlers = new HashSet();
handlers.addAll(_discoverableAnnotationHandlers);
handlers.addAll(_containerInitializerAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
_containerPathStats = new CounterStatistic();
for (Resource r : context.getMetaData().getContainerResources())
{
//queue it up for scanning if using multithreaded modeif (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers, r, _containerClassNameResolver);
_parserTasks.add(task);
_containerPathStats.increment();
if (LOG.isDebugEnabled())
task.setStatistic(new TimeStatistic());
}
}
}
/**
* Scan jars in WEB-INF/lib
*
* @param context
* @param parser
* @throws Exception
*/publicvoidparseWebInfLib(final WebAppContext context, final AnnotationParser parser)throws Exception
{
List frags = context.getMetaData().getFragments();
//email from Rajiv Mordani jsrs 315 7 April 2010//jars that do not have a web-fragment.xml are still considered fragments//they have to participate in the ordering
ArrayList webInfUris = new ArrayList();
List jars = context.getMetaData().getOrderedWebInfJars();
//No ordering just use the jars in any orderif (jars == null || jars.isEmpty())
jars = context.getMetaData().getWebInfJars();
_webInfLibStats = new CounterStatistic();
for (Resource r : jars)
{
//for each jar, we decide which set of annotations we need to parse forfinal Set handlers = new HashSet();
FragmentDescriptor f = getFragmentFromJar(r, frags);
//if its from a fragment jar that is metadata complete, we should skip scanning for @webservlet etc// but yet we still need to do the scanning for the classes on behalf of the servletcontainerinitializers//if a jar has no web-fragment.xml we scan it (because it is not excluded by the ordering)//or if it has a fragment we scan it if it is not metadata completeif (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
{
//register the classinheritance handler if there is oneif (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
//register the handlers for the @HandlesTypes values that are themselves annotations if there are any
handlers.addAll(_containerInitializerAnnotationHandlers);
//only register the discoverable annotation handlers if this fragment is not metadata complete, or has no fragment descriptorif (f == null || !isMetaDataComplete(f))
handlers.addAll(_discoverableAnnotationHandlers);
if (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers,r, _webAppClassNameResolver);
_parserTasks.add (task);
_webInfLibStats.increment();
if (LOG.isDebugEnabled())
task.setStatistic(new TimeStatistic());
}
}
}
}
/**
* Scan classes in WEB-INF/classes
*
* @param context
* @param parser
* @throws Exception
*/publicvoidparseWebInfClasses(final WebAppContext context, final AnnotationParser parser)throws Exception
{
Set handlers = new HashSet();
handlers.addAll(_discoverableAnnotationHandlers);
if (_classInheritanceHandler != null)
handlers.add(_classInheritanceHandler);
handlers.addAll(_containerInitializerAnnotationHandlers);
_webInfClassesStats = new CounterStatistic();
for (Resource dir : context.getMetaData().getWebInfClassesDirs())
{
if (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers, dir, _webAppClassNameResolver);
_parserTasks.add(task);
_webInfClassesStats.increment();
if (LOG.isDebugEnabled())
task.setStatistic(new TimeStatistic());
}
}
}
/**
* Get the web-fragment.xml from a jar
*
* @param jar
* @param frags
* @return the fragment if found, or null of not found
* @throws Exception
*/public FragmentDescriptor getFragmentFromJar(Resource jar, List frags)throws Exception
{
//check if the jar has a web-fragment.xml
FragmentDescriptor d = null;
for (FragmentDescriptor frag: frags)
{
Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xmlif (Resource.isContainedIn(fragResource,jar))
{
d = frag;
break;
}
}
return d;
}
publicbooleanisMetaDataComplete(WebDescriptor d){
return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
}
publicstaticclassClassInheritanceMapextendsConcurrentHashMap>
{
@Overridepublic String toString(){
return String.format("ClassInheritanceMap@%x{size=%d}",hashCode(),size());
}
}
}