Skip to content

Commit

Permalink
Issue #963 Location based classpath pattern (#978)
Browse files Browse the repository at this point in the history
Issue #963 location based white/black classpath lists
- removed outdated annotations/ClassNameResolver
- implemented loadedFrom in TypeUtil
- created a growable Trie
- reimplemented classpathpattern
- simplified OSGi classloading
  • Loading branch information
gregw committed Oct 5, 2016
1 parent 85f50da commit afb7505
Show file tree
Hide file tree
Showing 35 changed files with 1,656 additions and 976 deletions.
Expand Up @@ -21,7 +21,6 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -48,6 +47,7 @@
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
Expand Down Expand Up @@ -81,8 +81,6 @@ public class AnnotationConfiguration extends AbstractConfiguration
protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();

protected List<ParserTask> _parserTasks;
protected WebAppClassNameResolver _webAppClassNameResolver;
protected ContainerClassNameResolver _containerClassNameResolver;

protected CounterStatistic _containerPathStats;
protected CounterStatistic _webInfLibStats;
Expand Down Expand Up @@ -138,15 +136,13 @@ 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;
protected TimeStatistic _stat;

public ParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
public ParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource)
{
_parser = parser;
_handlers = handlers;
_resolver = resolver;
_resource = resource;
}

Expand All @@ -160,7 +156,7 @@ public Void call() throws Exception
if (_stat != null)
_stat.start();
if (_parser != null)
_parser.parse(_handlers, _resource, _resolver);
_parser.parse(_handlers, _resource);
if (_stat != null)
_stat.end();
return null;
Expand All @@ -174,83 +170,7 @@ public TimeStatistic getStatistic()
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.
*
*/
public class WebAppClassNameResolver implements ClassNameResolver
{
private WebAppContext _context;

public WebAppClassNameResolver (WebAppContext context)
{
_context = context;
}

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;
}
}


/**
* 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.
*
*/
public class ContainerClassNameResolver implements ClassNameResolver
{
private WebAppContext _context;

public ContainerClassNameResolver (WebAppContext context)
{
_context = context;
}
public boolean isExcluded (String name)
{
if (_context.isSystemClass(name)) return false;
if (_context.isServerClass(name)) return true;
return false;
}

public boolean shouldOverride (String name)
{
//visiting the container classpath,
if (_context.isParentLoaderPriority())
return true;
return false;
}
}
}


Expand Down Expand Up @@ -390,8 +310,6 @@ public int compare(ServletContainerInitializer sci1, ServletContainerInitializer
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
_webAppClassNameResolver = new WebAppClassNameResolver(context);
_containerClassNameResolver = new ContainerClassNameResolver(context);
String tmp = (String)context.getAttribute(SERVLET_CONTAINER_INITIALIZER_EXCLUSION_PATTERN);
_sciExcludePattern = (tmp==null?null:Pattern.compile(tmp));
}
Expand Down Expand Up @@ -445,15 +363,15 @@ public void configure(WebAppContext context) throws Exception

if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
scanForAnnotations(context);

// Resolve container initializers
List<ContainerInitializer> initializers =
(List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
(List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
if (initializers != null && initializers.size()>0)
{
Map<String, Set<String>> map = ( Map<String, Set<String>>) context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
for (ContainerInitializer i : initializers)
i.resolveClasses(context,map);
i.resolveClasses(context,map);
}
}

Expand Down Expand Up @@ -723,23 +641,7 @@ public void createServletContainerInitializerAnnotationHandlers (WebAppContext c
public Resource getJarFor (ServletContainerInitializer service)
throws MalformedURLException, IOException
{
//try the thread context classloader to get the jar that loaded the class
URL jarURL = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class");

//if for some reason that failed (eg we're in osgi and the TCCL does not know about the service) try the classloader that
//loaded the class
if (jarURL == null)
jarURL = service.getClass().getClassLoader().getResource(service.getClass().getName().replace('.','/')+".class");

String loadingJarName = jarURL.toString();

int i = loadingJarName.indexOf(".jar");
if (i < 0)
return null; //not from a jar

loadingJarName = loadingJarName.substring(0,i+4);
loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
return Resource.newResource(loadingJarName);
return TypeUtil.getLoadedFrom(service.getClass());
}

/**
Expand All @@ -760,26 +662,41 @@ public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitial
if (context == null)
throw new IllegalArgumentException("WebAppContext null");

if (LOG.isDebugEnabled()) LOG.debug("Checking {} for jar exclusion", sci);


//A ServletContainerInitializer that came from the container's classpath cannot be excluded by an ordering
//of WEB-INF/lib jars
if (isFromContainerClassPath(context, sci))
{
if (LOG.isDebugEnabled())
LOG.debug("!Excluded {} from container classpath", sci);
return false;
}

//If no ordering, nothing is excluded
if (context.getMetaData().getOrdering() == null)
{
if (LOG.isDebugEnabled())
LOG.debug("!Excluded {} no ordering", sci);
return false;

}

List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();

//there is an ordering, but there are no jars resulting from the ordering, everything excluded
if (orderedJars.isEmpty())
{
if (LOG.isDebugEnabled())
LOG.debug("Excluded {} empty ordering", sci);
return true;
}

if (sciResource == null)
return false; //not from a jar therefore not from WEB-INF so not excludable
{
//not from a jar therefore not from WEB-INF so not excludable
if (LOG.isDebugEnabled())
LOG.debug("!Excluded {} not from jar", sci);
return false;
}

URI loadingJarURI = sciResource.getURI();
boolean found = false;
Expand All @@ -790,10 +707,11 @@ public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitial
found = r.getURI().equals(loadingJarURI);
}

if (LOG.isDebugEnabled())
LOG.debug("{}Excluded {} found={}",found?"!":"",sci,found);
return !found;
}


/**
* Test if the ServletContainerIntializer is excluded by the
* o.e.j.containerInitializerExclusionPattern
Expand All @@ -808,7 +726,8 @@ public boolean matchesExclusionPattern(ServletContainerInitializer sci)
return false;

//test if name of class matches the regex
if (LOG.isDebugEnabled()) LOG.debug("Checking {} against containerInitializerExclusionPattern",sci.getClass().getName());
if (LOG.isDebugEnabled())
LOG.debug("Checking {} against containerInitializerExclusionPattern",sci.getClass().getName());
return _sciExcludePattern.matcher(sci.getClass().getName()).matches();
}

Expand Down Expand Up @@ -866,17 +785,20 @@ public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppConte
//because containerInitializerOrdering omits it
for (ServletContainerInitializer sci:_loadedInitializers)
{
LOG.setDebugEnabled(true);

if (matchesExclusionPattern(sci))
{
if (LOG.isDebugEnabled()) LOG.debug("{} excluded by pattern", sci);
if (LOG.isDebugEnabled())
LOG.debug("{} excluded by pattern", sci);
continue;
}

Resource sciResource = getJarFor(sci);
if (isFromExcludedJar(context, sci, sciResource))
{
if (LOG.isDebugEnabled()) LOG.debug("{} is from excluded jar", sci);
if (LOG.isDebugEnabled())
LOG.debug("{} is from excluded jar", sci);
continue;
}

Expand All @@ -885,7 +807,8 @@ public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppConte
if (initializerOrdering != null
&& (!initializerOrdering.hasWildcard() && initializerOrdering.getIndexOf(name) < 0))
{
if (LOG.isDebugEnabled()) LOG.debug("{} is excluded by ordering", sci);
if (LOG.isDebugEnabled())
LOG.debug("{} is excluded by ordering", sci);
continue;
}

Expand All @@ -912,12 +835,14 @@ public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppConte
//no web.xml ordering defined, add SCIs in any order
if (context.getMetaData().getOrdering() == null)
{
if (LOG.isDebugEnabled()) LOG.debug("No web.xml ordering, ServletContainerInitializers in random order");
if (LOG.isDebugEnabled())
LOG.debug("No web.xml ordering, ServletContainerInitializers in random order");
nonExcludedInitializers.addAll(sciResourceMap.keySet());
}
else
{
if (LOG.isDebugEnabled()) LOG.debug("Ordering ServletContainerInitializers with ordering {}",context.getMetaData().getOrdering());
if (LOG.isDebugEnabled())
LOG.debug("Ordering ServletContainerInitializers with ordering {}",context.getMetaData().getOrdering());
for (Map.Entry<ServletContainerInitializer, Resource> entry:sciResourceMap.entrySet())
{
//add in SCIs from the container classpath
Expand Down Expand Up @@ -992,7 +917,7 @@ public void parseContainerPath (final WebAppContext context, final AnnotationPar
//queue it up for scanning if using multithreaded mode
if (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers, r, _containerClassNameResolver);
ParserTask task = new ParserTask(parser, handlers, r);
_parserTasks.add(task);
_containerPathStats.increment();
if (LOG.isDebugEnabled())
Expand Down Expand Up @@ -1054,7 +979,7 @@ public void parseWebInfLib (final WebAppContext context, final AnnotationParser

if (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers,r, _webAppClassNameResolver);
ParserTask task = new ParserTask(parser, handlers,r);
_parserTasks.add (task);
_webInfLibStats.increment();
if (LOG.isDebugEnabled())
Expand Down Expand Up @@ -1087,7 +1012,7 @@ public void parseWebInfClasses (final WebAppContext context, final AnnotationPar
{
if (_parserTasks != null)
{
ParserTask task = new ParserTask(parser, handlers, dir, _webAppClassNameResolver);
ParserTask task = new ParserTask(parser, handlers, dir);
_parserTasks.add(task);
_webInfClassesStats.increment();
if (LOG.isDebugEnabled())
Expand Down

0 comments on commit afb7505

Please sign in to comment.