416597 Allow classes and jars on the webappcontext extraclasspath to be scanned for annotations
This commit is contained in:
parent
edaa23b21e
commit
b8a4bf37e6
|
@ -24,6 +24,7 @@ import java.util.EventListener;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.annotation.HandlesTypes;
|
||||
|
@ -59,6 +60,81 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preConfigure(final WebAppContext context) throws Exception
|
||||
{
|
||||
|
@ -351,25 +427,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
}
|
||||
|
||||
parser.parse (containerUris.toArray(new URI[containerUris.size()]),
|
||||
new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return false;
|
||||
if (context.isServerClass(name)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at system classpath
|
||||
if (context.isParentLoaderPriority())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
new ContainerClassNameResolver (context));
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,24 +485,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
parser.registerHandlers(_discoverableAnnotationHandlers);
|
||||
}
|
||||
|
||||
parser.parse(uri,
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
parser.parse(uri, new WebAppClassNameResolver(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,11 +501,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
throws Exception
|
||||
{
|
||||
LOG.debug("Scanning classes in WEB-INF/classes");
|
||||
if (context.getWebInf() != null)
|
||||
{
|
||||
Resource classesDir = context.getWebInf().addPath("classes/");
|
||||
if (classesDir.exists())
|
||||
{
|
||||
|
||||
parser.clearHandlers();
|
||||
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
|
||||
{
|
||||
|
@ -475,24 +512,9 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
|||
parser.registerHandler(_classInheritanceHandler);
|
||||
parser.registerHandlers(_containerInitializerAnnotationHandlers);
|
||||
|
||||
parser.parseDir(classesDir,
|
||||
new ClassNameResolver()
|
||||
for (Resource dir : context.getMetaData().getWebInfClassesDirs())
|
||||
{
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
parser.parseDir(dir, new WebAppClassNameResolver(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -860,7 +860,7 @@ public class AnnotationParser
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse a particular resource
|
||||
* Parse a particular uri
|
||||
* @param uri
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
|
@ -871,7 +871,24 @@ public class AnnotationParser
|
|||
if (uri == null)
|
||||
return;
|
||||
|
||||
Resource r = Resource.newResource(uri);
|
||||
parse (Resource.newResource(uri), resolver);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a resource
|
||||
* @param r
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
*/
|
||||
public void parse (Resource r, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (r == null)
|
||||
return;
|
||||
|
||||
if (r.exists() && r.isDirectory())
|
||||
{
|
||||
parseDir(r, resolver);
|
||||
|
@ -891,11 +908,10 @@ public class AnnotationParser
|
|||
return;
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) LOG.warn("Resource not scannable for classes: {}", uri);
|
||||
if (LOG.isDebugEnabled()) LOG.warn("Resource not scannable for classes: {}", r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parse a resource that is a jar file.
|
||||
*
|
||||
|
@ -910,7 +926,6 @@ public class AnnotationParser
|
|||
return;
|
||||
|
||||
URI uri = jarResource.getURI();
|
||||
|
||||
if (jarResource.toString().endsWith(".jar"))
|
||||
{
|
||||
if (LOG.isDebugEnabled()) {LOG.debug("Scanning jar {}", jarResource);};
|
||||
|
@ -1037,7 +1052,6 @@ public class AnnotationParser
|
|||
if (path == null || path.length()==0)
|
||||
return false;
|
||||
|
||||
|
||||
//skip any classfiles that are in a hidden directory
|
||||
if (path.startsWith(".") || path.contains("/."))
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@ public class MetaData
|
|||
protected final Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
|
||||
protected final Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
|
||||
protected final Map<Resource, List<DiscoveredAnnotation>> _webFragmentAnnotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
|
||||
protected final List<Resource> _webInfClasses = new ArrayList<Resource>();
|
||||
protected final List<Resource> _webInfJars = new ArrayList<Resource>();
|
||||
protected final List<Resource> _orderedWebInfJars = new ArrayList<Resource>();
|
||||
protected final List<Resource> _orderedContainerResources = new ArrayList<Resource>();
|
||||
|
@ -573,6 +574,17 @@ public class MetaData
|
|||
{
|
||||
_orderedContainerResources.add(jar);
|
||||
}
|
||||
|
||||
public void setWebInfClassesDirs (List<Resource> dirs)
|
||||
{
|
||||
_webInfClasses.addAll(dirs);
|
||||
}
|
||||
|
||||
public List<Resource> getWebInfClassesDirs ()
|
||||
{
|
||||
return _webInfClasses;
|
||||
}
|
||||
|
||||
public boolean isAllowDuplicateFragmentNames()
|
||||
{
|
||||
return allowDuplicateFragmentNames;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.net.URLClassLoader;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -139,6 +140,9 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
}
|
||||
}
|
||||
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
|
||||
|
||||
//No pattern to appy to classes, just add to metadata
|
||||
context.getMetaData().setWebInfClassesDirs(findClassDirs(context));
|
||||
}
|
||||
|
||||
|
||||
|
@ -694,8 +698,29 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
return canonicalName.toString();
|
||||
}
|
||||
|
||||
|
||||
protected List<Resource> findClassDirs (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
if (context == null)
|
||||
return null;
|
||||
|
||||
List<Resource> classDirs = new ArrayList<Resource>();
|
||||
|
||||
Resource webInfClasses = findWebInfClassesDir(context);
|
||||
if (webInfClasses != null)
|
||||
classDirs.add(webInfClasses);
|
||||
List<Resource> extraClassDirs = findExtraClasspathDirs(context);
|
||||
if (extraClassDirs != null)
|
||||
classDirs.addAll(extraClassDirs);
|
||||
|
||||
return classDirs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look for jars in WEB-INF/lib
|
||||
* Look for jars that should be treated as if they are in WEB-INF/lib
|
||||
*
|
||||
* @param context
|
||||
* @return the list of jar resources found within context
|
||||
* @throws Exception
|
||||
|
@ -704,14 +729,31 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
throws Exception
|
||||
{
|
||||
List<Resource> jarResources = new ArrayList<Resource>();
|
||||
List<Resource> webInfLibJars = findWebInfLibJars(context);
|
||||
if (webInfLibJars != null)
|
||||
jarResources.addAll(webInfLibJars);
|
||||
List<Resource> extraClasspathJars = findExtraClasspathJars(context);
|
||||
if (extraClasspathJars != null)
|
||||
jarResources.addAll(extraClasspathJars);
|
||||
return jarResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for jars in WEB-INF/lib
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected List<Resource> findWebInfLibJars(WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
Resource web_inf = context.getWebInf();
|
||||
if (web_inf==null || !web_inf.exists())
|
||||
return null;
|
||||
|
||||
List<Resource> jarResources = new ArrayList<Resource>();
|
||||
Resource web_inf_lib = web_inf.addPath("/lib");
|
||||
|
||||
|
||||
if (web_inf_lib.exists() && web_inf_lib.isDirectory())
|
||||
{
|
||||
String[] files=web_inf_lib.list();
|
||||
|
@ -736,4 +778,90 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
}
|
||||
return jarResources;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get jars from WebAppContext.getExtraClasspath as resources
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected List<Resource> findExtraClasspathJars(WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
if (context == null || context.getExtraClasspath() == null)
|
||||
return null;
|
||||
|
||||
List<Resource> jarResources = new ArrayList<Resource>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(context.getExtraClasspath(), ",;");
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
Resource resource = context.newResource(tokenizer.nextToken().trim());
|
||||
String fnlc = resource.getName().toLowerCase(Locale.ENGLISH);
|
||||
int dot = fnlc.lastIndexOf('.');
|
||||
String extension = (dot < 0 ? null : fnlc.substring(dot));
|
||||
if (extension != null && (extension.equals(".jar") || extension.equals(".zip")))
|
||||
{
|
||||
jarResources.add(resource);
|
||||
}
|
||||
}
|
||||
|
||||
return jarResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WEB-INF/classes dir
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Resource findWebInfClassesDir (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
if (context == null)
|
||||
return null;
|
||||
|
||||
Resource web_inf = context.getWebInf();
|
||||
|
||||
// Find WEB-INF/classes
|
||||
if (web_inf != null && web_inf.isDirectory())
|
||||
{
|
||||
// Look for classes directory
|
||||
Resource classes= web_inf.addPath("classes/");
|
||||
if (classes.exists())
|
||||
return classes;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get class dirs from WebAppContext.getExtraClasspath as resources
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected List<Resource> findExtraClasspathDirs(WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
if (context == null || context.getExtraClasspath() == null)
|
||||
return null;
|
||||
|
||||
List<Resource> dirResources = new ArrayList<Resource>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(context.getExtraClasspath(), ",;");
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
Resource resource = context.newResource(tokenizer.nextToken().trim());
|
||||
if (resource.exists() && resource.isDirectory())
|
||||
dirResources.add(resource);
|
||||
}
|
||||
|
||||
return dirResources;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue