Merge remote-tracking branch 'origin/jetty-9.4.x'
This commit is contained in:
commit
84f7fc31cb
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.annotations;
|
|||
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;
|
||||
|
@ -49,6 +48,7 @@ import org.eclipse.jetty.plus.webapp.PlusConfiguration;
|
|||
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;
|
||||
|
@ -86,8 +86,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;
|
||||
|
@ -152,15 +150,13 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -174,7 +170,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
if (_stat != null)
|
||||
_stat.start();
|
||||
if (_parser != null)
|
||||
_parser.parse(_handlers, _resource, _resolver);
|
||||
_parser.parse(_handlers, _resource);
|
||||
if (_stat != null)
|
||||
_stat.end();
|
||||
return null;
|
||||
|
@ -188,83 +184,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -404,8 +324,6 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
@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));
|
||||
}
|
||||
|
@ -459,15 +377,15 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,23 +655,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -774,26 +676,41 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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;
|
||||
|
@ -804,10 +721,11 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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
|
||||
|
@ -822,7 +740,8 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -883,14 +802,16 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -899,7 +820,8 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -926,12 +848,14 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
//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
|
||||
|
@ -1006,7 +930,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
//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())
|
||||
|
@ -1068,7 +992,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
|
||||
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())
|
||||
|
@ -1101,7 +1025,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
{
|
||||
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())
|
||||
|
|
|
@ -547,25 +547,22 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver to use
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (Set<? extends Handler> handlers, String className, ClassNameResolver resolver)
|
||||
public void parse (Set<? extends Handler> handlers, String className)
|
||||
throws Exception
|
||||
{
|
||||
if (className == null)
|
||||
return;
|
||||
|
||||
if (!resolver.isExcluded(className))
|
||||
if (!isParsed(className))
|
||||
{
|
||||
if (!isParsed(className) || resolver.shouldOverride(className))
|
||||
className = className.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(className);
|
||||
if (resource!= null)
|
||||
{
|
||||
className = className.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(className);
|
||||
if (resource!= null)
|
||||
Resource r = Resource.newResource(resource);
|
||||
try (InputStream is = r.getInputStream())
|
||||
{
|
||||
Resource r = Resource.newResource(resource);
|
||||
try (InputStream is = r.getInputStream())
|
||||
{
|
||||
scanClass(handlers, null, is);
|
||||
}
|
||||
scanClass(handlers, null, is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -582,29 +579,27 @@ public class AnnotationParser
|
|||
* @param visitSuperClasses if true, also visit super classes for parse
|
||||
* @throws Exception if unable to parse class
|
||||
*/
|
||||
public void parse (Set<? extends Handler> handlers, Class<?> clazz, ClassNameResolver resolver, boolean visitSuperClasses)
|
||||
public void parse (Set<? extends Handler> handlers, Class<?> clazz, boolean visitSuperClasses)
|
||||
throws Exception
|
||||
{
|
||||
Class<?> cz = clazz;
|
||||
while (cz != null)
|
||||
{
|
||||
if (!resolver.isExcluded(cz.getName()))
|
||||
if (!isParsed(cz.getName()))
|
||||
{
|
||||
if (!isParsed(cz.getName()) || resolver.shouldOverride(cz.getName()))
|
||||
String nameAsResource = cz.getName().replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(nameAsResource);
|
||||
if (resource!= null)
|
||||
{
|
||||
String nameAsResource = cz.getName().replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(nameAsResource);
|
||||
if (resource!= null)
|
||||
Resource r = Resource.newResource(resource);
|
||||
try (InputStream is = r.getInputStream())
|
||||
{
|
||||
Resource r = Resource.newResource(resource);
|
||||
try (InputStream is = r.getInputStream())
|
||||
{
|
||||
scanClass(handlers, null, is);
|
||||
}
|
||||
scanClass(handlers, null, is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (visitSuperClasses)
|
||||
cz = cz.getSuperclass();
|
||||
else
|
||||
|
@ -622,13 +617,13 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (Set<? extends Handler> handlers, String[] classNames, ClassNameResolver resolver)
|
||||
public void parse (Set<? extends Handler> handlers, String[] classNames)
|
||||
throws Exception
|
||||
{
|
||||
if (classNames == null)
|
||||
return;
|
||||
|
||||
parse(handlers, Arrays.asList(classNames), resolver);
|
||||
parse(handlers, Arrays.asList(classNames));
|
||||
}
|
||||
|
||||
|
||||
|
@ -640,7 +635,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (Set<? extends Handler> handlers, List<String> classNames, ClassNameResolver resolver)
|
||||
public void parse (Set<? extends Handler> handlers, List<String> classNames)
|
||||
throws Exception
|
||||
{
|
||||
MultiException me = new MultiException();
|
||||
|
@ -649,7 +644,7 @@ public class AnnotationParser
|
|||
{
|
||||
try
|
||||
{
|
||||
if ((resolver == null) || (!resolver.isExcluded(s) && (!isParsed(s) || resolver.shouldOverride(s))))
|
||||
if (!isParsed(s))
|
||||
{
|
||||
s = s.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(s);
|
||||
|
@ -680,7 +675,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
protected void parseDir (Set<? extends Handler> handlers, Resource dir, ClassNameResolver resolver)
|
||||
protected void parseDir (Set<? extends Handler> handlers, Resource dir)
|
||||
throws Exception
|
||||
{
|
||||
// skip dirs whose name start with . (ie hidden)
|
||||
|
@ -696,7 +691,7 @@ public class AnnotationParser
|
|||
{
|
||||
Resource res = dir.addPath(files[f]);
|
||||
if (res.isDirectory())
|
||||
parseDir(handlers, res, resolver);
|
||||
parseDir(handlers, res);
|
||||
else
|
||||
{
|
||||
//we've already verified the directories, so just verify the class file name
|
||||
|
@ -706,7 +701,7 @@ public class AnnotationParser
|
|||
try
|
||||
{
|
||||
String name = res.getName();
|
||||
if ((resolver == null)|| (!resolver.isExcluded(name) && (!isParsed(name) || resolver.shouldOverride(name))))
|
||||
if (!isParsed(name))
|
||||
{
|
||||
Resource r = Resource.newResource(res.getURL());
|
||||
if (LOG.isDebugEnabled()) {LOG.debug("Scanning class {}", r);};
|
||||
|
@ -744,7 +739,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (final Set<? extends Handler> handlers, ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver)
|
||||
public void parse (final Set<? extends Handler> handlers, ClassLoader loader, boolean visitParents, boolean nullInclusive)
|
||||
throws Exception
|
||||
{
|
||||
if (loader==null)
|
||||
|
@ -762,7 +757,7 @@ public class AnnotationParser
|
|||
{
|
||||
try
|
||||
{
|
||||
parseJarEntry(handlers, Resource.newResource(jarUri), entry, resolver);
|
||||
parseJarEntry(handlers, Resource.newResource(jarUri), entry);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -785,7 +780,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (final Set<? extends Handler> handlers, final URI[] uris, final ClassNameResolver resolver)
|
||||
public void parse (final Set<? extends Handler> handlers, final URI[] uris)
|
||||
throws Exception
|
||||
{
|
||||
if (uris==null)
|
||||
|
@ -797,7 +792,7 @@ public class AnnotationParser
|
|||
{
|
||||
try
|
||||
{
|
||||
parse(handlers, uri, resolver);
|
||||
parse(handlers, uri);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -815,13 +810,13 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (final Set<? extends Handler> handlers, URI uri, final ClassNameResolver resolver)
|
||||
public void parse (final Set<? extends Handler> handlers, URI uri)
|
||||
throws Exception
|
||||
{
|
||||
if (uri == null)
|
||||
return;
|
||||
|
||||
parse (handlers, Resource.newResource(uri), resolver);
|
||||
parse (handlers, Resource.newResource(uri));
|
||||
}
|
||||
|
||||
|
||||
|
@ -833,7 +828,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
public void parse (final Set<? extends Handler> handlers, Resource r, final ClassNameResolver resolver)
|
||||
public void parse (final Set<? extends Handler> handlers, Resource r)
|
||||
throws Exception
|
||||
{
|
||||
if (r == null)
|
||||
|
@ -841,14 +836,14 @@ public class AnnotationParser
|
|||
|
||||
if (r.exists() && r.isDirectory())
|
||||
{
|
||||
parseDir(handlers, r, resolver);
|
||||
parseDir(handlers, r);
|
||||
return;
|
||||
}
|
||||
|
||||
String fullname = r.toString();
|
||||
if (fullname.endsWith(".jar"))
|
||||
{
|
||||
parseJar(handlers, r, resolver);
|
||||
parseJar(handlers, r);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -875,7 +870,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
protected void parseJar (Set<? extends Handler> handlers, Resource jarResource, final ClassNameResolver resolver)
|
||||
protected void parseJar (Set<? extends Handler> handlers, Resource jarResource)
|
||||
throws Exception
|
||||
{
|
||||
if (jarResource == null)
|
||||
|
@ -899,7 +894,7 @@ public class AnnotationParser
|
|||
{
|
||||
try
|
||||
{
|
||||
parseJarEntry(handlers, jarResource, entry, resolver);
|
||||
parseJarEntry(handlers, jarResource, entry);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -930,7 +925,7 @@ public class AnnotationParser
|
|||
* @param resolver the class name resolver
|
||||
* @throws Exception if unable to parse
|
||||
*/
|
||||
protected void parseJarEntry (Set<? extends Handler> handlers, Resource jar, JarEntry entry, final ClassNameResolver resolver)
|
||||
protected void parseJarEntry (Set<? extends Handler> handlers, Resource jar, JarEntry entry)
|
||||
throws Exception
|
||||
{
|
||||
if (jar == null || entry == null)
|
||||
|
@ -947,9 +942,7 @@ public class AnnotationParser
|
|||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
|
||||
if ((resolver == null)
|
||||
||
|
||||
(!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
|
||||
if (!isParsed(shortName))
|
||||
{
|
||||
Resource clazz = Resource.newResource("jar:"+jar.getURI()+"!/"+name);
|
||||
if (LOG.isDebugEnabled()) {LOG.debug("Scanning class from jar {}", clazz);};
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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;
|
||||
|
||||
|
||||
|
||||
public interface ClassNameResolver
|
||||
{
|
||||
/**
|
||||
* Based on the execution context, should the class represented
|
||||
* by "name" be excluded from consideration?
|
||||
* @param name the name to test
|
||||
* @return true if classname is excluded
|
||||
*/
|
||||
public boolean isExcluded (String name);
|
||||
|
||||
|
||||
/**
|
||||
* Based on the execution context, if a duplicate class
|
||||
* represented by "name" is detected, should the existing
|
||||
* one be overridden or not?
|
||||
* @param name the name to test
|
||||
* @return true if name should be overridden
|
||||
*/
|
||||
public boolean shouldOverride (String name);
|
||||
}
|
|
@ -74,6 +74,12 @@ public class TestAnnotationInheritance
|
|||
return;
|
||||
annotatedMethods.add(info.getClassInfo().getClassName()+"."+info.getMethodName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return annotatedClassNames.toString()+annotatedMethods+annotatedFields;
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -93,18 +99,7 @@ public class TestAnnotationInheritance
|
|||
|
||||
SampleHandler handler = new SampleHandler();
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
parser.parse(Collections.singleton(handler), classNames, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
parser.parse(Collections.singleton(handler), classNames);
|
||||
|
||||
//check we got 2 class annotations
|
||||
assertEquals(2, handler.annotatedClassNames.size());
|
||||
|
@ -129,18 +124,7 @@ public class TestAnnotationInheritance
|
|||
{
|
||||
SampleHandler handler = new SampleHandler();
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
parser.parse(Collections.singleton(handler), ClassB.class, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
parser.parse(Collections.singleton(handler), ClassB.class, true);
|
||||
|
||||
//check we got 2 class annotations
|
||||
assertEquals(2, handler.annotatedClassNames.size());
|
||||
|
@ -160,46 +144,6 @@ public class TestAnnotationInheritance
|
|||
assertEquals("org.eclipse.jetty.annotations.ClassA.m", handler.annotatedFields.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExclusions() throws Exception
|
||||
{
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
SampleHandler handler = new SampleHandler();
|
||||
parser.parse(Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
assertEquals (0, handler.annotatedClassNames.size());
|
||||
assertEquals (0, handler.annotatedFields.size());
|
||||
assertEquals (0, handler.annotatedMethods.size());
|
||||
|
||||
handler.annotatedClassNames.clear();
|
||||
handler.annotatedFields.clear();
|
||||
handler.annotatedMethods.clear();
|
||||
|
||||
parser.parse (Collections.singleton(handler), ClassA.class.getName(), new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
assertEquals (1, handler.annotatedClassNames.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeInheritanceHandling() throws Exception
|
||||
{
|
||||
|
@ -218,7 +162,7 @@ public class TestAnnotationInheritance
|
|||
classNames.add(InterfaceD.class.getName());
|
||||
classNames.add(Foo.class.getName());
|
||||
|
||||
parser.parse(Collections.singleton(handler), classNames, null);
|
||||
parser.parse(Collections.singleton(handler), classNames);
|
||||
|
||||
assertNotNull(map);
|
||||
assertFalse(map.isEmpty());
|
||||
|
|
|
@ -111,19 +111,7 @@ public class TestAnnotationParser
|
|||
}
|
||||
|
||||
//long start = System.currentTimeMillis();
|
||||
parser.parse(Collections.singleton(new SampleAnnotationHandler()), classNames,new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
parser.parse(Collections.singleton(new SampleAnnotationHandler()), classNames);
|
||||
//long end = System.currentTimeMillis();
|
||||
|
||||
//System.err.println("Time to parse class: " + ((end - start)));
|
||||
|
@ -162,7 +150,7 @@ public class TestAnnotationParser
|
|||
}
|
||||
}
|
||||
|
||||
parser.parse(Collections.singleton(new MultiAnnotationHandler()), classNames,null);
|
||||
parser.parse(Collections.singleton(new MultiAnnotationHandler()), classNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -171,7 +159,7 @@ public class TestAnnotationParser
|
|||
File badClassesJar = MavenTestingUtils.getTestResourceFile("bad-classes.jar");
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
Set<Handler> emptySet = Collections.emptySet();
|
||||
parser.parse(emptySet, badClassesJar.toURI(),null);
|
||||
parser.parse(emptySet, badClassesJar.toURI());
|
||||
// only the valid classes inside bad-classes.jar should be parsed. If any invalid classes are parsed and exception would be thrown here
|
||||
}
|
||||
|
||||
|
@ -196,7 +184,7 @@ public class TestAnnotationParser
|
|||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
// Parse
|
||||
parser.parse(Collections.singleton(tracker), basedir.toURI(),null);
|
||||
parser.parse(Collections.singleton(tracker), basedir.toURI());
|
||||
|
||||
// Validate
|
||||
Assert.assertThat("Found Class", tracker.foundClasses, contains(ClassA.class.getName()));
|
||||
|
|
|
@ -73,18 +73,7 @@ public class TestServletAnnotations
|
|||
|
||||
TestWebServletAnnotationHandler handler = new TestWebServletAnnotationHandler(wac, results);
|
||||
|
||||
parser.parse(Collections.singleton(handler), classes, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
parser.parse(Collections.singleton(handler), classes);
|
||||
|
||||
|
||||
assertEquals(1, results.size());
|
||||
|
|
|
@ -44,23 +44,30 @@ public class JettyWeldInitializer
|
|||
{
|
||||
initContext(webapp);
|
||||
|
||||
// TODO use location bases include/exclude
|
||||
|
||||
// webapp cannot change / replace weld classes
|
||||
webapp.addSystemClass("org.jboss.weld.");
|
||||
webapp.addSystemClass("org.jboss.classfilewriter.");
|
||||
webapp.addSystemClass("org.jboss.logging.");
|
||||
webapp.addSystemClass("com.google.common.");
|
||||
webapp.addSystemClass("org.eclipse.jetty.cdi.websocket.annotation.");
|
||||
webapp.getSystemClasspathPattern()
|
||||
.include(
|
||||
"org.jboss.weld.",
|
||||
"org.jboss.classfilewriter.",
|
||||
"org.jboss.logging.",
|
||||
"com.google.common.",
|
||||
"org.eclipse.jetty.cdi.websocket.annotation."
|
||||
);
|
||||
|
||||
|
||||
|
||||
// don't hide weld classes from webapps (allow webapp to use ones from system classloader)
|
||||
webapp.prependServerClass("-org.eclipse.jetty.cdi.websocket.annotation.");
|
||||
webapp.prependServerClass("-org.eclipse.jetty.cdi.core.");
|
||||
webapp.prependServerClass("-org.eclipse.jetty.cdi.servlet.");
|
||||
webapp.addServerClass("-org.jboss.weld.");
|
||||
webapp.addServerClass("-org.jboss.classfilewriter.");
|
||||
webapp.addServerClass("-org.jboss.logging.");
|
||||
webapp.addServerClass("-com.google.common.");
|
||||
|
||||
webapp.getServerClasspathPattern()
|
||||
.exclude(
|
||||
"org.eclipse.jetty.cdi.websocket.annotation.",
|
||||
"org.eclipse.jetty.cdi.core.",
|
||||
"org.eclipse.jetty.cdi.servlet.",
|
||||
"org.jboss.weld.",
|
||||
"org.jboss.classfilewriter.",
|
||||
"org.jboss.logging.",
|
||||
"com.google.common.");
|
||||
}
|
||||
|
||||
public static void initContext(ContextHandler handler) throws NamingException
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
[description]
|
||||
Enables GCloud Datastore API and implementation
|
||||
|
||||
[depends]
|
||||
gcloud
|
||||
jcl-api
|
||||
jcl-impl
|
||||
|
||||
[files]
|
||||
maven://com.google.cloud/google-cloud-datastore/0.3.0|lib/gcloud/google-cloud-datastore-0.3.0.jar
|
||||
maven://com.google.cloud/google-cloud-core/0.3.0|lib/gcloud/google-cloud-core-0.3.0.jar
|
||||
maven://com.google.auth/google-auth-library-credentials/0.3.1|lib/gcloud/google-auth-library-credentials-0.3.1.jar
|
||||
maven://com.google.auth/google-auth-library-oauth2-http/0.3.1|lib/gcloud/google-auth-library-oauth2-http-0.3.1.jar
|
||||
maven://com.google.http-client/google-http-client-jackson2/1.19.0|lib/gcloud/google-http-client-jackson2-1.19.0.jar
|
||||
maven://com.fasterxml.jackson.core/jackson-core/2.1.3|lib/gcloud/jackson-core-2.1.3.jar
|
||||
maven://com.google.http-client/google-http-client/1.21.0|lib/gcloud/google-http-client-1.21.0.jar
|
||||
maven://com.google.code.findbugs/jsr305/1.3.9|lib/gcloud/jsr305-1.3.9.jar
|
||||
maven://org.apache.httpcomponents/httpclient/4.0.1|lib/gcloud/httpclient-4.0.1.jar
|
||||
maven://org.apache.httpcomponents/httpcore/4.0.1|lib/gcloud/httpcore-4.0.1.jar
|
||||
maven://commons-codec/commons-codec/1.3|lib/gcloud/commons-codec-1.3.jar
|
||||
maven://com.google.oauth-client/google-oauth-client/1.21.0|lib/gcloud/google-oauth-client-1.21.0.jar
|
||||
maven://com.google.guava/guava/19.0|lib/gcloud/guava-19.0.jar
|
||||
maven://com.google.api-client/google-api-client-appengine/1.21.0|lib/gcloud/google-api-client-appengine-1.21.0.jar
|
||||
maven://com.google.oauth-client/google-oauth-client-appengine/1.21.0|lib/gcloud/google-oauth-client-appengine-1.21.0.jar
|
||||
maven://com.google.oauth-client/google-oauth-client-servlet/1.21.0|lib/gcloud/google-oauth-client-servlet-1.21.0.jar
|
||||
maven://com.google.http-client/google-http-client-jdo/1.21.0|lib/gcloud/google-http-client-jdo-1.21.0.jar
|
||||
maven://com.google.api-client/google-api-client-servlet/1.21.0|lib/gcloud/google-api-client-servlet-1.21.0.jar
|
||||
maven://javax.jdo/jdo2-api/2.3-eb|lib/gcloud/jdo2-api-2.3-eb.jar
|
||||
maven://javax.transaction/transaction-api/1.1|lib/gcloud/transaction-api-1.1.jar
|
||||
maven://com.google.http-client/google-http-client-appengine/1.21.0|lib/gcloud/google-http-client-appengine-1.21.0.jar
|
||||
maven://com.google.http-client/google-http-client-jackson/1.21.0|lib/gcloud/google-http-client-jackson-1.21.0.jar
|
||||
maven://org.codehaus.jackson/jackson-core-asl/1.9.11|lib/gcloud/jackson-core-asl-1.9.11.jar
|
||||
maven://joda-time/joda-time/2.9.2|lib/gcloud/joda-time-2.9.2.jar
|
||||
maven://com.google.protobuf/protobuf-java/3.0.0-beta-3|lib/gcloud/protobuf-java-3.0.0-beta-3.jar
|
||||
maven://com.google.api/gax/0.0.16|lib/gcloud/gax-0.0.16.jar
|
||||
maven://io.grpc/grpc-all/0.15.0|lib/gcloud/grpc-all-0.15.0.jar
|
||||
maven://io.grpc/grpc-auth/0.15.0|lib/gcloud/grpc-auth-0.15.0.jar
|
||||
maven://io.grpc/grpc-netty/0.15.0|lib/gcloud/grpc-netty-0.15.0.jar
|
||||
maven://io.netty/netty-codec-http2/4.1.1.Final|lib/gcloud/netty-codec-http2-4.1.1.jar
|
||||
maven://io.netty/netty-codec-http/4.1.1.Final|lib/gcloud/netty-codec-http-4.1.1.Final.jar
|
||||
maven://io.netty/netty-codec/4.1.1.Final|lib/gcloud/netty-codec-4.1.1.Final.jar
|
||||
maven://io.netty/netty-handler/4.1.1.Final|lib/gcloud/netty-handler-4.1.1.Final.jar
|
||||
maven://io.netty/netty-buffer/4.1.1.Final|lib/gcloud/netty-buffer-4.1.1.Final.jar
|
||||
maven://io.netty/netty-common/4.1.1.Final|lib/gcloud/netty-common-4.1.1.Final.jar
|
||||
maven://io.netty/netty-transport/4.1.1.Final|lib/gcloud/netty-transport-4.1.1.Final.jar
|
||||
maven://io.netty/netty-resolver/4.1.1.Final|lib/gcloud/netty-resolver-4.1.1.Final.jar
|
||||
maven://io.grpc/grpc-okhttp/0.15.0|lib/gcloud/grpc-okhttp-0.15.0.jar
|
||||
maven://com.squareup.okio/okio/1.6.0|lib/gcloud/okio-1.6.0.jar
|
||||
maven://com.squareup.okhttp/okhttp/2.5.0|lib/gcloud/okhttp-2.5.0.jar
|
||||
maven://io.grpc/grpc-protobuf-nano/0.15.0|lib/gcloud/grpc-protobuf-nano-0.15.0.jar
|
||||
maven://com.google.protobuf.nano/protobuf-javanano/3.0.0-alpha-5|lib/gcloud/protobuf-javanano-3.0.0-alpha-5.jar
|
||||
maven://io.grpc/grpc-stub/0.15.0|lib/gcloud/grpc-stub-0.15.0.jar
|
||||
maven://io.grpc/grpc-protobuf/0.15.0|lib/gcloud/grpc-protobuf-0.15.0.jar
|
||||
maven://com.google.protobuf/protobuf-java-util/3.0.0-beta-3|lib/gcloud/protobuf-java-util-3.0.0-beta-3.jar
|
||||
maven://com.google.code.gson/gson/2.3|lib/gcloud/gson-2.3.jar
|
||||
maven://io.grpc/grpc-protobuf-lite/0.15.0|lib/gcloud/grpc-protobuf-lite-0.15.0.jar
|
||||
maven://io.grpc/grpc-core/0.15.0|lib/gcloud/grpc-core-0.15.0.jar
|
||||
maven://com.google.auto.value/auto-value/1.1|lib/gcloud/auto-value-1.1.jar
|
||||
maven://com.google.inject/guice/4.0|lib/gcloud/guice-4.0.jar
|
||||
maven://javax.inject/javax.inject/1|lib/gcloud/javax.inject-1.jar
|
||||
maven://aopalliance/aopalliance/1.0|lib/gcloud/aopalliance-1.0.jar
|
||||
maven://com.google.api.grpc/grpc-google-common-protos/0.0.7|lib/gcloud/grpc-google-common-protos-0.0.7.jar
|
||||
maven://org.json/json/20151123|lib/gcloud/json-20151123.jar
|
||||
maven://com.google.cloud.datastore/datastore-v1-protos/1.0.1|lib/gcloud/datastore-v1-protos-1.0.1-beta.jar
|
||||
maven://com.google.cloud.datastore/datastore-v1-proto-client/1.1.0|lib/gcloud/datastore-v1-proto-client-1.1.0.jar
|
||||
maven://com.google.http-client/google-http-client-protobuf/1.20.0|lib/gcloud/google-http-client-protobuf-1.20.0.jar
|
||||
maven://com.google.api-client/google-api-client/1.20.0|lib/gcloud/google-api-client-1.20.0.jar
|
||||
maven://com.google.guava/guava-jdk5/13.0|lib/gcloud/guava-jdk5-13.0.jar
|
|
@ -0,0 +1,23 @@
|
|||
[description]
|
||||
Control GCloud API classpath
|
||||
|
||||
[files]
|
||||
basehome:modules/gcloud/gcloud.xml|etc/gcloud.xml
|
||||
|
||||
[lib]
|
||||
lib/gcloud/*.jar
|
||||
|
||||
[xml]
|
||||
etc/gcloud.xml
|
||||
|
||||
[license]
|
||||
GCloudDatastore is an open source project hosted on Github and released under the Apache 2.0 license.
|
||||
https://github.com/GoogleCloudPlatform/gcloud-java
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
[ini-template]
|
||||
## Configure the jars and packages exposed or hidden from webapps by comma separated
|
||||
## list of classnames, package names or file URIs (See ClasspathPattern)
|
||||
## Eg. to hide all gcloud dependencies other than the com.google.guava package:
|
||||
## Default is all jars in lib/gcloud are hidden
|
||||
# gcloud.addServerClasses=file:${jetty.base}/lib/gcloud,-com.google.guava.
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
<!-- Configure a GCloud classpath exposed to webapps -->
|
||||
<!-- ===================================================================== -->
|
||||
<Call class="org.eclipse.jetty.webapp.WebAppContext" name="addServerClasses">
|
||||
<Arg><Ref refid="Server"/></Arg>
|
||||
<Arg>
|
||||
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
|
||||
<Arg><Property name="gcloud.addServerClasses"><Default>file:${jetty.base}/lib/gcloud</Default></Property></Arg>
|
||||
</Call>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
|
@ -5,88 +5,20 @@ Enables GCloudDatastore session management.
|
|||
session-store
|
||||
|
||||
[depends]
|
||||
gcloud-datastore
|
||||
annotations
|
||||
webapp
|
||||
sessions
|
||||
jcl-api
|
||||
jcl-impl
|
||||
|
||||
[files]
|
||||
basehome:etc/sessions/gcloud/index.yaml|etc/index.yaml
|
||||
maven://com.google.cloud/google-cloud-datastore/0.3.0|lib/gcloud/google-cloud-datastore-0.3.0.jar
|
||||
maven://com.google.cloud/google-cloud-core/0.3.0|lib/gcloud/google-cloud-core-0.3.0.jar
|
||||
maven://com.google.auth/google-auth-library-credentials/0.3.1|lib/gcloud/google-auth-library-credentials-0.3.1.jar
|
||||
maven://com.google.auth/google-auth-library-oauth2-http/0.3.1|lib/gcloud/google-auth-library-oauth2-http-0.3.1.jar
|
||||
maven://com.google.http-client/google-http-client-jackson2/1.19.0|lib/gcloud/google-http-client-jackson2-1.19.0.jar
|
||||
maven://com.fasterxml.jackson.core/jackson-core/2.1.3|lib/gcloud/jackson-core-2.1.3.jar
|
||||
maven://com.google.http-client/google-http-client/1.21.0|lib/gcloud/google-http-client-1.21.0.jar
|
||||
maven://com.google.code.findbugs/jsr305/1.3.9|lib/gcloud/jsr305-1.3.9.jar
|
||||
maven://org.apache.httpcomponents/httpclient/4.0.1|lib/gcloud/httpclient-4.0.1.jar
|
||||
maven://org.apache.httpcomponents/httpcore/4.0.1|lib/gcloud/httpcore-4.0.1.jar
|
||||
maven://commons-codec/commons-codec/1.3|lib/gcloud/commons-codec-1.3.jar
|
||||
maven://com.google.oauth-client/google-oauth-client/1.21.0|lib/gcloud/google-oauth-client-1.21.0.jar
|
||||
maven://com.google.guava/guava/19.0|lib/gcloud/guava-19.0.jar
|
||||
maven://com.google.api-client/google-api-client-appengine/1.21.0|lib/gcloud/google-api-client-appengine-1.21.0.jar
|
||||
maven://com.google.oauth-client/google-oauth-client-appengine/1.21.0|lib/gcloud/google-oauth-client-appengine-1.21.0.jar
|
||||
maven://com.google.oauth-client/google-oauth-client-servlet/1.21.0|lib/gcloud/google-oauth-client-servlet-1.21.0.jar
|
||||
maven://com.google.http-client/google-http-client-jdo/1.21.0|lib/gcloud/google-http-client-jdo-1.21.0.jar
|
||||
maven://com.google.api-client/google-api-client-servlet/1.21.0|lib/gcloud/google-api-client-servlet-1.21.0.jar
|
||||
maven://javax.jdo/jdo2-api/2.3-eb|lib/gcloud/jdo2-api-2.3-eb.jar
|
||||
maven://javax.transaction/transaction-api/1.1|lib/gcloud/transaction-api-1.1.jar
|
||||
maven://com.google.http-client/google-http-client-appengine/1.21.0|lib/gcloud/google-http-client-appengine-1.21.0.jar
|
||||
maven://com.google.http-client/google-http-client-jackson/1.21.0|lib/gcloud/google-http-client-jackson-1.21.0.jar
|
||||
maven://org.codehaus.jackson/jackson-core-asl/1.9.11|lib/gcloud/jackson-core-asl-1.9.11.jar
|
||||
maven://joda-time/joda-time/2.9.2|lib/gcloud/joda-time-2.9.2.jar
|
||||
maven://com.google.protobuf/protobuf-java/3.0.0-beta-3|lib/gcloud/protobuf-java-3.0.0-beta-3.jar
|
||||
maven://com.google.api/gax/0.0.16|lib/gcloud/gax-0.0.16.jar
|
||||
maven://io.grpc/grpc-all/0.15.0|lib/gcloud/grpc-all-0.15.0.jar
|
||||
maven://io.grpc/grpc-auth/0.15.0|lib/gcloud/grpc-auth-0.15.0.jar
|
||||
maven://io.grpc/grpc-netty/0.15.0|lib/gcloud/grpc-netty-0.15.0.jar
|
||||
maven://io.netty/netty-codec-http2/4.1.1.Final|lib/gcloud/netty-codec-http2-4.1.1.jar
|
||||
maven://io.netty/netty-codec-http/4.1.1.Final|lib/gcloud/netty-codec-http-4.1.1.Final.jar
|
||||
maven://io.netty/netty-codec/4.1.1.Final|lib/gcloud/netty-codec-4.1.1.Final.jar
|
||||
maven://io.netty/netty-handler/4.1.1.Final|lib/gcloud/netty-handler-4.1.1.Final.jar
|
||||
maven://io.netty/netty-buffer/4.1.1.Final|lib/gcloud/netty-buffer-4.1.1.Final.jar
|
||||
maven://io.netty/netty-common/4.1.1.Final|lib/gcloud/netty-common-4.1.1.Final.jar
|
||||
maven://io.netty/netty-transport/4.1.1.Final|lib/gcloud/netty-transport-4.1.1.Final.jar
|
||||
maven://io.netty/netty-resolver/4.1.1.Final|lib/gcloud/netty-resolver-4.1.1.Final.jar
|
||||
maven://io.grpc/grpc-okhttp/0.15.0|lib/gcloud/grpc-okhttp-0.15.0.jar
|
||||
maven://com.squareup.okio/okio/1.6.0|lib/gcloud/okio-1.6.0.jar
|
||||
maven://com.squareup.okhttp/okhttp/2.5.0|lib/gcloud/okhttp-2.5.0.jar
|
||||
maven://io.grpc/grpc-protobuf-nano/0.15.0|lib/gcloud/grpc-protobuf-nano-0.15.0.jar
|
||||
maven://com.google.protobuf.nano/protobuf-javanano/3.0.0-alpha-5|lib/gcloud/protobuf-javanano-3.0.0-alpha-5.jar
|
||||
maven://io.grpc/grpc-stub/0.15.0|lib/gcloud/grpc-stub-0.15.0.jar
|
||||
maven://io.grpc/grpc-protobuf/0.15.0|lib/gcloud/grpc-protobuf-0.15.0.jar
|
||||
maven://com.google.protobuf/protobuf-java-util/3.0.0-beta-3|lib/gcloud/protobuf-java-util-3.0.0-beta-3.jar
|
||||
maven://com.google.code.gson/gson/2.3|lib/gcloud/gson-2.3.jar
|
||||
maven://io.grpc/grpc-protobuf-lite/0.15.0|lib/gcloud/grpc-protobuf-lite-0.15.0.jar
|
||||
maven://io.grpc/grpc-core/0.15.0|lib/gcloud/grpc-core-0.15.0.jar
|
||||
maven://com.google.auto.value/auto-value/1.1|lib/gcloud/auto-value-1.1.jar
|
||||
maven://com.google.inject/guice/4.0|lib/gcloud/guice-4.0.jar
|
||||
maven://javax.inject/javax.inject/1|lib/gcloud/javax.inject-1.jar
|
||||
maven://aopalliance/aopalliance/1.0|lib/gcloud/aopalliance-1.0.jar
|
||||
maven://com.google.api.grpc/grpc-google-common-protos/0.0.7|lib/gcloud/grpc-google-common-protos-0.0.7.jar
|
||||
maven://org.json/json/20151123|lib/gcloud/json-20151123.jar
|
||||
maven://com.google.cloud.datastore/datastore-v1-protos/1.0.1|lib/gcloud/datastore-v1-protos-1.0.1-beta.jar
|
||||
maven://com.google.cloud.datastore/datastore-v1-proto-client/1.1.0|lib/gcloud/datastore-v1-proto-client-1.1.0.jar
|
||||
maven://com.google.http-client/google-http-client-protobuf/1.20.0|lib/gcloud/google-http-client-protobuf-1.20.0.jar
|
||||
maven://com.google.api-client/google-api-client/1.20.0|lib/gcloud/google-api-client-1.20.0.jar
|
||||
maven://com.google.guava/guava-jdk5/13.0|lib/gcloud/guava-jdk5-13.0.jar
|
||||
|
||||
|
||||
basehome:modules/gcloud/index.yaml|etc/index.yaml
|
||||
|
||||
[lib]
|
||||
lib/jetty-gcloud-session-manager-${jetty.version}.jar
|
||||
lib/gcloud/*.jar
|
||||
|
||||
[xml]
|
||||
etc/sessions/gcloud/session-store.xml
|
||||
|
||||
[license]
|
||||
GCloudDatastore is an open source project hosted on Github and released under the Apache 2.0 license.
|
||||
https://github.com/GoogleCloudPlatform/gcloud-java
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
[ini-template]
|
||||
|
||||
## GCloudDatastore Session config
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<name>Jetty :: GCloud</name>
|
||||
|
||||
<properties>
|
||||
<gcloud.version>0.3.0</gcloud.version>
|
||||
<gcloud.version>0.4.0</gcloud.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
|
|
@ -18,11 +18,14 @@
|
|||
|
||||
package org.eclipse.jetty.osgi.annotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
|
||||
import org.eclipse.jetty.annotations.ClassNameResolver;
|
||||
import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
|
||||
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -44,9 +47,9 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
|
|||
public class BundleParserTask extends ParserTask
|
||||
{
|
||||
|
||||
public BundleParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
|
||||
public BundleParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource)
|
||||
{
|
||||
super(parser, handlers, resource, resolver);
|
||||
super(parser, handlers, resource);
|
||||
}
|
||||
|
||||
public Void call() throws Exception
|
||||
|
@ -57,7 +60,7 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
|
|||
Bundle bundle = osgiAnnotationParser.getBundle(_resource);
|
||||
if (_stat != null)
|
||||
_stat.start();
|
||||
osgiAnnotationParser.parse(_handlers, bundle, _resolver);
|
||||
osgiAnnotationParser.parse(_handlers, bundle);
|
||||
if (_stat != null)
|
||||
_stat.end();
|
||||
}
|
||||
|
@ -79,6 +82,17 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
|
|||
return new AnnotationParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getJarFor(ServletContainerInitializer service) throws MalformedURLException, IOException
|
||||
{
|
||||
Resource resource = super.getJarFor(service);
|
||||
// TODO This is not correct, but implemented like this to be bug for bug compatible
|
||||
// with previous implementation that could only handle actual jars and not bundles.
|
||||
if (resource!=null && !resource.toString().endsWith(".jar"))
|
||||
return null;
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Here is the order in which jars and osgi artifacts are scanned for discoverable annotations.
|
||||
* <ol>
|
||||
|
@ -195,47 +209,13 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
|
|||
handlers.add(_classInheritanceHandler);
|
||||
handlers.addAll(_containerInitializerAnnotationHandlers);
|
||||
|
||||
ClassNameResolver classNameResolver = createClassNameResolver(context);
|
||||
if (_parserTasks != null)
|
||||
{
|
||||
BundleParserTask task = new BundleParserTask(parser, handlers, bundleRes, classNameResolver);
|
||||
BundleParserTask task = new BundleParserTask(parser, handlers, bundleRes);
|
||||
_parserTasks.add(task);
|
||||
if (LOG.isDebugEnabled())
|
||||
task.setStatistic(new TimeStatistic());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the same classname resolver than for the webInfjar scanner
|
||||
* @param context the web app context
|
||||
* @return the class name resolver
|
||||
*/
|
||||
protected ClassNameResolver createClassNameResolver(final WebAppContext context)
|
||||
{
|
||||
return createClassNameResolver(context,true,false,false,false);
|
||||
}
|
||||
|
||||
protected ClassNameResolver createClassNameResolver(final WebAppContext context,
|
||||
final boolean excludeSysClass, final boolean excludeServerClass, final boolean excludeEverythingElse,
|
||||
final boolean overrideIsParenLoaderIsPriority)
|
||||
{
|
||||
return new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return excludeSysClass;
|
||||
if (context.isServerClass(name)) return excludeServerClass;
|
||||
return excludeEverythingElse;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at system classpath
|
||||
if (context.isParentLoaderPriority())
|
||||
return overrideIsParenLoaderIsPriority;
|
||||
return !overrideIsParenLoaderIsPriority;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ 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.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.util.ConcurrentHashSet;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
@ -85,7 +84,7 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
|
|||
*
|
||||
*/
|
||||
@Override
|
||||
public void parse (Set<? extends Handler> handlers, URI[] uris, ClassNameResolver resolver)
|
||||
public void parse (Set<? extends Handler> handlers, URI[] uris)
|
||||
throws Exception
|
||||
{
|
||||
for (URI uri : uris)
|
||||
|
@ -99,16 +98,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(handlers, new URI[] {uri},resolver);
|
||||
super.parse(handlers, new URI[] {uri});
|
||||
}
|
||||
else
|
||||
{
|
||||
parse(handlers, associatedBundle,resolver);
|
||||
parse(handlers, associatedBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void parse(Set<? extends Handler> handlers, Bundle bundle, ClassNameResolver resolver)
|
||||
protected void parse(Set<? extends Handler> handlers, Bundle bundle)
|
||||
throws Exception
|
||||
{
|
||||
URI uri = _bundleToUri.get(bundle);
|
||||
|
@ -205,7 +204,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))))
|
||||
if (!isParsed(shortName))
|
||||
{
|
||||
try (InputStream classInputStream = classUrl.openStream())
|
||||
{
|
||||
|
|
|
@ -47,18 +47,16 @@ public abstract class AbstractOSGiApp extends App
|
|||
private static final Logger LOG = Log.getLogger(AbstractOSGiApp.class);
|
||||
|
||||
protected Bundle _bundle;
|
||||
protected Dictionary _properties;
|
||||
protected Dictionary<?,?> _properties;
|
||||
protected ServiceRegistration _registration;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public AbstractOSGiApp(DeploymentManager manager, AppProvider provider, Bundle bundle, String originId)
|
||||
{
|
||||
super(manager, provider, originId);
|
||||
_properties = bundle.getHeaders();
|
||||
_bundle = bundle;
|
||||
this (manager, provider, bundle, bundle.getHeaders(), originId);
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
public AbstractOSGiApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary properties, String originId)
|
||||
public AbstractOSGiApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary<?,?> properties, String originId)
|
||||
{
|
||||
super(manager, provider, originId);
|
||||
_properties = properties;
|
||||
|
|
|
@ -405,18 +405,23 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
|
|||
}
|
||||
}
|
||||
}
|
||||
if (contextXmlUrl == null) return;
|
||||
if (contextXmlUrl == null)
|
||||
return;
|
||||
|
||||
// Apply it just as the standard jetty ContextProvider would do
|
||||
LOG.info("Applying " + contextXmlUrl + " to " + _webApp);
|
||||
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl);
|
||||
HashMap properties = new HashMap();
|
||||
properties.put("Server", getDeploymentManager().getServer());
|
||||
properties.put(OSGiWebappConstants.JETTY_BUNDLE_ROOT, rootResource.toString());
|
||||
properties.put(OSGiServerConstants.JETTY_HOME, getDeploymentManager().getServer().getAttribute(OSGiServerConstants.JETTY_HOME));
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
xmlConfiguration.configure(_webApp);
|
||||
WebAppClassLoader.runWithServerClassAccess(()->
|
||||
{
|
||||
HashMap<String,String> properties = new HashMap<>();
|
||||
xmlConfiguration.getIdMap().put("Server",getDeploymentManager().getServer());
|
||||
properties.put(OSGiWebappConstants.JETTY_BUNDLE_ROOT, rootResource.toString());
|
||||
properties.put(OSGiServerConstants.JETTY_HOME, (String)getDeploymentManager().getServer().getAttribute(OSGiServerConstants.JETTY_HOME));
|
||||
xmlConfiguration.getProperties().putAll(properties);
|
||||
xmlConfiguration.configure(_webApp);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -175,7 +175,7 @@ public class BundleWebAppProvider extends AbstractWebAppProvider implements Bund
|
|||
String contextPath = null;
|
||||
try
|
||||
{
|
||||
Dictionary headers = bundle.getHeaders();
|
||||
Dictionary<String,String> headers = bundle.getHeaders();
|
||||
|
||||
//does the bundle have a OSGiWebappConstants.JETTY_WAR_FOLDER_PATH
|
||||
String resourcePath = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH, OSGiWebappConstants.JETTY_WAR_RESOURCE_PATH, headers);
|
||||
|
@ -217,7 +217,7 @@ public class BundleWebAppProvider extends AbstractWebAppProvider implements Bund
|
|||
{
|
||||
//Could be a static webapp with no web.xml
|
||||
String base = ".";
|
||||
contextPath = (String)headers.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
contextPath = headers.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
|
||||
String originId = getOriginId(bundle,base);
|
||||
|
||||
OSGiApp app = new OSGiApp(getDeploymentManager(), this, bundle, originId);
|
||||
|
|
|
@ -78,8 +78,6 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
|
||||
private Bundle _contributor;
|
||||
|
||||
private boolean _lookInOsgiFirst = true;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param parent The parent classloader.
|
||||
|
@ -96,11 +94,26 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
return super.loadClass(name);
|
||||
try
|
||||
{
|
||||
return _osgiBundleClassLoader.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException cne)
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException cne2)
|
||||
{
|
||||
throw cne;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -121,36 +134,18 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
{
|
||||
Enumeration<URL> osgiUrls = _osgiBundleClassLoader.getResources(name);
|
||||
Enumeration<URL> urls = super.getResources(name);
|
||||
if (_lookInOsgiFirst)
|
||||
{
|
||||
return Collections.enumeration(toList(osgiUrls, urls));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.enumeration(toList(urls, osgiUrls));
|
||||
}
|
||||
List<URL> resources = toList(osgiUrls, urls);
|
||||
return Collections.enumeration(resources);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public URL getResource(String name)
|
||||
{
|
||||
if (_lookInOsgiFirst)
|
||||
{
|
||||
URL url = _osgiBundleClassLoader.getResource(name);
|
||||
return url != null ? url : super.getResource(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
URL url = super.getResource(name);
|
||||
return url != null ? url : _osgiBundleClassLoader.getResource(name);
|
||||
}
|
||||
URL url = _osgiBundleClassLoader.getResource(name);
|
||||
return url != null ? url : super.getResource(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private List<URL> toList(Enumeration<URL> e, Enumeration<URL> e2)
|
||||
{
|
||||
|
@ -160,30 +155,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
|
|||
while (e2 != null && e2.hasMoreElements())
|
||||
list.add(e2.nextElement());
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
try
|
||||
{
|
||||
return _lookInOsgiFirst ? _osgiBundleClassLoader.loadClass(name) : super.findClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException cne)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _lookInOsgiFirst ? super.findClass(name) : _osgiBundleClassLoader.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException cne2)
|
||||
{
|
||||
throw cne;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
|
|
@ -50,8 +50,8 @@ public class TestConfiguration
|
|||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
wac.setClassLoader(new WebAppClassLoader(Thread.currentThread().getContextClassLoader(), wac));
|
||||
wac.addSystemClass("org.eclipse.jetty.jndi.");
|
||||
wac.prependServerClass("-org.eclipse.jetty.jndi.");
|
||||
wac.getSystemClasspathPattern().include("org.eclipse.jetty.jndi.");
|
||||
wac.getServerClasspathPattern().exclude("org.eclipse.jetty.jndi.");
|
||||
|
||||
MetaData metaData = new MetaData();
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
|||
}
|
||||
|
||||
// If not a supported method - no Vary because no matter what client, this URI is always excluded
|
||||
if (!_methods.matches(baseRequest.getMethod()))
|
||||
if (!_methods.test(baseRequest.getMethod()))
|
||||
{
|
||||
LOG.debug("{} excluded by method {}",this,request);
|
||||
_handler.handle(target,baseRequest, request, response);
|
||||
|
@ -173,7 +173,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
|||
/* ------------------------------------------------------------ */
|
||||
protected boolean isMimeTypeBufferable(String mimetype)
|
||||
{
|
||||
return _mimeTypes.matches(mimetype);
|
||||
return _mimeTypes.test(mimetype);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -182,7 +182,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
|||
if (requestURI == null)
|
||||
return true;
|
||||
|
||||
return _paths.matches(requestURI);
|
||||
return _paths.test(requestURI);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -457,7 +457,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
}
|
||||
|
||||
// If not a supported method - no Vary because no matter what client, this URI is always excluded
|
||||
if (!_methods.matches(baseRequest.getMethod()))
|
||||
if (!_methods.test(baseRequest.getMethod()))
|
||||
{
|
||||
LOG.debug("{} excluded by method {}",this,request);
|
||||
_handler.handle(target,baseRequest, request, response);
|
||||
|
@ -549,14 +549,14 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
if (ua == null)
|
||||
return false;
|
||||
|
||||
return _agentPatterns.matches(ua);
|
||||
return _agentPatterns.test(ua);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean isMimeTypeGzipable(String mimetype)
|
||||
{
|
||||
return _mimeTypes.matches(mimetype);
|
||||
return _mimeTypes.test(mimetype);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -572,7 +572,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
if (requestURI == null)
|
||||
return true;
|
||||
|
||||
return _paths.matches(requestURI);
|
||||
return _paths.test(requestURI);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
|
@ -495,6 +497,39 @@ public class ArrayTernaryTrie<V> extends AbstractTrie<V>
|
|||
return keys;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
int s=0;
|
||||
for (int r=0;r<=_rows;r++)
|
||||
{
|
||||
if (_key[r]!=null && _value[r]!=null)
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
for (int r=0;r<=_rows;r++)
|
||||
{
|
||||
if (_key[r]!=null && _value[r]!=null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public Set<Map.Entry<String,V>> entrySet()
|
||||
{
|
||||
Set<Map.Entry<String,V>> entries = new HashSet<>();
|
||||
for (int r=0;r<=_rows;r++)
|
||||
{
|
||||
if (_key[r]!=null && _value[r]!=null)
|
||||
entries.add(new AbstractMap.SimpleEntry<>(_key[r],_value[r]));
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFull()
|
||||
{
|
||||
|
@ -524,4 +559,143 @@ public class ArrayTernaryTrie<V> extends AbstractTrie<V>
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Growing<V> implements Trie<V>
|
||||
{
|
||||
private final int _growby;
|
||||
private ArrayTernaryTrie<V> _trie;
|
||||
|
||||
public Growing()
|
||||
{
|
||||
this(1024,1024);
|
||||
}
|
||||
|
||||
public Growing(int capacity, int growby)
|
||||
{
|
||||
_growby=growby;
|
||||
_trie = new ArrayTernaryTrie<>(capacity);
|
||||
}
|
||||
|
||||
public Growing(boolean insensitive, int capacity, int growby)
|
||||
{
|
||||
_growby=growby;
|
||||
_trie = new ArrayTernaryTrie<>(insensitive,capacity);
|
||||
}
|
||||
|
||||
public boolean put(V v)
|
||||
{
|
||||
return put(v.toString(),v);
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return _trie.hashCode();
|
||||
}
|
||||
|
||||
public V remove(String s)
|
||||
{
|
||||
return _trie.remove(s);
|
||||
}
|
||||
|
||||
public V get(String s)
|
||||
{
|
||||
return _trie.get(s);
|
||||
}
|
||||
|
||||
public V get(ByteBuffer b)
|
||||
{
|
||||
return _trie.get(b);
|
||||
}
|
||||
|
||||
public V getBest(byte[] b, int offset, int len)
|
||||
{
|
||||
return _trie.getBest(b,offset,len);
|
||||
}
|
||||
|
||||
public boolean isCaseInsensitive()
|
||||
{
|
||||
return _trie.isCaseInsensitive();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return _trie.equals(obj);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
_trie.clear();
|
||||
}
|
||||
|
||||
public boolean put(String s, V v)
|
||||
{
|
||||
boolean added = _trie.put(s,v);
|
||||
while (!added)
|
||||
{
|
||||
ArrayTernaryTrie<V> bigger = new ArrayTernaryTrie<>(_trie._key.length+_growby);
|
||||
for (Map.Entry<String,V> entry : _trie.entrySet())
|
||||
bigger.put(entry.getKey(),entry.getValue());
|
||||
added = _trie.put(s,v);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public V get(String s, int offset, int len)
|
||||
{
|
||||
return _trie.get(s,offset,len);
|
||||
}
|
||||
|
||||
public V get(ByteBuffer b, int offset, int len)
|
||||
{
|
||||
return _trie.get(b,offset,len);
|
||||
}
|
||||
|
||||
public V getBest(String s)
|
||||
{
|
||||
return _trie.getBest(s);
|
||||
}
|
||||
|
||||
public V getBest(String s, int offset, int length)
|
||||
{
|
||||
return _trie.getBest(s,offset,length);
|
||||
}
|
||||
|
||||
public V getBest(ByteBuffer b, int offset, int len)
|
||||
{
|
||||
return _trie.getBest(b,offset,len);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return _trie.toString();
|
||||
}
|
||||
|
||||
public Set<String> keySet()
|
||||
{
|
||||
return _trie.keySet();
|
||||
}
|
||||
|
||||
public boolean isFull()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dump()
|
||||
{
|
||||
_trie.dump();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _trie.isEmpty();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return _trie.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,21 +25,21 @@ import java.util.function.Predicate;
|
|||
|
||||
|
||||
/** Utility class to maintain a set of inclusions and exclusions.
|
||||
* <p>Maintains a set of included and excluded elements. The method {@link #matches(Object)}
|
||||
* <p>Maintains a set of included and excluded elements. The method {@link #test(Object)}
|
||||
* will return true IFF the passed object is not in the excluded set AND ( either the
|
||||
* included set is empty OR the object is in the included set)
|
||||
* <p>The type of the underlying {@link Set} used may be passed into the
|
||||
* constructor, so special sets like Servlet PathMap may be used.
|
||||
* <p>
|
||||
* @param <P> The type of element of the set (often a pattern)
|
||||
* @param <T> The type of the instance passed to the predicate
|
||||
* @param <T> The type of element of the set (often a pattern)
|
||||
* @param <P> The type of the instance passed to the predicate
|
||||
*/
|
||||
public class IncludeExcludeSet<P,T> implements Predicate<T>
|
||||
public class IncludeExcludeSet<T,P> implements Predicate<P>
|
||||
{
|
||||
private final Set<P> _includes;
|
||||
private final Predicate<T> _includePredicate;
|
||||
private final Set<P> _excludes;
|
||||
private final Predicate<T> _excludePredicate;
|
||||
private final Set<T> _includes;
|
||||
private final Predicate<P> _includePredicate;
|
||||
private final Set<T> _excludes;
|
||||
private final Predicate<P> _excludePredicate;
|
||||
|
||||
private static class SetContainsPredicate<T> implements Predicate<T>
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ public class IncludeExcludeSet<P,T> implements Predicate<T>
|
|||
* is created.
|
||||
* @param <SET> The type of a set to use as the backing store
|
||||
*/
|
||||
public <SET extends Set<P>> IncludeExcludeSet(Class<SET> setClass)
|
||||
public <SET extends Set<T>> IncludeExcludeSet(Class<SET> setClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ public class IncludeExcludeSet<P,T> implements Predicate<T>
|
|||
|
||||
if(_includes instanceof Predicate)
|
||||
{
|
||||
_includePredicate = (Predicate<T>)_includes;
|
||||
_includePredicate = (Predicate<P>)_includes;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ public class IncludeExcludeSet<P,T> implements Predicate<T>
|
|||
|
||||
if(_excludes instanceof Predicate)
|
||||
{
|
||||
_excludePredicate = (Predicate<T>)_excludes;
|
||||
_excludePredicate = (Predicate<P>)_excludes;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -113,7 +113,7 @@ public class IncludeExcludeSet<P,T> implements Predicate<T>
|
|||
* @param excludePredicate the Predicate for excluded item testing (null for simple {@link Set#contains(Object)} test)
|
||||
* @param <SET> The type of a set to use as the backing store
|
||||
*/
|
||||
public <SET extends Set<P>> IncludeExcludeSet(Set<P> includeSet, Predicate<T> includePredicate, Set<P> excludeSet, Predicate<T> excludePredicate)
|
||||
public <SET extends Set<T>> IncludeExcludeSet(Set<T> includeSet, Predicate<P> includePredicate, Set<T> excludeSet, Predicate<P> excludePredicate)
|
||||
{
|
||||
Objects.requireNonNull(includeSet,"Include Set");
|
||||
Objects.requireNonNull(includePredicate,"Include Predicate");
|
||||
|
@ -126,51 +126,73 @@ public class IncludeExcludeSet<P,T> implements Predicate<T>
|
|||
_excludePredicate = excludePredicate;
|
||||
}
|
||||
|
||||
public void include(P element)
|
||||
public void include(T element)
|
||||
{
|
||||
_includes.add(element);
|
||||
}
|
||||
|
||||
public void include(P... element)
|
||||
public void include(T... element)
|
||||
{
|
||||
for (P e: element)
|
||||
for (T e: element)
|
||||
_includes.add(e);
|
||||
}
|
||||
|
||||
public void exclude(P element)
|
||||
public void exclude(T element)
|
||||
{
|
||||
_excludes.add(element);
|
||||
}
|
||||
|
||||
public void exclude(P... element)
|
||||
public void exclude(T... element)
|
||||
{
|
||||
for (P e: element)
|
||||
for (T e: element)
|
||||
_excludes.add(e);
|
||||
}
|
||||
|
||||
public boolean matches(T t)
|
||||
|
||||
@Deprecated
|
||||
public boolean matches(P t)
|
||||
{
|
||||
return test(t);
|
||||
}
|
||||
|
||||
public boolean test(T t)
|
||||
@Override
|
||||
public boolean test(P t)
|
||||
{
|
||||
if (!_includes.isEmpty() && !_includePredicate.test(t))
|
||||
return false;
|
||||
return !_excludePredicate.test(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Included and not Excluded
|
||||
* @param t The item to test
|
||||
* @return Boolean.TRUE if t is included, Boolean.FALSE if t is excluded and null if neither
|
||||
*/
|
||||
public Boolean isIncludedAndNotExcluded(P t)
|
||||
{
|
||||
if (_excludePredicate.test(t))
|
||||
return Boolean.FALSE;
|
||||
if (_includePredicate.test(t))
|
||||
return Boolean.TRUE;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasIncludes()
|
||||
{
|
||||
return !_includes.isEmpty();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return _includes.size()+_excludes.size();
|
||||
}
|
||||
|
||||
public Set<P> getIncluded()
|
||||
public Set<T> getIncluded()
|
||||
{
|
||||
return _includes;
|
||||
}
|
||||
|
||||
public Set<P> getExcluded()
|
||||
public Set<T> getExcluded()
|
||||
{
|
||||
return _excludes;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.Set;
|
|||
public interface Trie<V>
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Put and entry into the Trie
|
||||
/** Put an entry into the Trie
|
||||
* @param s The key for the entry
|
||||
* @param v The value of the entry
|
||||
* @return True if the Trie had capacity to add the field.
|
||||
|
@ -47,14 +47,14 @@ public interface Trie<V>
|
|||
public V remove(String s);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get and exact match from a String key
|
||||
/** Get an exact match from a String key
|
||||
* @param s The key
|
||||
* @return the value for the string key
|
||||
*/
|
||||
public V get(String s);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get and exact match from a String key
|
||||
/** Get an exact match from a String key
|
||||
* @param s The key
|
||||
* @param offset The offset within the string of the key
|
||||
* @param len the length of the key
|
||||
|
@ -63,14 +63,14 @@ public interface Trie<V>
|
|||
public V get(String s,int offset,int len);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get and exact match from a segment of a ByteBuufer as key
|
||||
/** Get an exact match from a segment of a ByteBuufer as key
|
||||
* @param b The buffer
|
||||
* @return The value or null if not found
|
||||
*/
|
||||
public V get(ByteBuffer b);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get and exact match from a segment of a ByteBuufer as key
|
||||
/** Get an exact match from a segment of a ByteBuufer as key
|
||||
* @param b The buffer
|
||||
* @param offset The offset within the buffer of the key
|
||||
* @param len the length of the key
|
||||
|
|
|
@ -24,6 +24,9 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -31,9 +34,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -693,4 +699,38 @@ public class TypeUtil
|
|||
return !((Boolean)o).booleanValue();
|
||||
return "false".equalsIgnoreCase(o.toString());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static Resource getLoadedFrom(Class<?> clazz)
|
||||
{
|
||||
ProtectionDomain domain = clazz.getProtectionDomain();
|
||||
if (domain!=null)
|
||||
{
|
||||
CodeSource source = domain.getCodeSource();
|
||||
if (source!=null)
|
||||
{
|
||||
URL location = source.getLocation();
|
||||
|
||||
if (location!=null)
|
||||
return Resource.newResource(location);
|
||||
}
|
||||
}
|
||||
|
||||
String rname = clazz.getName().replace('.','/')+".class";
|
||||
ClassLoader loader = clazz.getClassLoader();
|
||||
URL url = (loader==null?ClassLoader.getSystemClassLoader():loader).getResource(rname);
|
||||
if (url!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Resource.newResource(URIUtil.getJarSource(url.toString()));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
@ -845,4 +846,30 @@ public class URIUtil
|
|||
|
||||
return URI.create(buf.toString());
|
||||
}
|
||||
|
||||
public static URI getJarSource(URI uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!"jar".equals(uri.getScheme()))
|
||||
return uri;
|
||||
String s = uri.getSchemeSpecificPart();
|
||||
int bang_slash = s.indexOf("!/");
|
||||
if (bang_slash>=0)
|
||||
s=s.substring(0,bang_slash);
|
||||
return new URI(s);
|
||||
}
|
||||
catch(URISyntaxException e)
|
||||
{
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getJarSource(String uri)
|
||||
{
|
||||
if (!uri.startsWith("jar:"))
|
||||
return uri;
|
||||
int bang_slash = uri.indexOf("!/");
|
||||
return (bang_slash>=0)?uri.substring(4,bang_slash):uri.substring(4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class IncludeExcludeTest
|
|||
IncludeExclude<String> ie = new IncludeExclude<>();
|
||||
|
||||
assertThat("Empty IncludeExclude", ie.size(), is(0));
|
||||
assertThat("Matches 'foo'",ie.matches("foo"),is(true));
|
||||
assertThat("Matches 'foo'",ie.test("foo"),is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -43,10 +43,10 @@ public class IncludeExcludeTest
|
|||
ie.include("bar");
|
||||
|
||||
assertThat("IncludeExclude.size", ie.size(), is(2));
|
||||
assertEquals(false,ie.matches(""));
|
||||
assertEquals(true,ie.matches("foo"));
|
||||
assertEquals(true,ie.matches("bar"));
|
||||
assertEquals(false,ie.matches("foobar"));
|
||||
assertEquals(false,ie.test(""));
|
||||
assertEquals(true,ie.test("foo"));
|
||||
assertEquals(true,ie.test("bar"));
|
||||
assertEquals(false,ie.test("foobar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -58,11 +58,11 @@ public class IncludeExcludeTest
|
|||
|
||||
assertEquals(2,ie.size());
|
||||
|
||||
assertEquals(false,ie.matches("foo"));
|
||||
assertEquals(false,ie.matches("bar"));
|
||||
assertEquals(true,ie.matches(""));
|
||||
assertEquals(true,ie.matches("foobar"));
|
||||
assertEquals(true,ie.matches("wibble"));
|
||||
assertEquals(false,ie.test("foo"));
|
||||
assertEquals(false,ie.test("bar"));
|
||||
assertEquals(true,ie.test(""));
|
||||
assertEquals(true,ie.test("foobar"));
|
||||
assertEquals(true,ie.test("wibble"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -76,11 +76,11 @@ public class IncludeExcludeTest
|
|||
|
||||
assertEquals(4,ie.size());
|
||||
|
||||
assertEquals(true,ie.matches("foo"));
|
||||
assertEquals(false,ie.matches("bar"));
|
||||
assertEquals(false,ie.matches(""));
|
||||
assertEquals(false,ie.matches("foobar"));
|
||||
assertEquals(false,ie.matches("xxx"));
|
||||
assertEquals(true,ie.test("foo"));
|
||||
assertEquals(false,ie.test("bar"));
|
||||
assertEquals(false,ie.test(""));
|
||||
assertEquals(false,ie.test("foobar"));
|
||||
assertEquals(false,ie.test("xxx"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class IncludeExcludeTest
|
|||
IncludeExclude<String> ie = new IncludeExclude<>(RegexSet.class);
|
||||
|
||||
assertEquals(0,ie.size());
|
||||
assertEquals(true,ie.matches("foo"));
|
||||
assertEquals(true,ie.test("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,13 +102,13 @@ public class IncludeExcludeTest
|
|||
ie.include("b((ar)|(oo))");
|
||||
|
||||
assertEquals(2,ie.size());
|
||||
assertEquals(false,ie.matches(""));
|
||||
assertEquals(true,ie.matches("foo"));
|
||||
assertEquals(true,ie.matches("far"));
|
||||
assertEquals(true,ie.matches("bar"));
|
||||
assertEquals(true,ie.matches("boo"));
|
||||
assertEquals(false,ie.matches("foobar"));
|
||||
assertEquals(false,ie.matches("xxx"));
|
||||
assertEquals(false,ie.test(""));
|
||||
assertEquals(true,ie.test("foo"));
|
||||
assertEquals(true,ie.test("far"));
|
||||
assertEquals(true,ie.test("bar"));
|
||||
assertEquals(true,ie.test("boo"));
|
||||
assertEquals(false,ie.test("foobar"));
|
||||
assertEquals(false,ie.test("xxx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -120,13 +120,13 @@ public class IncludeExcludeTest
|
|||
|
||||
assertEquals(2,ie.size());
|
||||
|
||||
assertEquals(false,ie.matches("foo"));
|
||||
assertEquals(false,ie.matches("far"));
|
||||
assertEquals(false,ie.matches("bar"));
|
||||
assertEquals(false,ie.matches("boo"));
|
||||
assertEquals(true,ie.matches(""));
|
||||
assertEquals(true,ie.matches("foobar"));
|
||||
assertEquals(true,ie.matches("xxx"));
|
||||
assertEquals(false,ie.test("foo"));
|
||||
assertEquals(false,ie.test("far"));
|
||||
assertEquals(false,ie.test("bar"));
|
||||
assertEquals(false,ie.test("boo"));
|
||||
assertEquals(true,ie.test(""));
|
||||
assertEquals(true,ie.test("foobar"));
|
||||
assertEquals(true,ie.test("xxx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -139,14 +139,14 @@ public class IncludeExcludeTest
|
|||
ie.exclude("b((ar)|(oo))");
|
||||
|
||||
assertEquals(4,ie.size());
|
||||
assertEquals(false,ie.matches("foo"));
|
||||
assertEquals(false,ie.matches("far"));
|
||||
assertEquals(false,ie.matches("bar"));
|
||||
assertEquals(false,ie.matches("boo"));
|
||||
assertEquals(false,ie.matches(""));
|
||||
assertEquals(false,ie.matches("xxx"));
|
||||
assertEquals(false,ie.test("foo"));
|
||||
assertEquals(false,ie.test("far"));
|
||||
assertEquals(false,ie.test("bar"));
|
||||
assertEquals(false,ie.test("boo"));
|
||||
assertEquals(false,ie.test(""));
|
||||
assertEquals(false,ie.test("xxx"));
|
||||
|
||||
assertEquals(true,ie.matches("foobar"));
|
||||
assertEquals(true,ie.matches("Ant"));
|
||||
assertEquals(true,ie.test("foobar"));
|
||||
assertEquals(true,ie.test("Ant"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -119,4 +120,12 @@ public class TypeUtilTest
|
|||
Assert.assertFalse(TypeUtil.isFalse("blargle"));
|
||||
Assert.assertFalse(TypeUtil.isFalse(new Object(){@Override public String toString(){return "true";}}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadedFrom() throws Exception
|
||||
{
|
||||
Assert.assertThat(TypeUtil.getLoadedFrom(String.class).toString(),Matchers.containsString("/rt.jar"));
|
||||
Assert.assertThat(TypeUtil.getLoadedFrom(Assert.class).toString(),Matchers.containsString(".jar"));
|
||||
Assert.assertThat(TypeUtil.getLoadedFrom(TypeUtil.class).toString(),Matchers.containsString("/classes/"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,17 @@
|
|||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
@ -286,4 +291,15 @@ public class URIUtilTest
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Test
|
||||
public void testJarSource() throws Exception
|
||||
{
|
||||
assertThat(URIUtil.getJarSource("file:///tmp/"),is("file:///tmp/"));
|
||||
assertThat(URIUtil.getJarSource("jar:file:///tmp/foo.jar"),is("file:///tmp/foo.jar"));
|
||||
assertThat(URIUtil.getJarSource("jar:file:///tmp/foo.jar!/some/path"),is("file:///tmp/foo.jar"));
|
||||
assertThat(URIUtil.getJarSource(new URI("file:///tmp/")),is(new URI("file:///tmp/")));
|
||||
assertThat(URIUtil.getJarSource(new URI("jar:file:///tmp/foo.jar")),is(new URI("file:///tmp/foo.jar")));
|
||||
assertThat(URIUtil.getJarSource(new URI("jar:file:///tmp/foo.jar!/some/path")),is(new URI("file:///tmp/foo.jar")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Call class="org.eclipse.jetty.webapp.WebAppContext" name="addSystemClasses">
|
||||
<Arg><Ref refid="Server"/></Arg>
|
||||
<Arg>
|
||||
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
|
||||
<Arg><Property name="jetty.webapp.addSystemClasses"/></Arg>
|
||||
</Call>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<Call class="org.eclipse.jetty.webapp.WebAppContext" name="addServerClasses">
|
||||
<Arg><Ref refid="Server"/></Arg>
|
||||
<Arg>
|
||||
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
|
||||
<Arg><Property name="jetty.webapp.addServerClasses"/></Arg>
|
||||
</Call>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
|
@ -6,5 +6,23 @@ classpath. Without this, only Jetty specific handlers may be deployed.
|
|||
servlet
|
||||
security
|
||||
|
||||
[xml]
|
||||
etc/jetty-webapp.xml
|
||||
|
||||
[lib]
|
||||
lib/jetty-webapp-${jetty.version}.jar
|
||||
|
||||
|
||||
[ini-template]
|
||||
## Add to the server wide default jars and packages protected or hidden from webapps.
|
||||
## System classes are protected and cannot be overridden by a webapp.
|
||||
## Server classes are hidden and cannot be seen by a webapp
|
||||
## Lists of patterns are comma separated and may be either:
|
||||
## + a qualified classname e.g. 'com.acme.Foo'
|
||||
## + a package name e.g. 'net.example.'
|
||||
## + a jar file e.g. 'file:${jetty.base}/lib/dependency.jar'
|
||||
## + a directory of jars,resource or classes e.g. 'file:${jetty.base}/resources'
|
||||
## + A pattern preceeded with a '-' is an exclusion, all other patterns are inclusions
|
||||
##
|
||||
#jetty.webapp.addSystemClasses=
|
||||
#jetty.webapp.addServerClasses=
|
||||
|
|
|
@ -19,15 +19,36 @@
|
|||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.eclipse.jetty.util.ArrayTernaryTrie;
|
||||
import org.eclipse.jetty.util.IncludeExcludeSet;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Classpath classes list performs pattern matching of a class name
|
||||
* against an classpath pattern entries.
|
||||
* A class pattern is a string of one of the forms/rules:<ul>
|
||||
* Classpath classes list performs sequential pattern matching of a class name
|
||||
* against an internal array of classpath pattern entries.
|
||||
* A class pattern is a string of one of the forms:<ul>
|
||||
* <li>'org.package.SomeClass' will match a specific class
|
||||
* <li>'org.package.' will match a specific package hierarchy
|
||||
* <li>'-org.package.Classname' excludes a specific class
|
||||
|
@ -36,45 +57,64 @@ import java.util.stream.Collectors;
|
|||
* are to be explicitly included or excluded (eg. org.example.MyClass$NestedClass).
|
||||
* <li>Nested classes are matched by their containing class. (eg. -org.example.MyClass
|
||||
* would exclude org.example.MyClass$AnyNestedClass)
|
||||
* <li>Package or Class exclusions are applied before inclusive patterns.
|
||||
* </ul>
|
||||
* When class is initialized from a classpath pattern string, entries
|
||||
* in this string should be separated by ':' (semicolon) or ',' (comma).
|
||||
*/
|
||||
|
||||
public class ClasspathPattern
|
||||
public class ClasspathPattern extends AbstractSet<String>
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ClasspathPattern.class);
|
||||
|
||||
enum Type { PACKAGE, CLASSNAME, LOCATION }
|
||||
|
||||
private static class Entry
|
||||
{
|
||||
final String _pattern;
|
||||
final String _name;
|
||||
final boolean _inclusive;
|
||||
final boolean _package;
|
||||
private final String _pattern;
|
||||
private final String _name;
|
||||
private final boolean _inclusive;
|
||||
private final Type _type;
|
||||
|
||||
Entry(String pattern)
|
||||
{
|
||||
_pattern=pattern;
|
||||
_inclusive = !pattern.startsWith("-");
|
||||
_package = pattern.endsWith(".");
|
||||
_name = _inclusive ? pattern : pattern.substring(1).trim();
|
||||
_type = (_name.startsWith("file:"))?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME);
|
||||
}
|
||||
|
||||
boolean isInclusive()
|
||||
Entry(String name, boolean include)
|
||||
{
|
||||
return _inclusive;
|
||||
_pattern=include?name:("-"+name);
|
||||
_inclusive = include;
|
||||
_name = name;
|
||||
_type = (_name.startsWith("file:"))?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
|
||||
public String getPattern()
|
||||
{
|
||||
if (o instanceof Entry)
|
||||
{
|
||||
Entry e=(Entry)o;
|
||||
if (_pattern==null && e._pattern==null)
|
||||
return true;
|
||||
return _pattern.equals(e._pattern);
|
||||
}
|
||||
return false;
|
||||
return _pattern;
|
||||
}
|
||||
|
||||
public boolean isPackage()
|
||||
{
|
||||
return _type==Type.PACKAGE;
|
||||
}
|
||||
|
||||
public boolean isClassName()
|
||||
{
|
||||
return _type==Type.CLASSNAME;
|
||||
}
|
||||
|
||||
public boolean isLocation()
|
||||
{
|
||||
return _type==Type.LOCATION;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,183 +122,407 @@ public class ClasspathPattern
|
|||
{
|
||||
return _pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return _pattern.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return (o instanceof Entry)
|
||||
&& _pattern.equals(((Entry)o)._pattern);
|
||||
}
|
||||
|
||||
public boolean isInclusive()
|
||||
{
|
||||
return _inclusive;
|
||||
}
|
||||
}
|
||||
|
||||
final private List<Entry> _entries = new ArrayList<Entry>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static class ByPackage extends AbstractSet<Entry> implements Predicate<String>
|
||||
{
|
||||
private final ArrayTernaryTrie.Growing<Entry> _entries = new ArrayTernaryTrie.Growing<>(false,512,512);
|
||||
|
||||
@Override
|
||||
public boolean test(String name)
|
||||
{
|
||||
return _entries.getBest(name)!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry> iterator()
|
||||
{
|
||||
return _entries.keySet().stream().map(k->_entries.get(k)).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _entries.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Entry entry)
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (entry.isClassName())
|
||||
name+="$";
|
||||
else if (entry.isLocation())
|
||||
throw new IllegalArgumentException(entry.toString());
|
||||
else if (".".equals(name))
|
||||
name="";
|
||||
|
||||
if (_entries.get(name)!=null)
|
||||
return false;
|
||||
|
||||
_entries.put(name,entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object entry)
|
||||
{
|
||||
if (!(entry instanceof Entry))
|
||||
return false;
|
||||
|
||||
return _entries.remove(((Entry)entry).getName())!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_entries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class ByName extends HashSet<Entry> implements Predicate<String>
|
||||
{
|
||||
private final Map<String,Entry> _entries = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean test(String name)
|
||||
{
|
||||
return _entries.containsKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry> iterator()
|
||||
{
|
||||
return _entries.values().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Entry entry)
|
||||
{
|
||||
if (!entry.isClassName())
|
||||
throw new IllegalArgumentException(entry.toString());
|
||||
return _entries.put(entry.getName(),entry)==null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object entry)
|
||||
{
|
||||
if (!(entry instanceof Entry))
|
||||
return false;
|
||||
|
||||
return _entries.remove(((Entry)entry).getName())!=null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByPackageOrName extends AbstractSet<Entry> implements Predicate<String>
|
||||
{
|
||||
private final ByName _byName = new ByName();
|
||||
private final ByPackage _byPackage = new ByPackage();
|
||||
|
||||
@Override
|
||||
public boolean test(String name)
|
||||
{
|
||||
return _byPackage.test(name)
|
||||
|| _byName.test(name) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry> iterator()
|
||||
{
|
||||
// by package contains all entries (classes are also $ packages).
|
||||
return _byPackage.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _byPackage.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Entry e)
|
||||
{
|
||||
if (e.isLocation())
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
if (e.isPackage())
|
||||
return _byPackage.add(e);
|
||||
|
||||
// Add class name to packages also as classes act
|
||||
// as packages for nested classes.
|
||||
boolean added = _byPackage.add(e);
|
||||
added = _byName.add(e) || added;
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
if (!(o instanceof Entry))
|
||||
return false;
|
||||
|
||||
boolean removed = _byPackage.remove(o);
|
||||
|
||||
if (!((Entry)o).isPackage())
|
||||
removed = _byName.remove(o) || removed;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_byPackage.clear();
|
||||
_byName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class ByLocation extends HashSet<File> implements Predicate<Path>
|
||||
{
|
||||
@Override
|
||||
public boolean test(Path path)
|
||||
{
|
||||
for (File file: this)
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
if (path.startsWith(file.toPath()))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path.equals(file.toPath()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Map<String,Entry> _entries = new HashMap<>();
|
||||
Set<String> _classes = new HashSet<>();
|
||||
|
||||
IncludeExcludeSet<Entry,String> _patterns = new IncludeExcludeSet<>(ByPackageOrName.class);
|
||||
IncludeExcludeSet<File,Path> _locations = new IncludeExcludeSet<>(ByLocation.class);
|
||||
|
||||
public ClasspathPattern()
|
||||
{
|
||||
}
|
||||
|
||||
public ClasspathPattern(ClasspathPattern patterns)
|
||||
{
|
||||
if (patterns!=null)
|
||||
setAll(patterns.getPatterns());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ClasspathPattern(String... patterns)
|
||||
{
|
||||
if (patterns!=null && patterns.length>0)
|
||||
add(patterns);
|
||||
setAll(patterns);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ClasspathPattern(String pattern)
|
||||
{
|
||||
add(pattern);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ClasspathPattern(ClasspathPattern patterns)
|
||||
public boolean include(String name)
|
||||
{
|
||||
add(patterns);
|
||||
if (name==null)
|
||||
return false;
|
||||
return add(new Entry(name,true));
|
||||
}
|
||||
|
||||
public boolean include(String... name)
|
||||
{
|
||||
boolean added = false;
|
||||
for (String n:name)
|
||||
if (n!=null)
|
||||
added = add(new Entry(n,true)) || added;
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean exclude(String name)
|
||||
{
|
||||
if (name==null)
|
||||
return false;
|
||||
return add(new Entry(name,false));
|
||||
}
|
||||
|
||||
public boolean exclude(String... name)
|
||||
{
|
||||
boolean added = false;
|
||||
for (String n:name)
|
||||
if (n!=null)
|
||||
added = add(new Entry(n,false)) || added;
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(String pattern)
|
||||
{
|
||||
if (pattern==null)
|
||||
return false;
|
||||
return add(new Entry(pattern));
|
||||
}
|
||||
|
||||
public boolean add(String... pattern)
|
||||
{
|
||||
boolean added = false;
|
||||
for (String p:pattern)
|
||||
if (p!=null)
|
||||
added = add(new Entry(p)) || added;
|
||||
return added;
|
||||
}
|
||||
|
||||
protected boolean add(Entry entry)
|
||||
{
|
||||
if (_entries.containsKey(entry.getPattern()))
|
||||
return false;
|
||||
_entries.put(entry.getPattern(),entry);
|
||||
|
||||
if (entry.isLocation())
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = Resource.newResource(entry.getName()).getFile().getAbsoluteFile().getCanonicalFile();
|
||||
if (entry.isInclusive())
|
||||
_locations.include(file);
|
||||
else
|
||||
_locations.exclude(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry.isInclusive())
|
||||
_patterns.include(entry);
|
||||
else
|
||||
_patterns.exclude(entry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
if (!(o instanceof String))
|
||||
return false;
|
||||
String pattern = (String)o;
|
||||
|
||||
Entry entry = _entries.remove(pattern);
|
||||
if (entry==null)
|
||||
return false;
|
||||
|
||||
List<Entry> saved = new ArrayList<>(_entries.values());
|
||||
clear();
|
||||
for (Entry e:saved)
|
||||
add(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_entries.clear();
|
||||
_patterns.clear();
|
||||
_locations.clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isEmpty()
|
||||
@Override
|
||||
public Iterator<String> iterator()
|
||||
{
|
||||
return _entries.isEmpty();
|
||||
return _entries.keySet().iterator();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void exclude(String... patterns)
|
||||
{
|
||||
if (patterns==null || patterns.length==0)
|
||||
return;
|
||||
|
||||
for (String p :patterns)
|
||||
{
|
||||
if (p.startsWith("-"))
|
||||
throw new IllegalArgumentException();
|
||||
String x="-"+p;
|
||||
if (_entries.stream().anyMatch(e->{return x.equals(e.toString());}))
|
||||
continue;
|
||||
|
||||
Entry e = new Entry(x);
|
||||
_entries.add(0,e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void add(String... patterns)
|
||||
{
|
||||
if (patterns==null || patterns.length==0)
|
||||
return;
|
||||
|
||||
for (String p :patterns)
|
||||
{
|
||||
if (_entries.stream().anyMatch(e->{return p.equals(e.toString());}))
|
||||
continue;
|
||||
|
||||
Entry e = new Entry(p);
|
||||
if (e.isInclusive())
|
||||
_entries.add(e);
|
||||
else
|
||||
_entries.add(0,e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void add(ClasspathPattern pattern)
|
||||
{
|
||||
if (pattern==null)
|
||||
return;
|
||||
|
||||
for (Entry e :pattern._entries)
|
||||
{
|
||||
if (_entries.contains(e))
|
||||
continue;
|
||||
|
||||
if (e.isInclusive())
|
||||
_entries.add(e);
|
||||
else
|
||||
_entries.add(0,e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addInclusions(ClasspathPattern pattern)
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
if (pattern==null)
|
||||
return;
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
for (Entry e :pattern._entries)
|
||||
{
|
||||
if (_entries.contains(e))
|
||||
continue;
|
||||
|
||||
if (e.isInclusive())
|
||||
_entries.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addExclusions(ClasspathPattern pattern)
|
||||
/**
|
||||
* Initialize the matcher by parsing each classpath pattern in an array
|
||||
*
|
||||
* @param classes array of classpath patterns
|
||||
*/
|
||||
private void setAll(String[] classes)
|
||||
{
|
||||
if (pattern==null)
|
||||
return;
|
||||
|
||||
for (Entry e :pattern._entries)
|
||||
{
|
||||
if (_entries.contains(e))
|
||||
continue;
|
||||
|
||||
if (!e.isInclusive())
|
||||
_entries.add(0,e);
|
||||
}
|
||||
_entries.clear();
|
||||
addAll(classes);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean remove(String pattern)
|
||||
/**
|
||||
* @param classes array of classpath patterns
|
||||
*/
|
||||
private void addAll(String[] classes)
|
||||
{
|
||||
for (int i=_entries.size();i-->0;)
|
||||
{
|
||||
if (pattern.equals(_entries.get(i)._pattern))
|
||||
{
|
||||
_entries.remove(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (classes!=null)
|
||||
addAll(Arrays.asList(classes));
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return array of classpath patterns
|
||||
*/
|
||||
public String[] toArray()
|
||||
public String[] getPatterns()
|
||||
{
|
||||
return _entries.stream().map(e->{return e.toString();}).toArray(String[]::new);
|
||||
return toArray(new String[_entries.size()]);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return array of classpath patterns
|
||||
* @return array of inclusive classpath patterns
|
||||
*/
|
||||
public List<String> getPatterns()
|
||||
public String[] getInclusions()
|
||||
{
|
||||
return _entries.stream().map(e->{return e.toString();}).collect(Collectors.toList());
|
||||
return _entries.values().stream().filter(Entry::isInclusive).map(Entry::getName).toArray(String[]::new);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return List of classes excluded class exclusions and package patterns
|
||||
* @return array of excluded classpath patterns (without '-' prefix)
|
||||
*/
|
||||
public List<String> getClasses()
|
||||
public String[] getExclusions()
|
||||
{
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Entry e:_entries)
|
||||
{
|
||||
if (e._inclusive && !e._package)
|
||||
list.add(e._name);
|
||||
}
|
||||
return list;
|
||||
return _entries.values().stream().filter(e->!e.isInclusive()).map(Entry::getName).toArray(String[]::new);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Match the class name against the pattern
|
||||
*
|
||||
|
@ -267,26 +531,67 @@ public class ClasspathPattern
|
|||
*/
|
||||
public boolean match(String name)
|
||||
{
|
||||
name = name.replace('/','.');
|
||||
|
||||
for (Entry entry : _entries)
|
||||
return _patterns.test(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the class name against the pattern
|
||||
*
|
||||
* @param clazz A class to try to match
|
||||
* @return true if class matches the pattern
|
||||
*/
|
||||
public boolean match(Class<?> clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (entry==null)
|
||||
continue;
|
||||
if (entry._package)
|
||||
{
|
||||
if (name.startsWith(entry._name) || ".".equals(entry._pattern))
|
||||
return entry._inclusive;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.equals(entry._name))
|
||||
return entry._inclusive;
|
||||
|
||||
if (name.length()>entry._name.length() && '$'==name.charAt(entry._name.length()) && name.startsWith(entry._name))
|
||||
return entry._inclusive;
|
||||
}
|
||||
Resource resource = TypeUtil.getLoadedFrom(clazz);
|
||||
Path path = resource.getFile().toPath();
|
||||
|
||||
Boolean byName = _patterns.isIncludedAndNotExcluded(clazz.getName());
|
||||
Boolean byLocation = _locations.isIncludedAndNotExcluded(path);
|
||||
|
||||
// Combine the tri-state match of both IncludeExclude Sets
|
||||
boolean included = byName==TRUE || byLocation==TRUE
|
||||
|| (byName==null && !_patterns.hasIncludes() && byLocation==null && !_locations.hasIncludes());
|
||||
boolean excluded = byName==FALSE || byLocation==FALSE;
|
||||
return included && !excluded;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean match(String name, URL url)
|
||||
{
|
||||
// Strip class suffix for name matching
|
||||
if (name.endsWith(".class"))
|
||||
name=name.substring(0,name.length()-6);
|
||||
|
||||
// Treat path elements as packages for name matching
|
||||
name=name.replace("/",".");
|
||||
|
||||
Boolean byName = _patterns.isIncludedAndNotExcluded(name);
|
||||
|
||||
// Try to find a file path for location matching
|
||||
Boolean byLocation = null;
|
||||
try
|
||||
{
|
||||
Resource resource = Resource.newResource(URIUtil.getJarSource(url.toURI()));
|
||||
File file = resource.getFile();
|
||||
byLocation = _locations.isIncludedAndNotExcluded(file.toPath());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
|
||||
// Combine the tri-state match of both IncludeExclude Sets
|
||||
boolean included = byName==TRUE || byLocation==TRUE
|
||||
|| (byName==null && !_patterns.hasIncludes() && byLocation==null && !_locations.hasIncludes());
|
||||
boolean excluded = byName==FALSE || byLocation==FALSE;
|
||||
return included && !excluded;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
* @return Returns the permissions.
|
||||
*/
|
||||
PermissionCollection getPermissions();
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the class a System Class.
|
||||
* A System class is a class that is visible to a webapplication,
|
||||
|
@ -110,7 +110,7 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
* @param clazz The fully qualified name of the class.
|
||||
* @return True if the class is a system class.
|
||||
*/
|
||||
boolean isSystemClass(String clazz);
|
||||
boolean isSystemClass(Class<?> clazz);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the class a Server Class.
|
||||
|
@ -121,7 +121,7 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
* @param clazz The fully qualified name of the class.
|
||||
* @return True if the class is a server class.
|
||||
*/
|
||||
boolean isServerClass(String clazz);
|
||||
boolean isServerClass(Class<?> clazz);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -134,6 +134,10 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
String getExtraClasspath();
|
||||
|
||||
boolean isServerResource(String name, URL parent_url);
|
||||
|
||||
boolean isSystemResource(String name, URL webapp_url);
|
||||
|
||||
}
|
||||
|
||||
|
@ -141,9 +145,10 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
/** Run an action with access to ServerClasses
|
||||
* <p>Run the passed {@link PrivilegedExceptionAction} with the classloader
|
||||
* configured so as to allow server classes to be visible</p>
|
||||
* @param <T> The type returned by the action
|
||||
* @param action The action to run
|
||||
* @return The return from the action
|
||||
* @throws Exception when not able to run with server classes
|
||||
* @throws Exception if thrown by the action
|
||||
* @param <T> the type of PrivilegedExceptionAction
|
||||
*/
|
||||
public static <T> T runWithServerClassAccess(PrivilegedExceptionAction<T> action) throws Exception
|
||||
|
@ -361,27 +366,42 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException
|
||||
{
|
||||
boolean system_class=_context.isSystemClass(name);
|
||||
boolean server_class=_context.isServerClass(name) && !Boolean.TRUE.equals(__loadServerClasses.get());
|
||||
List<URL> from_parent = new ArrayList<>();
|
||||
List<URL> from_webapp = new ArrayList<>();
|
||||
|
||||
Enumeration<URL> urls = _parent.getResources(name);
|
||||
while (urls!=null && urls.hasMoreElements())
|
||||
{
|
||||
URL url = urls.nextElement();
|
||||
if (Boolean.TRUE.equals(__loadServerClasses.get()) || !_context.isServerResource(name,url))
|
||||
from_parent.add(url);
|
||||
}
|
||||
|
||||
urls = this.findResources(name);
|
||||
while (urls!=null && urls.hasMoreElements())
|
||||
{
|
||||
URL url = urls.nextElement();
|
||||
if (!_context.isSystemResource(name,url) || from_parent.isEmpty())
|
||||
from_webapp.add(url);
|
||||
}
|
||||
|
||||
List<URL> resources;
|
||||
|
||||
List<URL> from_parent = toList(server_class?null:_parent.getResources(name));
|
||||
List<URL> from_webapp = toList((system_class&&!from_parent.isEmpty())?null:this.findResources(name));
|
||||
|
||||
if (_context.isParentLoaderPriority())
|
||||
{
|
||||
from_parent.addAll(from_webapp);
|
||||
return Collections.enumeration(from_parent);
|
||||
resources = from_parent;
|
||||
}
|
||||
from_webapp.addAll(from_parent);
|
||||
return Collections.enumeration(from_webapp);
|
||||
}
|
||||
else
|
||||
{
|
||||
from_webapp.addAll(from_parent);
|
||||
resources = from_webapp;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("getResources {} {}",name,resources);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private List<URL> toList(Enumeration<URL> e)
|
||||
{
|
||||
if (e==null)
|
||||
return new ArrayList<URL>();
|
||||
return Collections.list(e);
|
||||
return Collections.enumeration(resources);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -395,138 +415,180 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
@Override
|
||||
public URL getResource(String name)
|
||||
{
|
||||
URL url= null;
|
||||
boolean tried_parent= false;
|
||||
|
||||
//If the resource is a class name with .class suffix, strip it off before comparison
|
||||
//as the server and system patterns are specified without a .class suffix
|
||||
String tmp = name;
|
||||
if (tmp != null && tmp.endsWith(".class"))
|
||||
tmp = tmp.substring(0, tmp.length()-6);
|
||||
|
||||
boolean system_class=_context.isSystemClass(tmp);
|
||||
boolean server_class=_context.isServerClass(tmp) && !Boolean.TRUE.equals(__loadServerClasses.get());
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("getResource({}) system={} server={} cl={}",name,system_class,server_class,this);
|
||||
|
||||
if (system_class && server_class)
|
||||
return null;
|
||||
|
||||
ClassLoader source=null;
|
||||
|
||||
if (_parent!=null &&(_context.isParentLoaderPriority() || system_class ) && !server_class)
|
||||
URL resource=null;
|
||||
if (_context.isParentLoaderPriority())
|
||||
{
|
||||
tried_parent= true;
|
||||
URL parent_url=_parent.getResource(name);
|
||||
|
||||
if (_parent!=null)
|
||||
// return if we have a url the webapp is allowed to see
|
||||
if (parent_url!=null
|
||||
&& (Boolean.TRUE.equals(__loadServerClasses.get())
|
||||
|| !_context.isServerResource(name,parent_url)))
|
||||
resource = parent_url;
|
||||
else
|
||||
{
|
||||
source=_parent;
|
||||
url=_parent.getResource(name);
|
||||
URL webapp_url = this.findResource(name);
|
||||
|
||||
// If found here then OK to use regardless of system or server classes
|
||||
// If it is a system resource, we've already tried to load from parent, so
|
||||
// would have returned it.
|
||||
// If it is a server resource, doesn't matter as we have loaded it from the
|
||||
// webapp
|
||||
if (webapp_url!=null)
|
||||
resource = webapp_url;
|
||||
}
|
||||
}
|
||||
|
||||
if (url == null)
|
||||
else
|
||||
{
|
||||
url= this.findResource(name);
|
||||
source=this;
|
||||
if (url == null && name.startsWith("/"))
|
||||
url= this.findResource(name.substring(1));
|
||||
}
|
||||
URL webapp_url = this.findResource(name);
|
||||
|
||||
if (url == null && !tried_parent && !server_class )
|
||||
{
|
||||
if (_parent!=null)
|
||||
if (webapp_url!=null && !_context.isSystemResource(name,webapp_url))
|
||||
resource = webapp_url;
|
||||
else
|
||||
{
|
||||
tried_parent=true;
|
||||
source=_parent;
|
||||
url= _parent.getResource(name);
|
||||
|
||||
// Couldn't find or see a webapp resource, so try a parent
|
||||
URL parent_url=_parent.getResource(name);
|
||||
if (parent_url!=null
|
||||
&& (Boolean.TRUE.equals(__loadServerClasses.get())
|
||||
|| !_context.isServerResource(name,parent_url)))
|
||||
resource = parent_url;
|
||||
// We couldn't find a parent resource, so OK to return a webapp one if it exists
|
||||
// and we just couldn't see it before
|
||||
else if (webapp_url!=null)
|
||||
resource = webapp_url;
|
||||
}
|
||||
}
|
||||
|
||||
// Perhaps this failed due to leading /
|
||||
if (resource==null && name.startsWith("/"))
|
||||
resource = getResource(name.substring(1));
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("gotResource({})=={} from={} tried_parent={}",name,url,source,tried_parent);
|
||||
|
||||
return url;
|
||||
LOG.debug("getResource {} {}",name,resource);
|
||||
|
||||
return resource;
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
|
||||
{
|
||||
LOG.setDebugEnabled(true);
|
||||
WebAppContext.LOG.setDebugEnabled(true);
|
||||
|
||||
synchronized (getClassLoadingLock(name))
|
||||
{
|
||||
Class<?> c= findLoadedClass(name);
|
||||
{
|
||||
ClassNotFoundException ex= null;
|
||||
boolean tried_parent= false;
|
||||
|
||||
boolean system_class=_context.isSystemClass(name);
|
||||
boolean server_class=_context.isServerClass(name) && !Boolean.TRUE.equals(__loadServerClasses.get());
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("loadClass({}) system={} server={} cl={}",name,system_class,server_class,this);
|
||||
Class<?> parent_class = null;
|
||||
Class<?> webapp_class = null;
|
||||
|
||||
ClassLoader source=null;
|
||||
|
||||
if (system_class && server_class)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (c == null && _parent!=null && (_context.isParentLoaderPriority() || system_class) && !server_class)
|
||||
{
|
||||
tried_parent= true;
|
||||
source=_parent;
|
||||
try
|
||||
{
|
||||
c= _parent.loadClass(name);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("loaded " + c);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
ex= e;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
source=this;
|
||||
c= this.findClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
ex= e;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == null && _parent!=null && !tried_parent && !server_class )
|
||||
{
|
||||
tried_parent=true;
|
||||
source=_parent;
|
||||
c= _parent.loadClass(name);
|
||||
}
|
||||
|
||||
if (c == null && ex!=null)
|
||||
// Has this loader loaded the class already?
|
||||
webapp_class = findLoadedClass(name);
|
||||
if (webapp_class != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("!loadedClass({}) from={} tried_parent={}",name,this,tried_parent);
|
||||
LOG.debug("found webapp loaded {}",webapp_class);
|
||||
return webapp_class;
|
||||
}
|
||||
|
||||
// Should we try the parent loader first?
|
||||
if (_context.isParentLoaderPriority())
|
||||
{
|
||||
// Try the parent loader
|
||||
try
|
||||
{
|
||||
parent_class = _parent.loadClass(name);
|
||||
|
||||
// If the webapp is allowed to see this class
|
||||
if (Boolean.TRUE.equals(__loadServerClasses.get()) || !_context.isServerClass(parent_class))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("PLP parent loaded {}",parent_class);
|
||||
return parent_class;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
// Save it for later
|
||||
ex = e;
|
||||
}
|
||||
|
||||
// Try the webapp loader
|
||||
try
|
||||
{
|
||||
// If found here then OK to use regardless of system or server classes
|
||||
// If it is a system class, we've already tried to load from parent, so
|
||||
// would have returned it.
|
||||
// If it is a server class, doesn't matter as we have loaded it from the
|
||||
// webapp
|
||||
webapp_class = this.findClass(name);
|
||||
resolveClass(webapp_class);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("PLP webapp loaded {}",webapp_class);
|
||||
return webapp_class;
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
if (ex==null)
|
||||
ex = e;
|
||||
else
|
||||
ex.addSuppressed(e);
|
||||
}
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("loadedClass({})=={} from={} tried_parent={}",name,c,source,tried_parent);
|
||||
|
||||
if (resolve)
|
||||
else
|
||||
{
|
||||
resolveClass(c);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("resolved({})=={} from={} tried_parent={}",name,c,source,tried_parent);
|
||||
}
|
||||
// Not parent loader priority, so...
|
||||
|
||||
return c;
|
||||
// Try the webapp classloader first
|
||||
// Look in the webapp classloader as a resource, to avoid
|
||||
// loading a system class.
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
URL webapp_url = findResource(path);
|
||||
|
||||
if (webapp_url!=null && !_context.isSystemResource(name,webapp_url))
|
||||
{
|
||||
webapp_class = this.foundClass(name,webapp_url);
|
||||
resolveClass(webapp_class);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("WAP webapp loaded {}",webapp_class);
|
||||
return webapp_class;
|
||||
}
|
||||
|
||||
// Try the parent loader
|
||||
try
|
||||
{
|
||||
parent_class = _parent.loadClass(name);
|
||||
|
||||
// If the webapp is allowed to see this class
|
||||
if (Boolean.TRUE.equals(__loadServerClasses.get()) || !_context.isServerClass(parent_class))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("WAP parent loaded {}",parent_class);
|
||||
return parent_class;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
ex=e;
|
||||
}
|
||||
|
||||
// We couldn't find a parent class, so OK to return a webapp one if it exists
|
||||
// and we just couldn't see it before
|
||||
if (webapp_url!=null)
|
||||
{
|
||||
webapp_class = this.foundClass(name,webapp_url);
|
||||
resolveClass(webapp_class);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("WAP !server webapp loaded {}",webapp_class);
|
||||
return webapp_class;
|
||||
}
|
||||
|
||||
throw ex==null?new ClassNotFoundException(name):ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,69 +626,71 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
{
|
||||
return _transformers.remove(transformer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected Class<?> findClass(final String name) throws ClassNotFoundException
|
||||
{
|
||||
Class<?> clazz=null;
|
||||
|
||||
if (_transformers.isEmpty())
|
||||
clazz = super.findClass(name);
|
||||
else
|
||||
return super.findClass(name);
|
||||
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
URL url = findResource(path);
|
||||
if (url==null)
|
||||
throw new ClassNotFoundException(name);
|
||||
return foundClass(name,url);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Class<?> foundClass(final String name, URL url) throws ClassNotFoundException
|
||||
{
|
||||
if (_transformers.isEmpty())
|
||||
return super.findClass(name);
|
||||
|
||||
InputStream content=null;
|
||||
try
|
||||
{
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
URL url = getResource(path);
|
||||
if (url==null)
|
||||
throw new ClassNotFoundException(name);
|
||||
content = url.openStream();
|
||||
byte[] bytes = IO.readBytes(content);
|
||||
|
||||
InputStream content=null;
|
||||
try
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("foundClass({}) url={} cl={}",name,url,this);
|
||||
|
||||
for (ClassFileTransformer transformer : _transformers)
|
||||
{
|
||||
content = url.openStream();
|
||||
byte[] bytes = IO.readBytes(content);
|
||||
byte[] tmp = transformer.transform(this,name,null,null,bytes);
|
||||
if (tmp != null)
|
||||
bytes = tmp;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("foundClass({}) url={} cl={}",name,url,this);
|
||||
|
||||
for (ClassFileTransformer transformer : _transformers)
|
||||
return defineClass(name,bytes,0,bytes.length);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
catch (IllegalClassFormatException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (content!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] tmp = transformer.transform(this,name,null,null,bytes);
|
||||
if (tmp != null)
|
||||
bytes = tmp;
|
||||
content.close();
|
||||
}
|
||||
|
||||
clazz=defineClass(name,bytes,0,bytes.length);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
catch (IllegalClassFormatException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (content!=null)
|
||||
catch (IOException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
content.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
throw new ClassNotFoundException(name,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
|
@ -639,4 +703,5 @@ public class WebAppClassLoader extends URLClassLoader
|
|||
{
|
||||
return "WebAppClassLoader=" + _name+"@"+Long.toHexString(hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.security.PermissionCollection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
|
@ -63,6 +64,7 @@ import org.eclipse.jetty.servlet.ServletHandler;
|
|||
import org.eclipse.jetty.util.AttributesMap;
|
||||
import org.eclipse.jetty.util.MultiException;
|
||||
import org.eclipse.jetty.util.TopologicalSort;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
|
@ -155,7 +157,7 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
|
|||
@ManagedObject("Web Application ContextHandler")
|
||||
public class WebAppContext extends ServletContextHandler implements WebAppClassLoader.Context
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebAppContext.class);
|
||||
static final Logger LOG = Log.getLogger(WebAppContext.class);
|
||||
|
||||
public static final String TEMPDIR = "javax.servlet.context.tempdir";
|
||||
public static final String BASETEMPDIR = "org.eclipse.jetty.webapp.basetempdir";
|
||||
|
@ -177,6 +179,23 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
"org.w3c." // javax.xml
|
||||
) ;
|
||||
|
||||
// Find the location of the JVM lib directory
|
||||
public final static String __jvmlib;
|
||||
static
|
||||
{
|
||||
String lib=null;
|
||||
try
|
||||
{
|
||||
lib=TypeUtil.getLoadedFrom(System.class).getFile().getParentFile().toURI().toString();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
lib=null;
|
||||
}
|
||||
__jvmlib=lib;
|
||||
}
|
||||
|
||||
// Server classes are classes that are hidden from being
|
||||
// loaded by the web application using system classloader,
|
||||
// so if web application needs to load any of such classes,
|
||||
|
@ -476,15 +495,15 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
// Add the known server class inclusions for all known configurations
|
||||
for (Configuration configuration : Configurations.getKnown())
|
||||
_serverClasses.addInclusions(configuration.getServerClasses());
|
||||
_serverClasses.include(configuration.getServerClasses().getInclusions());
|
||||
|
||||
// Setup Configuration classes for this webapp!
|
||||
loadConfigurations();
|
||||
_configurations.sort();
|
||||
for (Configuration configuration:_configurations)
|
||||
{
|
||||
_systemClasses.add(configuration.getSystemClasses());
|
||||
_serverClasses.addExclusions(configuration.getServerClasses());
|
||||
_systemClasses.add(configuration.getSystemClasses().getPatterns());
|
||||
_serverClasses.exclude(configuration.getServerClasses().getExclusions());
|
||||
}
|
||||
|
||||
// Configure classloader
|
||||
|
@ -679,17 +698,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return _permissions;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see #setServerClasses(String[])
|
||||
* @return Returns the serverClasses.
|
||||
*/
|
||||
@ManagedAttribute(value="classes and packages hidden by the context classloader", readonly=true)
|
||||
public String[] getServerClasses()
|
||||
{
|
||||
return _serverClasses.toArray();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the server classes patterns.
|
||||
|
@ -703,7 +711,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public void setServerClasspathPattern(ClasspathPattern serverClasses)
|
||||
{
|
||||
_serverClasses.clear();
|
||||
_serverClasses.add(serverClasses);
|
||||
_serverClasses.add(serverClasses.getPatterns());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -718,122 +726,98 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
public void setSystemClasspathPattern(ClasspathPattern systemClasses)
|
||||
{
|
||||
_systemClasses.clear();
|
||||
_systemClasses.add(systemClasses);
|
||||
_systemClasses.add(systemClasses.getPatterns());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addServerClasspathPattern(ClasspathPattern serverClasses)
|
||||
{
|
||||
_serverClasses.add(serverClasses);
|
||||
_serverClasses.add(serverClasses.getPatterns());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addSystemClasspathPattern(ClasspathPattern systemClasses)
|
||||
{
|
||||
_serverClasses.add(systemClasses);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ClasspathPattern getServerClasspathPattern()
|
||||
{
|
||||
return _serverClasses;
|
||||
_serverClasses.add(systemClasses.getPatterns());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return The ClasspathPattern used to match System (protected) classes
|
||||
*/
|
||||
public ClasspathPattern getSystemClasspathPattern()
|
||||
{
|
||||
return _systemClasses;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add to the list of Server classes.
|
||||
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
|
||||
* or a qualified package name ending with '.' (eg com.foo.). If the class
|
||||
* or package has '-' it is excluded from the server classes. This argument
|
||||
* may also be a comma separated list of classOrPackage patterns.
|
||||
* @deprecated use {@link #addServerClasspathPattern(ClasspathPattern)}
|
||||
* @see #setServerClasses(String[])
|
||||
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
|
||||
/**
|
||||
* @return The ClasspathPattern used to match Server (hidden) classes
|
||||
*/
|
||||
public void addServerClass(String classOrPackage)
|
||||
public ClasspathPattern getServerClasspathPattern()
|
||||
{
|
||||
_serverClasses.add(classOrPackage);
|
||||
return _serverClasses;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Prepend to the list of Server classes.
|
||||
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
|
||||
* or a qualified package name ending with '.' (eg com.foo.). If the class
|
||||
* or package has '-' it is excluded from the server classes. This argument may also be a comma
|
||||
* separated list of classOrPackage patterns.
|
||||
* @deprecated use {@link #addServerClasspathPattern(ClasspathPattern)}
|
||||
* @see #setServerClasses(String[])
|
||||
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
|
||||
*/
|
||||
public void prependServerClass(String classOrPackage)
|
||||
@ManagedAttribute(value="classes and packages protected by context classloader", readonly=true)
|
||||
public String[] getSystemClasses()
|
||||
{
|
||||
addServerClass(classOrPackage);
|
||||
return _systemClasses.getPatterns();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated use {@link #getSystemClasspathPattern()}.
|
||||
* @see #setSystemClasses(String[])
|
||||
* @return Returns the systemClasses.
|
||||
* @see #setServerClasses(String[])
|
||||
* @return Returns the serverClasses.
|
||||
*/
|
||||
@ManagedAttribute(value="classes and packages given priority by context classloader", readonly=true)
|
||||
public String[] getSystemClasses()
|
||||
@ManagedAttribute(value="classes and packages hidden by the context classloader", readonly=true)
|
||||
public String[] getServerClasses()
|
||||
{
|
||||
return _systemClasses.toArray();
|
||||
return _serverClasses.getPatterns();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean isServerClass(Class<?> clazz)
|
||||
{
|
||||
boolean result = _serverClasses.match(clazz);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("isServerClass=={} {}",result,clazz);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add to the list of System classes.
|
||||
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
|
||||
* or a qualified package name ending with '.' (eg com.foo.). If the class
|
||||
* or package has '-' it is excluded from the system classes.
|
||||
* This argument may also be a comma
|
||||
* separated list of classOrPackage patterns.
|
||||
* @deprecated use {@link #addSystemClasspathPattern(ClasspathPattern)}
|
||||
* @see #setSystemClasses(String[])
|
||||
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
|
||||
*/
|
||||
public void addSystemClass(String classOrPackage)
|
||||
@Override
|
||||
public boolean isSystemClass(Class<?> clazz)
|
||||
{
|
||||
_systemClasses.add(classOrPackage);
|
||||
boolean result = _systemClasses.match(clazz);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("isSystemClass=={} {}",result,clazz);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Prepend to the list of System classes.
|
||||
* @param classOrPackage A fully qualified class name (eg com.foo.MyClass)
|
||||
* or a qualified package name ending with '.' (eg com.foo.). If the class
|
||||
* or package has '-' it is excluded from the system classes.
|
||||
* This argument may also be a comma
|
||||
* separated list of classOrPackage patterns.
|
||||
* @deprecated use {@link #addSystemClasspathPattern(ClasspathPattern)}
|
||||
* @see #setSystemClasses(String[])
|
||||
* @see <a href="http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html">Jetty Documentation: Classloading</a>
|
||||
*/
|
||||
public void prependSystemClass(String classOrPackage)
|
||||
@Override
|
||||
public boolean isServerResource(String name, URL url)
|
||||
{
|
||||
_systemClasses.add(classOrPackage);
|
||||
boolean result = _serverClasses.match(name,url);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("isServerResource=={} {} {}",result,name,url);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean isServerClass(String name)
|
||||
public boolean isSystemResource(String name, URL url)
|
||||
{
|
||||
return _serverClasses.match(name);
|
||||
boolean result = _systemClasses.match(name,url);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("isSystemResource=={} {} {}",result,name,url);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean isSystemClass(String name)
|
||||
{
|
||||
return _systemClasses.match(name);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void setServer(Server server)
|
||||
|
@ -847,7 +831,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (systemClasses instanceof String[])
|
||||
systemClasses = new ClasspathPattern((String[])systemClasses);
|
||||
if (systemClasses instanceof ClasspathPattern)
|
||||
_systemClasses.add((ClasspathPattern)systemClasses);
|
||||
_systemClasses.add(((ClasspathPattern)systemClasses).getPatterns());
|
||||
}
|
||||
|
||||
if (_serverClasses.isEmpty())
|
||||
|
@ -856,7 +840,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
if (serverClasses instanceof String[])
|
||||
serverClasses = new ClasspathPattern((String[])serverClasses);
|
||||
if (serverClasses instanceof ClasspathPattern)
|
||||
_systemClasses.add((ClasspathPattern)serverClasses);
|
||||
_systemClasses.add(((ClasspathPattern)serverClasses).getPatterns());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -969,10 +953,24 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
List<String> system_classes=null;
|
||||
if (_systemClasses!=null)
|
||||
{
|
||||
system_classes=new ArrayList<>(_systemClasses);
|
||||
Collections.sort(system_classes);
|
||||
}
|
||||
|
||||
List<String> server_classes=null;
|
||||
if (_serverClasses!=null)
|
||||
{
|
||||
server_classes=new ArrayList<>(_serverClasses);
|
||||
Collections.sort(server_classes);
|
||||
}
|
||||
|
||||
dumpBeans(out,indent,
|
||||
Collections.singletonList(new ClassLoaderDump(getClassLoader())),
|
||||
Collections.singletonList(new DumpableCollection("Systemclasses "+this,_systemClasses==null?Collections.emptyList():_systemClasses.getPatterns())),
|
||||
Collections.singletonList(new DumpableCollection("Serverclasses "+this,_serverClasses==null?Collections.emptyList():_serverClasses.getPatterns())),
|
||||
Collections.singletonList(new DumpableCollection("Systemclasses "+this,system_classes)),
|
||||
Collections.singletonList(new DumpableCollection("Serverclasses "+this,server_classes)),
|
||||
Collections.singletonList(new DumpableCollection("Configurations "+this,_configurations.getConfigurations())),
|
||||
Collections.singletonList(new DumpableCollection("Handler attributes "+this,((AttributesMap)getAttributes()).getAttributeEntrySet())),
|
||||
Collections.singletonList(new DumpableCollection("Context attributes "+this,((Context)getServletContext()).getAttributeEntrySet())),
|
||||
|
@ -1497,7 +1495,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
//not one of the standard servlet listeners, check our extended session listener types
|
||||
boolean ok = false;
|
||||
for (Class l:SessionHandler.SESSION_LISTENER_TYPES)
|
||||
for (Class<?> l:SessionHandler.SESSION_LISTENER_TYPES)
|
||||
{
|
||||
if (l.isAssignableFrom(listener))
|
||||
{
|
||||
|
@ -1525,11 +1523,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
for (int i=resources.length;i-->0;)
|
||||
{
|
||||
if (resources[i].getName().startsWith("jar:file"))
|
||||
return resources[i].getURL();
|
||||
return resources[i].getURI().toURL();
|
||||
}
|
||||
}
|
||||
|
||||
return resource.getURL();
|
||||
return resource.getURI().toURL();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -1555,7 +1553,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return servletContext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -1564,4 +1561,52 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
return _metadata;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static void addServerClasses(Server server,String... pattern )
|
||||
{
|
||||
// look for a Server attribute with the list of Server classes
|
||||
// to apply to every web application. If not present, use our defaults.
|
||||
Object o = server.getAttribute(SERVER_SRV_CLASSES);
|
||||
|
||||
if (o instanceof ClasspathPattern)
|
||||
{
|
||||
((ClasspathPattern)o).add(pattern);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] server_classes;
|
||||
if (o instanceof String[])
|
||||
server_classes = (String[])o;
|
||||
else
|
||||
server_classes = __dftServerClasses.getPatterns();
|
||||
int l = server_classes.length;
|
||||
server_classes = Arrays.copyOf(server_classes,l+pattern.length);
|
||||
System.arraycopy(pattern,0,server_classes,l,pattern.length);
|
||||
server.setAttribute(SERVER_SRV_CLASSES,server_classes);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static void addSystemClasses(Server server,String... pattern )
|
||||
{
|
||||
// look for a Server attribute with the list of System classes
|
||||
// to apply to every web application. If not present, use our defaults.
|
||||
Object o = server.getAttribute(SERVER_SYS_CLASSES);
|
||||
|
||||
if (o instanceof ClasspathPattern)
|
||||
{
|
||||
((ClasspathPattern)o).add(pattern);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] system_classes;
|
||||
if (o instanceof String[])
|
||||
system_classes = (String[])o;
|
||||
else
|
||||
system_classes = __dftSystemClasses.getPatterns();
|
||||
int l = system_classes.length;
|
||||
system_classes = Arrays.copyOf(system_classes,l+pattern.length);
|
||||
System.arraycopy(pattern,0,system_classes,l,pattern.length);
|
||||
server.setAttribute(SERVER_SYS_CLASSES,system_classes);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,77 +18,214 @@
|
|||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.JDK;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sun.security.provider.Sun;
|
||||
|
||||
public class ClasspathPatternTest
|
||||
{
|
||||
private ClasspathPattern pattern = new ClasspathPattern();
|
||||
private final ClasspathPattern _pattern = new ClasspathPattern();
|
||||
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
pattern = new ClasspathPattern();
|
||||
pattern.add("org.package.");
|
||||
pattern.add("-org.excluded.");
|
||||
pattern.add("org.example.FooBar");
|
||||
pattern.add("-org.example.Excluded");
|
||||
pattern.add("-org.example.Nested$Minus","org.example.Nested","org.example.Nested$Something");
|
||||
_pattern.clear();
|
||||
_pattern.add("org.package.");
|
||||
_pattern.add("-org.excluded.");
|
||||
_pattern.add("org.example.FooBar");
|
||||
_pattern.add("-org.example.Excluded");
|
||||
_pattern.addAll(Arrays.asList(new String[]{
|
||||
"-org.example.Nested$Minus",
|
||||
"org.example.Nested",
|
||||
"org.example.Nested$Something"}));
|
||||
|
||||
|
||||
assertThat(_pattern,containsInAnyOrder(
|
||||
"org.package.",
|
||||
"-org.excluded.",
|
||||
"org.example.FooBar",
|
||||
"-org.example.Excluded",
|
||||
"-org.example.Nested$Minus",
|
||||
"org.example.Nested",
|
||||
"org.example.Nested$Something"
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testClassMatch()
|
||||
{
|
||||
assertTrue(pattern.match("org.example.FooBar"));
|
||||
assertTrue(pattern.match("org.example.Nested"));
|
||||
assertTrue(_pattern.match("org.example.FooBar"));
|
||||
assertTrue(_pattern.match("org.example.Nested"));
|
||||
|
||||
assertFalse(pattern.match("org.example.Unknown"));
|
||||
assertFalse(pattern.match("org.example.FooBar.Unknown"));
|
||||
assertFalse(_pattern.match("org.example.Unknown"));
|
||||
assertFalse(_pattern.match("org.example.FooBar.Unknown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageMatch()
|
||||
{
|
||||
assertTrue(pattern.match("org.package.Something"));
|
||||
assertTrue(pattern.match("org.package.other.Something"));
|
||||
assertTrue(_pattern.match("org.package.Something"));
|
||||
assertTrue(_pattern.match("org.package.other.Something"));
|
||||
|
||||
assertFalse(pattern.match("org.example.Unknown"));
|
||||
assertFalse(pattern.match("org.example.FooBar.Unknown"));
|
||||
assertFalse(pattern.match("org.example.FooBarElse"));
|
||||
assertFalse(_pattern.match("org.example.Unknown"));
|
||||
assertFalse(_pattern.match("org.example.FooBar.Unknown"));
|
||||
assertFalse(_pattern.match("org.example.FooBarElse"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitNestedMatch()
|
||||
{
|
||||
assertTrue(pattern.match("org.example.Nested$Something"));
|
||||
assertFalse(pattern.match("org.example.Nested$Minus"));
|
||||
assertTrue(pattern.match("org.example.Nested$Other"));
|
||||
assertTrue(_pattern.match("org.example.Nested$Something"));
|
||||
assertFalse(_pattern.match("org.example.Nested$Minus"));
|
||||
assertTrue(_pattern.match("org.example.Nested$Other"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitNestedMatch()
|
||||
{
|
||||
assertTrue(pattern.match("org.example.FooBar$Other"));
|
||||
assertTrue(pattern.match("org.example.Nested$Other"));
|
||||
assertTrue(_pattern.match("org.example.FooBar$Other"));
|
||||
assertTrue(_pattern.match("org.example.Nested$Other"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubledNested()
|
||||
{
|
||||
assertTrue(pattern.match("org.example.Nested$Something$Else"));
|
||||
assertTrue(_pattern.match("org.example.Nested$Something$Else"));
|
||||
|
||||
assertFalse(pattern.match("org.example.Nested$Minus$Else"));
|
||||
assertFalse(_pattern.match("org.example.Nested$Minus$Else"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAll()
|
||||
{
|
||||
pattern.clear();
|
||||
pattern.add(".");
|
||||
assertTrue(pattern.match("org.example.Anything"));
|
||||
assertTrue(pattern.match("org.example.Anything$Else"));
|
||||
_pattern.clear();
|
||||
_pattern.add(".");
|
||||
assertTrue(_pattern.match("org.example.Anything"));
|
||||
assertTrue(_pattern.match("org.example.Anything$Else"));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
@Test
|
||||
public void testiIncludedLocations() throws Exception
|
||||
{
|
||||
// jar from JVM classloader
|
||||
Resource loc_string = TypeUtil.getLoadedFrom(String.class);
|
||||
// System.err.println(loc_string);
|
||||
|
||||
// another jar from JVM classloader
|
||||
Resource loc_jsse = TypeUtil.getLoadedFrom(Sun.class);
|
||||
// System.err.println(loc_jsse);
|
||||
|
||||
// a jar from maven repo jar
|
||||
Resource loc_junit = TypeUtil.getLoadedFrom(Test.class);
|
||||
// System.err.println(loc_junit);
|
||||
|
||||
// a jar from another maven repo jar
|
||||
Resource loc_tool = TypeUtil.getLoadedFrom(JDK.class);
|
||||
// System.err.println(loc_tool);
|
||||
|
||||
// class file
|
||||
Resource loc_test = TypeUtil.getLoadedFrom(ClasspathPatternTest.class);
|
||||
// System.err.println(loc_test);
|
||||
|
||||
ClasspathPattern pattern = new ClasspathPattern();
|
||||
pattern.include("something");
|
||||
assertThat(pattern.match(String.class),is(false));
|
||||
assertThat(pattern.match(Sun.class),is(false));
|
||||
assertThat(pattern.match(Test.class),is(false));
|
||||
assertThat(pattern.match(JDK.class),is(false));
|
||||
assertThat(pattern.match(ClasspathPatternTest.class),is(false));
|
||||
|
||||
// Add directory for both JVM classes
|
||||
pattern.include(loc_string.getFile().getParentFile().toURI().toString());
|
||||
|
||||
// Add jar for individual class and classes directory
|
||||
pattern.include(loc_junit.toString(),loc_test.toString());
|
||||
|
||||
assertThat(pattern.match(String.class),is(true));
|
||||
assertThat(pattern.match(Sun.class),is(true));
|
||||
assertThat(pattern.match(Test.class),is(true));
|
||||
assertThat(pattern.match(JDK.class),is(false));
|
||||
assertThat(pattern.match(ClasspathPatternTest.class),is(true));
|
||||
|
||||
// exclude by package name still works
|
||||
pattern.add("-sun.security.provider.Sun");
|
||||
assertThat(pattern.match(String.class),is(true));
|
||||
assertThat(pattern.match(Sun.class),is(false));
|
||||
assertThat(pattern.match(Test.class),is(true));
|
||||
assertThat(pattern.match(JDK.class),is(false));
|
||||
assertThat(pattern.match(ClasspathPatternTest.class),is(true));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
@Test
|
||||
public void testExcludeLocations() throws Exception
|
||||
{
|
||||
// jar from JVM classloader
|
||||
Resource loc_string = TypeUtil.getLoadedFrom(String.class);
|
||||
// System.err.println(loc_string);
|
||||
|
||||
// another jar from JVM classloader
|
||||
Resource loc_jsse = TypeUtil.getLoadedFrom(Sun.class);
|
||||
// System.err.println(loc_jsse);
|
||||
|
||||
// a jar from maven repo jar
|
||||
Resource loc_junit = TypeUtil.getLoadedFrom(Test.class);
|
||||
// System.err.println(loc_junit);
|
||||
|
||||
// a jar from another maven repo jar
|
||||
Resource loc_tool = TypeUtil.getLoadedFrom(JDK.class);
|
||||
// System.err.println(loc_tool);
|
||||
|
||||
// class file
|
||||
Resource loc_test = TypeUtil.getLoadedFrom(ClasspathPatternTest.class);
|
||||
// System.err.println(loc_test);
|
||||
|
||||
ClasspathPattern pattern = new ClasspathPattern();
|
||||
|
||||
// include everything
|
||||
pattern.include(".");
|
||||
|
||||
assertThat(pattern.match(String.class),is(true));
|
||||
assertThat(pattern.match(Sun.class),is(true));
|
||||
assertThat(pattern.match(Test.class),is(true));
|
||||
assertThat(pattern.match(JDK.class),is(true));
|
||||
assertThat(pattern.match(ClasspathPatternTest.class),is(true));
|
||||
|
||||
// Add directory for both JVM classes
|
||||
pattern.exclude(loc_string.getFile().getParentFile().toURI().toString());
|
||||
|
||||
// Add jar for individual class and classes directory
|
||||
pattern.exclude(loc_junit.toString(),loc_test.toString());
|
||||
|
||||
assertThat(pattern.match(String.class),is(false));
|
||||
assertThat(pattern.match(Sun.class),is(false));
|
||||
assertThat(pattern.match(Test.class),is(false));
|
||||
assertThat(pattern.match(JDK.class),is(true));
|
||||
assertThat(pattern.match(ClasspathPatternTest.class),is(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ import java.lang.instrument.ClassFileTransformer;
|
|||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
@ -67,6 +67,8 @@ public class WebAppClassLoaderTest
|
|||
_loader.addJars(webapp.addPath("WEB-INF/lib"));
|
||||
_loader.addClassPath(webapp.addPath("WEB-INF/classes"));
|
||||
_loader.setName("test");
|
||||
|
||||
_context.setServer(new Server());
|
||||
}
|
||||
|
||||
public void assertCanLoadClass(String clazz) throws ClassNotFoundException
|
||||
|
@ -286,7 +288,7 @@ public class WebAppClassLoaderTest
|
|||
URL targetTestClasses = this.getClass().getClassLoader().getResource("org/acme/resource.txt");
|
||||
|
||||
_context.setParentLoaderPriority(false);
|
||||
dump(_context);
|
||||
|
||||
resources =Collections.list(_loader.getResources("org/acme/resource.txt"));
|
||||
|
||||
expected.clear();
|
||||
|
@ -296,12 +298,6 @@ public class WebAppClassLoaderTest
|
|||
|
||||
assertThat("Resources Found (Parent Loader Priority == false)",resources,ordered(expected));
|
||||
|
||||
// dump(resources);
|
||||
// assertEquals(3,resources.size());
|
||||
// assertEquals(0,resources.get(0).toString().indexOf("jar:file:"));
|
||||
// assertEquals(-1,resources.get(1).toString().indexOf("test-classes"));
|
||||
// assertEquals(0,resources.get(2).toString().indexOf("file:"));
|
||||
|
||||
_context.setParentLoaderPriority(true);
|
||||
// dump(_context);
|
||||
resources =Collections.list(_loader.getResources("org/acme/resource.txt"));
|
||||
|
@ -356,49 +352,6 @@ public class WebAppClassLoaderTest
|
|||
|
||||
assertThat("Resources Found (Parent Loader Priority == true) (with systemClasses filtering)",resources,ordered(expected));
|
||||
|
||||
// dump(resources);
|
||||
// assertEquals(1,resources.size());
|
||||
// assertEquals(0,resources.get(0).toString().indexOf("file:"));
|
||||
}
|
||||
|
||||
private void dump(WebAppContext wac)
|
||||
{
|
||||
System.err.println("--Dump WebAppContext - " + wac);
|
||||
System.err.printf(" context.getClass().getClassLoader() = %s%n",wac.getClass().getClassLoader());
|
||||
dumpClassLoaderHierarchy(" ",wac.getClass().getClassLoader());
|
||||
System.err.printf(" context.getClassLoader() = %s%n",wac.getClassLoader());
|
||||
dumpClassLoaderHierarchy(" ",wac.getClassLoader());
|
||||
}
|
||||
|
||||
private void dumpClassLoaderHierarchy(String indent, ClassLoader classLoader)
|
||||
{
|
||||
if (classLoader != null)
|
||||
{
|
||||
if(classLoader instanceof URLClassLoader)
|
||||
{
|
||||
URLClassLoader urlCL = (URLClassLoader)classLoader;
|
||||
URL urls[] = urlCL.getURLs();
|
||||
for (URL url : urls)
|
||||
{
|
||||
System.err.printf("%s url[] = %s%n",indent,url);
|
||||
}
|
||||
}
|
||||
|
||||
ClassLoader parent = classLoader.getParent();
|
||||
if (parent != null)
|
||||
{
|
||||
System.err.printf("%s .parent = %s%n",indent,parent);
|
||||
dumpClassLoaderHierarchy(indent + " ",parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dump(List<URL> resources)
|
||||
{
|
||||
System.err.println("--Dump--");
|
||||
for(URL url: resources)
|
||||
{
|
||||
System.err.printf(" \"%s\"%n",url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue