Bring jetty-7 into line with new annotation parsing mechansim from jetty-8
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@575 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
640b20941a
commit
0358f29479
|
@ -0,0 +1,180 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor.Descriptor;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
|
||||
|
||||
public abstract class AbstractConfiguration implements Configuration
|
||||
{
|
||||
public static final String CONTAINER_JAR_RESOURCES = WebInfConfiguration.CONTAINER_JAR_RESOURCES;
|
||||
public static final String WEB_INF_JAR_RESOURCES = WebInfConfiguration.WEB_INF_JAR_RESOURCES;
|
||||
public static final String WEBXML_VERSION = WebXmlProcessor.WEBXML_VERSION;
|
||||
public static final String METADATA_COMPLETE = WebXmlProcessor.METADATA_COMPLETE;
|
||||
public static final String WEBXML_CLASSNAMES = WebXmlProcessor.WEBXML_CLASSNAMES;
|
||||
|
||||
public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
//if no pattern for the container path is defined, then by default scan NOTHING
|
||||
Log.debug("Scanning container jars");
|
||||
|
||||
//Convert from Resource to URI
|
||||
ArrayList<URI> containerUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(CONTAINER_JAR_RESOURCES);
|
||||
for (Resource r : jarResources)
|
||||
{
|
||||
URI uri = r.getURI();
|
||||
containerUris.add(uri);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
WebXmlProcessor webXmlProcessor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.WEB_PROCESSOR);
|
||||
if (webXmlProcessor == null)
|
||||
throw new IllegalStateException ("No processor for web xml");
|
||||
|
||||
List<Descriptor> frags = webXmlProcessor.getFragments();
|
||||
|
||||
//Get the web-inf lib jars who have a web-fragment.xml that is not metadata-complete (or is not set)
|
||||
ArrayList<URI> webInfUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(WEB_INF_JAR_RESOURCES);
|
||||
|
||||
for (Resource r : jarResources)
|
||||
{
|
||||
URI uri = r.getURI();
|
||||
Descriptor d = null;
|
||||
for (Descriptor frag: frags)
|
||||
{
|
||||
Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml
|
||||
if (Resource.isContainedIn(fragResource,r))
|
||||
{
|
||||
d = frag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if there was no web-fragment.xml for the jar, or there was one
|
||||
//and its metadata is NOT complete, we want to exame it for annotations
|
||||
if (d == null || (d != null && !d.isMetaDataComplete()))
|
||||
webInfUris.add(uri);
|
||||
}
|
||||
|
||||
parser.parse(webInfUris.toArray(new URI[webInfUris.size()]),
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
Log.debug("Scanning classes in WEB-INF/classes");
|
||||
parser.parse(context.getWebInf().addPath("classes/"),
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void parse25Classes (final WebAppContext context, final AnnotationParser parser)
|
||||
throws Exception
|
||||
{
|
||||
//only parse servlets, filters and listeners from web.xml
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning only classes from web.xml");
|
||||
ArrayList<String> classNames = (ArrayList<String>)context.getAttribute(WEBXML_CLASSNAMES);
|
||||
for (String s : classNames)
|
||||
{
|
||||
Class clazz = Loader.loadClass(null, s);
|
||||
parser.parse(clazz, 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;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,218 +13,83 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.plus.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.FilterMapping;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AnnotationConfiguration extends org.eclipse.jetty.plus.webapp.Configuration
|
||||
public class AnnotationConfiguration extends AbstractConfiguration
|
||||
{
|
||||
public static final String JAR_RESOURCES = WebInfConfiguration.JAR_RESOURCES;
|
||||
|
||||
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
|
||||
*/
|
||||
public void parseAnnotations(final WebAppContext context) throws Exception
|
||||
public void preConfigure(final WebAppContext context) throws Exception
|
||||
{
|
||||
/*
|
||||
* TODO Need to also take account of hidden classes on system classpath that should never
|
||||
* contribute annotations to a webapp (system and server classes):
|
||||
*
|
||||
* --- when scanning system classpath:
|
||||
* + system classes : should always be scanned (subject to pattern)
|
||||
* + server classes : always ignored
|
||||
*
|
||||
* --- when scanning webapp classpath:
|
||||
* + system classes : always ignored
|
||||
* + server classes : always scanned
|
||||
*
|
||||
*
|
||||
* If same class is found in both container and in context then need to use
|
||||
* webappcontext parentloaderpriority to work out which one contributes the
|
||||
* annotation.
|
||||
*/
|
||||
AnnotationFinder finder = new AnnotationFinder();
|
||||
|
||||
//TODO change for servlet spec 3
|
||||
parseContainerPath (context, finder);
|
||||
parseWebInfLib (context, finder);
|
||||
parseWebInfClasses (context, finder);
|
||||
|
||||
AnnotationProcessor processor = new AnnotationProcessor(context, finder);
|
||||
processor.process();
|
||||
|
||||
List servlets = processor.getServlets();
|
||||
List filters = processor.getFilters();
|
||||
List servletMappings = processor.getServletMappings();
|
||||
List filterMappings = processor.getFilterMappings();
|
||||
List listeners = processor.getListeners();
|
||||
|
||||
ServletHandler servletHandler = (ServletHandler)context.getServletHandler();
|
||||
servletHandler.setFilters((FilterHolder[])LazyList.toArray(filters,FilterHolder.class));
|
||||
servletHandler.setFilterMappings((FilterMapping[])LazyList.toArray(filterMappings,FilterMapping.class));
|
||||
servletHandler.setServlets((ServletHolder[])LazyList.toArray(servlets,ServletHolder.class));
|
||||
servletHandler.setServletMappings((ServletMapping[])LazyList.toArray(servletMappings,ServletMapping.class));
|
||||
context.setEventListeners((EventListener[])LazyList.toArray(listeners,EventListener.class));
|
||||
}
|
||||
|
||||
|
||||
public void parseContainerPath (final WebAppContext context, final AnnotationFinder finder)
|
||||
throws Exception
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
//if no pattern for the container path is defined, then by default scan NOTHING
|
||||
Log.debug("Scanning container jars");
|
||||
|
||||
//Get the container jar uris
|
||||
|
||||
ArrayList<URI> containerCandidateUris = findJars (context.getClassLoader().getParent(), true);
|
||||
|
||||
//Pick out the uris from JAR_RESOURCES that match those uris to be scanned
|
||||
ArrayList<URI> containerUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(JAR_RESOURCES);
|
||||
for (Resource r : jarResources)
|
||||
Boolean b = (Boolean)context.getAttribute(METADATA_COMPLETE);
|
||||
boolean metadataComplete = (b != null && b.booleanValue());
|
||||
Integer i = (Integer)context.getAttribute(WEBXML_VERSION);
|
||||
int webxmlVersion = (i == null? 0 : i.intValue());
|
||||
|
||||
if (metadataComplete)
|
||||
{
|
||||
URI uri = r.getURI();
|
||||
if (containerCandidateUris.contains(uri))
|
||||
{
|
||||
containerUris.add(uri);
|
||||
}
|
||||
|
||||
//Never scan any jars or classes for annotations if metadata is complete
|
||||
if (Log.isDebugEnabled()) Log.debug("Metadata-complete==true, not processing annotations for context "+context);
|
||||
return;
|
||||
}
|
||||
|
||||
finder.find (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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void parseWebInfLib (final WebAppContext context, final AnnotationFinder finder)
|
||||
throws Exception
|
||||
{
|
||||
Log.debug("Scanning WEB-INF/lib jars");
|
||||
//Get the uris of jars on the webapp classloader
|
||||
ArrayList<URI> candidateUris = findJars(context.getClassLoader(), false);
|
||||
|
||||
//Pick out the uris from JAR_RESOURCES that match those to be scanned
|
||||
ArrayList<URI> webInfUris = new ArrayList<URI>();
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(JAR_RESOURCES);
|
||||
for (Resource r : jarResources)
|
||||
else
|
||||
{
|
||||
URI uri = r.getURI();
|
||||
if (candidateUris.contains(uri))
|
||||
{
|
||||
webInfUris.add(uri);
|
||||
}
|
||||
}
|
||||
|
||||
//if no pattern for web-inf/lib is defined, then by default scan everything in it
|
||||
finder.find(webInfUris.toArray(new URI[webInfUris.size()]),
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
//Only scan jars and classes if metadata is not complete and the web app is version 3.0, or
|
||||
//a 2.5 version webapp that has specifically asked to discover annotations
|
||||
if (Log.isDebugEnabled()) Log.debug("parsing annotations");
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void parseWebInfClasses (final WebAppContext context, final AnnotationFinder finder)
|
||||
throws Exception
|
||||
{
|
||||
Log.debug("Scanning classes in WEB-INF/classes");
|
||||
finder.find(context.getWebInf().addPath("classes/"),
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", new ResourceAnnotationHandler (context));
|
||||
parser.registerAnnotationHandler("javax.annotation.Resources", new ResourcesAnnotationHandler (context));
|
||||
parser.registerAnnotationHandler("javax.annotation.PostConstruct", new PostConstructAnnotationHandler(context));
|
||||
parser.registerAnnotationHandler("javax.annotation.PreDestroy", new PreDestroyAnnotationHandler(context));
|
||||
parser.registerAnnotationHandler("javax.annotation.security.RunAs", new RunAsAnnotationHandler(context));
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
ClassInheritanceHandler classHandler = new ClassInheritanceHandler();
|
||||
parser.registerClassHandler(classHandler);
|
||||
|
||||
|
||||
if (webxmlVersion >= 30 || context.isConfigurationDiscovered())
|
||||
{
|
||||
//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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ArrayList<URI> findJars (ClassLoader loader, boolean visitParent)
|
||||
{
|
||||
ArrayList<URI> uris = new ArrayList<URI>();
|
||||
|
||||
while (loader != null && (loader instanceof URLClassLoader))
|
||||
{
|
||||
URL[] urls = ((URLClassLoader)loader).getURLs();
|
||||
if (urls != null)
|
||||
{
|
||||
for (URL u : urls)
|
||||
{
|
||||
try
|
||||
{
|
||||
uris.add(u.toURI());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (visitParent)
|
||||
loader = loader.getParent();
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning all classes for annotations: webxmlVersion="+webxmlVersion+" configurationDiscovered="+context.isConfigurationDiscovered());
|
||||
parseContainerPath(context, parser);
|
||||
parseWebInfLib (context, parser);
|
||||
parseWebInfClasses(context, parser);
|
||||
}
|
||||
else
|
||||
loader = null;
|
||||
}
|
||||
return uris;
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Scanning only classes in web.xml for annotations");
|
||||
parse25Classes(context, parser);
|
||||
}
|
||||
|
||||
//save the type inheritance map created by the parser for later reference
|
||||
context.setAttribute(CLASS_INHERITANCE_MAP, classHandler.getMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,781 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.JarScanner;
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.EmptyVisitor;
|
||||
|
||||
|
||||
/**
|
||||
* AnnotationFinder
|
||||
*
|
||||
*
|
||||
* Scans class sources using asm to find annotations.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AnnotationFinder
|
||||
{
|
||||
private Map<String,ParsedClass> parsedClasses = new HashMap<String, ParsedClass>();
|
||||
|
||||
|
||||
public static String normalize (String name)
|
||||
{
|
||||
if (name==null)
|
||||
return null;
|
||||
|
||||
if (name.startsWith("L") && name.endsWith(";"))
|
||||
name = name.substring(1, name.length()-1);
|
||||
|
||||
if (name.endsWith(".class"))
|
||||
name = name.substring(0, name.length()-".class".length());
|
||||
|
||||
name = name.replace('$', '.');
|
||||
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
public static Class convertType (org.objectweb.asm.Type t)
|
||||
throws Exception
|
||||
{
|
||||
if (t == null)
|
||||
return (Class)null;
|
||||
|
||||
switch (t.getSort())
|
||||
{
|
||||
case Type.BOOLEAN:
|
||||
{
|
||||
return Boolean.TYPE;
|
||||
}
|
||||
case Type.ARRAY:
|
||||
{
|
||||
Class clazz = convertType(t.getElementType());
|
||||
return Array.newInstance(clazz, 0).getClass();
|
||||
}
|
||||
case Type.BYTE:
|
||||
{
|
||||
return Byte.TYPE;
|
||||
}
|
||||
case Type.CHAR:
|
||||
{
|
||||
return Character.TYPE;
|
||||
}
|
||||
case Type.DOUBLE:
|
||||
{
|
||||
return Double.TYPE;
|
||||
}
|
||||
case Type.FLOAT:
|
||||
{
|
||||
return Float.TYPE;
|
||||
}
|
||||
case Type.INT:
|
||||
{
|
||||
return Integer.TYPE;
|
||||
}
|
||||
case Type.LONG:
|
||||
{
|
||||
return Long.TYPE;
|
||||
}
|
||||
case Type.OBJECT:
|
||||
{
|
||||
return (Loader.loadClass(null, t.getClassName()));
|
||||
}
|
||||
case Type.SHORT:
|
||||
{
|
||||
return Short.TYPE;
|
||||
}
|
||||
case Type.VOID:
|
||||
{
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Class[] convertTypes (Type[] types)
|
||||
throws Exception
|
||||
{
|
||||
if (types==null)
|
||||
return new Class[0];
|
||||
|
||||
Class[] classArray = new Class[types.length];
|
||||
|
||||
for (int i=0; i<types.length; i++)
|
||||
{
|
||||
classArray[i] = convertType(types[i]);
|
||||
}
|
||||
return classArray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AnnotatedStructure
|
||||
*
|
||||
* Annotations on an object such as a class, field or method.
|
||||
*/
|
||||
public static class AnnotatedStructure extends EmptyVisitor
|
||||
{
|
||||
Map<String, Map<String, Object>> annotations = new HashMap<String, Map<String,Object>>();
|
||||
|
||||
|
||||
public AnnotationVisitor addAnnotation (final String name)
|
||||
{
|
||||
final HashMap<String,Object> annotationValues = new HashMap<String,Object>();
|
||||
this.annotations.put(normalize(name), annotationValues);
|
||||
return new AnnotationVisitor()
|
||||
{
|
||||
public void visit(String name, Object value)
|
||||
{
|
||||
annotationValues.put(name, value);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc)
|
||||
{
|
||||
return null; //ignore nested annotations
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitArray(String arg0)
|
||||
{
|
||||
return null;//ignore array valued annotations
|
||||
}
|
||||
|
||||
public void visitEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public void visitEnum(String name, String desc, String value)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Map<String, Map<String, Object>> getAnnotations ()
|
||||
{
|
||||
return annotations;
|
||||
}
|
||||
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer strbuff = new StringBuffer();
|
||||
|
||||
for (Map.Entry<String, Map<String,Object>> e: annotations.entrySet())
|
||||
{
|
||||
strbuff.append(e.getKey()+"\n");
|
||||
for (Map.Entry<String,Object> v: e.getValue().entrySet())
|
||||
{
|
||||
strbuff.append("\t"+v.getKey()+"="+v.getValue()+", ");
|
||||
}
|
||||
}
|
||||
return strbuff.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ParsedClass
|
||||
*
|
||||
* A class that contains annotations.
|
||||
*/
|
||||
public static class ParsedClass extends AnnotatedStructure
|
||||
{
|
||||
String className;
|
||||
String superClassName;
|
||||
Class clazz;
|
||||
List<ParsedMethod> methods = new ArrayList<ParsedMethod>();
|
||||
List<ParsedField> fields = new ArrayList<ParsedField>();
|
||||
|
||||
|
||||
public ParsedClass (String className, String superClassName)
|
||||
{
|
||||
this.className = normalize(className);
|
||||
this.superClassName = normalize(superClassName);
|
||||
}
|
||||
|
||||
public String getClassName()
|
||||
{
|
||||
return this.className;
|
||||
}
|
||||
|
||||
public String getSuperClassName ()
|
||||
{
|
||||
return this.superClassName;
|
||||
}
|
||||
|
||||
public Class toClass ()
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
if (clazz==null)
|
||||
clazz = Loader.loadClass(null, className);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public List<ParsedMethod> getMethods ()
|
||||
{
|
||||
return methods;
|
||||
}
|
||||
|
||||
public ParsedMethod getMethod(String name, String paramString)
|
||||
{
|
||||
Iterator<ParsedMethod> itor = methods.iterator();
|
||||
ParsedMethod method = null;
|
||||
while (itor.hasNext() && method==null)
|
||||
{
|
||||
ParsedMethod m = itor.next();
|
||||
if (m.matches(name, paramString))
|
||||
method = m;
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
public void addMethod (ParsedMethod m)
|
||||
{
|
||||
if (getMethod(m.methodName, m.paramString)!= null)
|
||||
return;
|
||||
methods.add(m);
|
||||
}
|
||||
|
||||
public List<ParsedField> getFields()
|
||||
{
|
||||
return fields;
|
||||
}
|
||||
|
||||
public ParsedField getField(String name)
|
||||
{
|
||||
Iterator<ParsedField> itor = fields.iterator();
|
||||
ParsedField field = null;
|
||||
while (itor.hasNext() && field==null)
|
||||
{
|
||||
ParsedField f = itor.next();
|
||||
if (f.matches(name))
|
||||
field=f;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
public void addField (ParsedField f)
|
||||
{
|
||||
if (getField(f.fieldName) != null)
|
||||
return;
|
||||
fields.add(f);
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer strbuff = new StringBuffer();
|
||||
strbuff.append(this.className+"\n");
|
||||
strbuff.append("Class annotations\n"+super.toString());
|
||||
strbuff.append("\n");
|
||||
strbuff.append("Method annotations\n");
|
||||
for (ParsedMethod p:methods)
|
||||
strbuff.append(p+"\n");
|
||||
strbuff.append("\n");
|
||||
strbuff.append("Field annotations\n");
|
||||
for (ParsedField f:fields)
|
||||
strbuff.append(f+"\n");
|
||||
strbuff.append("\n");
|
||||
return strbuff.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ParsedMethod
|
||||
*
|
||||
* A class method that can contain annotations.
|
||||
*/
|
||||
public static class ParsedMethod extends AnnotatedStructure
|
||||
{
|
||||
ParsedClass pclass;
|
||||
String methodName;
|
||||
String paramString;
|
||||
Method method;
|
||||
|
||||
|
||||
public ParsedMethod(ParsedClass pclass, String name, String paramString)
|
||||
{
|
||||
this.pclass=pclass;
|
||||
this.methodName=name;
|
||||
this.paramString=paramString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||
{
|
||||
this.pclass.addMethod(this);
|
||||
return addAnnotation(desc);
|
||||
}
|
||||
|
||||
public Method toMethod ()
|
||||
throws Exception
|
||||
{
|
||||
if (method == null)
|
||||
{
|
||||
Type[] types = null;
|
||||
if (paramString!=null)
|
||||
types = Type.getArgumentTypes(paramString);
|
||||
|
||||
Class[] args = convertTypes(types);
|
||||
method = pclass.toClass().getDeclaredMethod(methodName, args);
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
public boolean matches (String name, String paramString)
|
||||
{
|
||||
if (!methodName.equals(name))
|
||||
return false;
|
||||
|
||||
if (this.paramString!=null && this.paramString.equals(paramString))
|
||||
return true;
|
||||
|
||||
return (this.paramString == paramString);
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return pclass.getClassName()+"."+methodName+"\n\t"+super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ParsedField
|
||||
*
|
||||
* A class field that can contain annotations. Also implements the
|
||||
* asm visitor for Annotations.
|
||||
*/
|
||||
public static class ParsedField extends AnnotatedStructure
|
||||
{
|
||||
ParsedClass pclass;
|
||||
String fieldName;
|
||||
Field field;
|
||||
|
||||
public ParsedField (ParsedClass pclass, String name)
|
||||
{
|
||||
this.pclass=pclass;
|
||||
this.fieldName=name;
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||
{
|
||||
this.pclass.addField(this);
|
||||
return addAnnotation(desc);
|
||||
}
|
||||
|
||||
public Field toField ()
|
||||
throws Exception
|
||||
{
|
||||
if (field==null)
|
||||
{
|
||||
field=this.pclass.toClass().getDeclaredField(fieldName);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
public boolean matches (String name)
|
||||
{
|
||||
if (fieldName.equals(name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return pclass.getClassName()+"."+fieldName+"\n\t"+super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MyClassVisitor
|
||||
*
|
||||
* ASM visitor for a class.
|
||||
*/
|
||||
public class MyClassVisitor extends EmptyVisitor
|
||||
{
|
||||
ParsedClass pclass;
|
||||
|
||||
|
||||
public void visit (int version,
|
||||
int access,
|
||||
String name,
|
||||
String signature,
|
||||
String superName,
|
||||
String[] interfaces)
|
||||
{
|
||||
pclass = new ParsedClass(name, superName);
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation (String desc, boolean visible)
|
||||
{
|
||||
if (!parsedClasses.containsKey(pclass.getClassName()))
|
||||
parsedClasses.put(pclass.getClassName(), pclass);
|
||||
|
||||
return pclass.addAnnotation(desc);
|
||||
}
|
||||
|
||||
public MethodVisitor visitMethod (int access,
|
||||
String name,
|
||||
String desc,
|
||||
String signature,
|
||||
String[] exceptions)
|
||||
{
|
||||
if (!parsedClasses.values().contains(pclass))
|
||||
parsedClasses.put(pclass.getClassName(),pclass);
|
||||
|
||||
ParsedMethod method = pclass.getMethod(name, desc);
|
||||
if (method==null)
|
||||
method = new ParsedMethod(pclass, name, desc);
|
||||
return method;
|
||||
}
|
||||
|
||||
public FieldVisitor visitField (int access,
|
||||
String name,
|
||||
String desc,
|
||||
String signature,
|
||||
Object value)
|
||||
{
|
||||
if (!parsedClasses.values().contains(pclass))
|
||||
parsedClasses.put(pclass.getClassName(),pclass);
|
||||
|
||||
ParsedField field = pclass.getField(name);
|
||||
if (field==null)
|
||||
field = new ParsedField(pclass, name);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void find (String className, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (className == null)
|
||||
return;
|
||||
|
||||
if (!resolver.isExcluded(className))
|
||||
{
|
||||
if ((parsedClasses.get(className) == null) || (resolver.shouldOverride(className)))
|
||||
{
|
||||
parsedClasses.remove(className);
|
||||
className = className.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), className, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void find (String[] classNames, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (classNames == null)
|
||||
return;
|
||||
|
||||
find(Arrays.asList(classNames), resolver);
|
||||
}
|
||||
|
||||
public void find (List<String> classNames, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
for (String s:classNames)
|
||||
{
|
||||
if (!resolver.isExcluded(s))
|
||||
{
|
||||
if ((parsedClasses.get(s) == null) || (resolver.shouldOverride(s)))
|
||||
{
|
||||
parsedClasses.remove(s);
|
||||
s = s.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), s, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void find (Resource dir, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (!dir.isDirectory() || !dir.exists())
|
||||
return;
|
||||
|
||||
|
||||
String[] files=dir.list();
|
||||
for (int f=0;files!=null && f<files.length;f++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource res = dir.addPath(files[f]);
|
||||
if (res.isDirectory())
|
||||
find(res, resolver);
|
||||
String name = res.getName();
|
||||
if (name.endsWith(".class"))
|
||||
{
|
||||
if (!resolver.isExcluded(name))
|
||||
{
|
||||
if ((parsedClasses.get(name) == null) || (resolver.shouldOverride(name)))
|
||||
{
|
||||
parsedClasses.remove(name);
|
||||
scanClass(res.getURL().openStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.warn(Log.EXCEPTION,ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find annotations on classes in the supplied classloader.
|
||||
* Only class files in jar files will be scanned.
|
||||
* @param loader
|
||||
* @param visitParents
|
||||
* @param jarNamePattern
|
||||
* @param nullInclusive
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
*/
|
||||
public void find (ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (loader==null)
|
||||
return;
|
||||
|
||||
if (!(loader instanceof URLClassLoader))
|
||||
return; //can't extract classes?
|
||||
|
||||
JarScanner scanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URI jarUri, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
if (!resolver.isExcluded(shortName))
|
||||
{
|
||||
if ((parsedClasses.get(shortName) == null) || (resolver.shouldOverride(shortName)))
|
||||
{
|
||||
parsedClasses.remove(shortName);
|
||||
Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
|
||||
scanClass(clazz.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry "+entry, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
scanner.scan(null, loader, nullInclusive, visitParents);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find annotations in classes in the supplied url of jar files.
|
||||
* @param uris
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
*/
|
||||
public void find (URI[] uris, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (uris==null)
|
||||
return;
|
||||
|
||||
JarScanner scanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URI jarUri, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
if (!resolver.isExcluded(shortName))
|
||||
{
|
||||
if ((parsedClasses.get(shortName) == null) || (resolver.shouldOverride(shortName)))
|
||||
{
|
||||
parsedClasses.remove(shortName);
|
||||
Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
|
||||
scanClass(clazz.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry "+entry, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
scanner.scan(null, uris, true);
|
||||
}
|
||||
|
||||
|
||||
/** Exclude class by name
|
||||
* Instances of {@link AnnotationFinder} can implement this method to exclude
|
||||
* classes by name.
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
protected boolean excludeClass (String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<Class<?>> getClassesForAnnotation(Class<?> annotationClass)
|
||||
throws Exception
|
||||
{
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||
{
|
||||
ParsedClass pc = e.getValue();
|
||||
Map<String, Map<String,Object>> annotations = pc.getAnnotations();
|
||||
for (String key:annotations.keySet())
|
||||
{
|
||||
if (key.equals(annotationClass.getName()))
|
||||
{
|
||||
classes.add(pc.toClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<Method> getMethodsForAnnotation (Class<?> annotationClass)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
List<Method> methods = new ArrayList<Method>();
|
||||
|
||||
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||
{
|
||||
ParsedClass pc = e.getValue();
|
||||
|
||||
List<ParsedMethod> pmethods = pc.getMethods();
|
||||
for (ParsedMethod p:pmethods)
|
||||
{
|
||||
for (String key:p.getAnnotations().keySet())
|
||||
{
|
||||
if (key.equals(annotationClass.getName()))
|
||||
{
|
||||
methods.add(p.toMethod());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List<Field> getFieldsForAnnotation (Class<?> annotation)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
for (Map.Entry<String, ParsedClass> e: parsedClasses.entrySet())
|
||||
{
|
||||
ParsedClass pc = e.getValue();
|
||||
|
||||
List<ParsedField> pfields = pc.getFields();
|
||||
for (ParsedField f:pfields)
|
||||
{
|
||||
for (String key:f.getAnnotations().keySet())
|
||||
{
|
||||
if (key.equals(annotation.getName()))
|
||||
{
|
||||
fields.add(f.toField());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer strbuff = new StringBuffer();
|
||||
for (Map.Entry<String, ParsedClass> e:parsedClasses.entrySet())
|
||||
{
|
||||
strbuff.append(e.getValue());
|
||||
strbuff.append("\n");
|
||||
}
|
||||
return strbuff.toString();
|
||||
}
|
||||
|
||||
|
||||
private void scanClass (InputStream is)
|
||||
throws IOException
|
||||
{
|
||||
ClassReader reader = new ClassReader(is);
|
||||
reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,598 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.JarScanner;
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.commons.EmptyVisitor;
|
||||
|
||||
/**
|
||||
* AnnotationParser
|
||||
*
|
||||
* Use asm to scan classes for annotations. A SAX-style parsing is done, with
|
||||
* a handler being able to be registered to handle each annotation type.
|
||||
*/
|
||||
public class AnnotationParser
|
||||
{
|
||||
protected List<String> _parsedClassNames = new ArrayList<String>();
|
||||
protected Map<String, AnnotationHandler> _annotationHandlers = new HashMap<String, AnnotationHandler>();
|
||||
protected List<ClassHandler> _classHandlers = new ArrayList<ClassHandler>();
|
||||
protected List<MethodHandler> _methodHandlers = new ArrayList<MethodHandler>();
|
||||
protected List<FieldHandler> _fieldHandlers = new ArrayList<FieldHandler>();
|
||||
|
||||
public static String normalize (String name)
|
||||
{
|
||||
if (name==null)
|
||||
return null;
|
||||
|
||||
if (name.startsWith("L") && name.endsWith(";"))
|
||||
name = name.substring(1, name.length()-1);
|
||||
|
||||
if (name.endsWith(".class"))
|
||||
name = name.substring(0, name.length()-".class".length());
|
||||
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public abstract class Value
|
||||
{
|
||||
String _name;
|
||||
|
||||
public Value (String name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public abstract Object getValue();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class SimpleValue extends Value
|
||||
{
|
||||
Object _val;
|
||||
|
||||
public SimpleValue(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void setValue(Object val)
|
||||
{
|
||||
_val=val;
|
||||
}
|
||||
public Object getValue()
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "("+getName()+":"+_val+")";
|
||||
}
|
||||
}
|
||||
|
||||
public class ListValue extends Value
|
||||
{
|
||||
List<Value> _val;
|
||||
|
||||
public ListValue (String name)
|
||||
{
|
||||
super(name);
|
||||
_val = new ArrayList<Value>();
|
||||
}
|
||||
|
||||
public Object getValue()
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
public List<Value> getList()
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
public void addValue (Value v)
|
||||
{
|
||||
_val.add(v);
|
||||
}
|
||||
|
||||
public int size ()
|
||||
{
|
||||
return _val.size();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buff = new StringBuffer();
|
||||
buff.append("(");
|
||||
buff.append(getName());
|
||||
buff.append(":");
|
||||
for (Value n: _val)
|
||||
{
|
||||
buff.append(" "+n.toString());
|
||||
}
|
||||
buff.append(")");
|
||||
|
||||
return buff.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface AnnotationHandler
|
||||
{
|
||||
public void handleClass (String className, int version, int access,
|
||||
String signature, String superName, String[] interfaces,
|
||||
String annotation, List<Value>values);
|
||||
|
||||
public void handleMethod (String className, String methodName, int access,
|
||||
String params, String signature,String[] exceptions,
|
||||
String annotation, List<Value>values);
|
||||
|
||||
public void handleField (String className, String fieldName, int access,
|
||||
String fieldType, String signature, Object value,
|
||||
String annotation, List<Value>values);
|
||||
}
|
||||
|
||||
|
||||
public interface ClassHandler
|
||||
{
|
||||
public void handle (String className, int version, int access, String signature, String superName, String[] interfaces);
|
||||
}
|
||||
|
||||
public interface MethodHandler
|
||||
{
|
||||
public void handle (String className, String methodName, int access, String params, String signature,String[] exceptions);
|
||||
}
|
||||
|
||||
public interface FieldHandler
|
||||
{
|
||||
public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value);
|
||||
}
|
||||
|
||||
public class MyAnnotationVisitor implements AnnotationVisitor
|
||||
{
|
||||
List<Value> _annotationValues;
|
||||
String _annotationName;
|
||||
|
||||
public MyAnnotationVisitor (String annotationName, List<Value> values)
|
||||
{
|
||||
_annotationValues = values;
|
||||
_annotationName = annotationName;
|
||||
}
|
||||
|
||||
public List<Value> getAnnotationValues()
|
||||
{
|
||||
return _annotationValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a single-valued (name,value) pair for this annotation
|
||||
* @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void visit(String aname, Object avalue)
|
||||
{
|
||||
SimpleValue v = new SimpleValue(aname);
|
||||
v.setValue(avalue);
|
||||
_annotationValues.add(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a (name,value) pair whose value is another Annotation
|
||||
* @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc)
|
||||
{
|
||||
String s = normalize(desc);
|
||||
ListValue v = new ListValue(s);
|
||||
_annotationValues.add(v);
|
||||
MyAnnotationVisitor visitor = new MyAnnotationVisitor(s, v.getList());
|
||||
return visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an array valued (name, value) pair for this annotation
|
||||
* @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
|
||||
*/
|
||||
public AnnotationVisitor visitArray(String name)
|
||||
{
|
||||
ListValue v = new ListValue(name);
|
||||
_annotationValues.add(v);
|
||||
MyAnnotationVisitor visitor = new MyAnnotationVisitor(null, v.getList());
|
||||
return visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a enum-valued (name,value) pair for this annotation
|
||||
* @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void visitEnum(String name, String desc, String value)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void visitEnd()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MyClassVisitor
|
||||
*
|
||||
* ASM visitor for a class.
|
||||
*/
|
||||
public class MyClassVisitor extends EmptyVisitor
|
||||
{
|
||||
String _className;
|
||||
int _access;
|
||||
String _signature;
|
||||
String _superName;
|
||||
String[] _interfaces;
|
||||
int _version;
|
||||
|
||||
|
||||
public void visit (int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces)
|
||||
{
|
||||
_className = normalize(name);
|
||||
_access = access;
|
||||
_signature = signature;
|
||||
_superName = superName;
|
||||
_interfaces = interfaces;
|
||||
_version = version;
|
||||
|
||||
_parsedClassNames.add(_className);
|
||||
//call all registered ClassHandlers
|
||||
String[] normalizedInterfaces = null;
|
||||
if (interfaces!= null)
|
||||
{
|
||||
normalizedInterfaces = new String[interfaces.length];
|
||||
int i=0;
|
||||
for (String s : interfaces)
|
||||
normalizedInterfaces[i++] = normalize(s);
|
||||
}
|
||||
|
||||
for (ClassHandler h : AnnotationParser.this._classHandlers)
|
||||
{
|
||||
h.handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
|
||||
}
|
||||
}
|
||||
|
||||
public AnnotationVisitor visitAnnotation (String desc, boolean visible)
|
||||
{
|
||||
MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
|
||||
{
|
||||
public void visitEnd()
|
||||
{
|
||||
super.visitEnd();
|
||||
|
||||
//call all AnnotationHandlers with classname, annotation name + values
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return visitor;
|
||||
}
|
||||
|
||||
public MethodVisitor visitMethod (final int access,
|
||||
final String name,
|
||||
final String params,
|
||||
final String signature,
|
||||
final String[] exceptions)
|
||||
{
|
||||
|
||||
return new EmptyVisitor ()
|
||||
{
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||
{
|
||||
MyAnnotationVisitor visitor = new MyAnnotationVisitor (normalize(desc), new ArrayList<Value>())
|
||||
{
|
||||
public void visitEnd()
|
||||
{
|
||||
super.visitEnd();
|
||||
//call all AnnotationHandlers with classname, method, annotation name + values
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.handleMethod(_className, name, access, params, signature, exceptions, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return visitor;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public FieldVisitor visitField (final int access,
|
||||
final String fieldName,
|
||||
final String fieldType,
|
||||
final String signature,
|
||||
final Object value)
|
||||
{
|
||||
|
||||
return new EmptyVisitor ()
|
||||
{
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
|
||||
{
|
||||
MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
|
||||
{
|
||||
public void visitEnd()
|
||||
{
|
||||
super.visitEnd();
|
||||
AnnotationHandler handler = AnnotationParser.this._annotationHandlers.get(_annotationName);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
|
||||
}
|
||||
}
|
||||
};
|
||||
return visitor;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void registerAnnotationHandler (String annotationName, AnnotationHandler handler)
|
||||
{
|
||||
_annotationHandlers.put(annotationName, handler);
|
||||
}
|
||||
|
||||
public void registerClassHandler (ClassHandler handler)
|
||||
{
|
||||
_classHandlers.add(handler);
|
||||
}
|
||||
|
||||
public boolean isParsed (String className)
|
||||
{
|
||||
return _parsedClassNames.contains(className);
|
||||
}
|
||||
|
||||
public void parse (String className, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (className == null)
|
||||
return;
|
||||
|
||||
if (!resolver.isExcluded(className))
|
||||
{
|
||||
if (!isParsed(className) || resolver.shouldOverride(className))
|
||||
{
|
||||
className = className.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), className, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses)
|
||||
throws Exception
|
||||
{
|
||||
Class cz = clazz;
|
||||
while (cz != null)
|
||||
{
|
||||
if (!resolver.isExcluded(cz.getName()))
|
||||
{
|
||||
if (!isParsed(cz.getName()) || resolver.shouldOverride(cz.getName()))
|
||||
{
|
||||
String nameAsResource = cz.getName().replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), nameAsResource, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
}
|
||||
}
|
||||
if (visitSuperClasses)
|
||||
cz = cz.getSuperclass();
|
||||
else
|
||||
cz = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void parse (String[] classNames, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (classNames == null)
|
||||
return;
|
||||
|
||||
parse(Arrays.asList(classNames), resolver);
|
||||
}
|
||||
|
||||
public void parse (List<String> classNames, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
for (String s:classNames)
|
||||
{
|
||||
if ((resolver == null) || (!resolver.isExcluded(s) && (!isParsed(s) || resolver.shouldOverride(s))))
|
||||
{
|
||||
s = s.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), s, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parse (Resource dir, ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (!dir.isDirectory() || !dir.exists())
|
||||
return;
|
||||
|
||||
|
||||
String[] files=dir.list();
|
||||
for (int f=0;files!=null && f<files.length;f++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource res = dir.addPath(files[f]);
|
||||
if (res.isDirectory())
|
||||
parse(res, resolver);
|
||||
String name = res.getName();
|
||||
if (name.endsWith(".class"))
|
||||
{
|
||||
if ((resolver == null)|| (!resolver.isExcluded(name) && (!isParsed(name) || resolver.shouldOverride(name))))
|
||||
scanClass(res.getURL().openStream());
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.warn(Log.EXCEPTION,ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find annotations on classes in the supplied classloader.
|
||||
* Only class files in jar files will be scanned.
|
||||
* @param loader
|
||||
* @param visitParents
|
||||
* @param jarNamePattern
|
||||
* @param nullInclusive
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
*/
|
||||
public void parse (ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (loader==null)
|
||||
return;
|
||||
|
||||
if (!(loader instanceof URLClassLoader))
|
||||
return; //can't extract classes?
|
||||
|
||||
JarScanner scanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URI jarUri, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
if ((resolver == null)
|
||||
||
|
||||
(!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
|
||||
{
|
||||
|
||||
Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
|
||||
scanClass(clazz.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry "+entry, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
scanner.scan(null, loader, nullInclusive, visitParents);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find annotations in classes in the supplied url of jar files.
|
||||
* @param uris
|
||||
* @param resolver
|
||||
* @throws Exception
|
||||
*/
|
||||
public void parse (URI[] uris, final ClassNameResolver resolver)
|
||||
throws Exception
|
||||
{
|
||||
if (uris==null)
|
||||
return;
|
||||
|
||||
JarScanner scanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URI jarUri, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
|
||||
if ((resolver == null)
|
||||
||
|
||||
(!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
|
||||
{
|
||||
Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
|
||||
scanClass(clazz.getInputStream());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry "+entry, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
scanner.scan(null, uris, true);
|
||||
}
|
||||
|
||||
|
||||
private void scanClass (InputStream is)
|
||||
throws IOException
|
||||
{
|
||||
ClassReader reader = new ClassReader(is);
|
||||
reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
}
|
|
@ -1,645 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.Resources;
|
||||
import javax.annotation.security.RunAs;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.util.IntrospectionUtil;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AnnotationProcessor
|
||||
*
|
||||
* Act on the annotations discovered in the webapp.
|
||||
*/
|
||||
public class AnnotationProcessor
|
||||
{
|
||||
AnnotationFinder _finder;
|
||||
ClassLoader _loader;
|
||||
RunAsCollection _runAs;
|
||||
InjectionCollection _injections;
|
||||
LifeCycleCallbackCollection _callbacks;
|
||||
List _servlets;
|
||||
List _filters;
|
||||
List _listeners;
|
||||
List _servletMappings;
|
||||
List _filterMappings;
|
||||
WebAppContext _webApp;
|
||||
|
||||
private static Class[] __envEntryTypes =
|
||||
new Class[] {String.class, Character.class, Integer.class, Boolean.class, Double.class, Byte.class, Short.class, Long.class, Float.class};
|
||||
|
||||
public AnnotationProcessor(WebAppContext webApp, AnnotationFinder finder)
|
||||
{
|
||||
if (webApp == null)
|
||||
throw new IllegalStateException("No WebAppContext");
|
||||
|
||||
_webApp=webApp;
|
||||
_finder=finder;
|
||||
ServletHandler servletHandler = _webApp.getServletHandler();
|
||||
_filters = LazyList.array2List(servletHandler.getFilters());
|
||||
_filterMappings = LazyList.array2List(servletHandler.getFilterMappings());
|
||||
_servlets = LazyList.array2List(servletHandler.getServlets());
|
||||
_servletMappings = LazyList.array2List(servletHandler.getServletMappings());
|
||||
_listeners = LazyList.array2List(_webApp.getEventListeners());
|
||||
|
||||
_runAs = (RunAsCollection)_webApp.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
_injections = (InjectionCollection)_webApp.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
_callbacks = (LifeCycleCallbackCollection)_webApp.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
|
||||
if (_runAs == null || _injections == null || _callbacks == null)
|
||||
throw new IllegalStateException("RunAs, Injections or LifeCycleCallbacks is null");
|
||||
}
|
||||
|
||||
|
||||
public void process ()
|
||||
throws Exception
|
||||
{
|
||||
processServlets();
|
||||
processFilters();
|
||||
processListeners();
|
||||
processRunAsAnnotations();
|
||||
processLifeCycleCallbackAnnotations();
|
||||
processResourcesAnnotations();
|
||||
processResourceAnnotations();
|
||||
}
|
||||
|
||||
public void processServlets ()
|
||||
throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void processFilters ()
|
||||
throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void processListeners ()
|
||||
throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public List getServlets ()
|
||||
{
|
||||
return _servlets;
|
||||
}
|
||||
|
||||
public List getServletMappings ()
|
||||
{
|
||||
return _servletMappings;
|
||||
}
|
||||
|
||||
public List getFilters ()
|
||||
{
|
||||
return _filters;
|
||||
}
|
||||
|
||||
public List getFilterMappings ()
|
||||
{
|
||||
return _filterMappings;
|
||||
}
|
||||
|
||||
public List getListeners()
|
||||
{
|
||||
return _listeners;
|
||||
}
|
||||
|
||||
|
||||
public void processRunAsAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
for (Class clazz:_finder.getClassesForAnnotation(RunAs.class))
|
||||
{
|
||||
if (!javax.servlet.Servlet.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Log.debug("Ignoring runAs notation on on-servlet class "+clazz.getName());
|
||||
continue;
|
||||
}
|
||||
RunAs runAs = (RunAs)clazz.getAnnotation(RunAs.class);
|
||||
if (runAs != null)
|
||||
{
|
||||
String role = runAs.value();
|
||||
if (role != null)
|
||||
{
|
||||
org.eclipse.jetty.plus.annotation.RunAs ra = new org.eclipse.jetty.plus.annotation.RunAs();
|
||||
ra.setTargetClass(clazz);
|
||||
ra.setRoleName(role);
|
||||
_runAs.add(ra);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void processLifeCycleCallbackAnnotations()
|
||||
throws Exception
|
||||
{
|
||||
processPostConstructAnnotations();
|
||||
processPreDestroyAnnotations();
|
||||
}
|
||||
|
||||
private void processPostConstructAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
// TODO: check that the same class does not have more than one
|
||||
for (Method m:_finder.getMethodsForAnnotation(PostConstruct.class))
|
||||
{
|
||||
if (!isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring "+m.getName()+" as non-servlet type");
|
||||
continue;
|
||||
}
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
PostConstructCallback callback = new PostConstructCallback();
|
||||
callback.setTargetClass(m.getDeclaringClass());
|
||||
callback.setTarget(m);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void processPreDestroyAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
//TODO: check that the same class does not have more than one
|
||||
|
||||
for (Method m: _finder.getMethodsForAnnotation(PreDestroy.class))
|
||||
{
|
||||
if (!isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring "+m.getName()+" as non-servlet type");
|
||||
continue;
|
||||
}
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
PreDestroyCallback callback = new PreDestroyCallback();
|
||||
callback.setTargetClass(m.getDeclaringClass());
|
||||
callback.setTarget(m);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process @Resources annotation on classes
|
||||
*/
|
||||
public void processResourcesAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
List<Class<?>> classes = _finder.getClassesForAnnotation(Resources.class);
|
||||
for (Class<?> clazz:classes)
|
||||
{
|
||||
if (!isServletType(clazz))
|
||||
{
|
||||
Log.debug("Ignoring @Resources annotation on on-servlet type class "+clazz.getName());
|
||||
continue;
|
||||
}
|
||||
//Handle Resources annotation - add namespace entries
|
||||
Resources resources = (Resources)clazz.getAnnotation(Resources.class);
|
||||
if (resources == null)
|
||||
continue;
|
||||
|
||||
Resource[] resArray = resources.value();
|
||||
if (resArray==null||resArray.length==0)
|
||||
continue;
|
||||
|
||||
for (int j=0;j<resArray.length;j++)
|
||||
{
|
||||
String name = resArray[j].name();
|
||||
String mappedName = resArray[j].mappedName();
|
||||
Resource.AuthenticationType auth = resArray[j].authenticationType();
|
||||
Class type = resArray[j].type();
|
||||
boolean shareable = resArray[j].shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
try
|
||||
{
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName))
|
||||
throw new IllegalStateException("No resource bound at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void processResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
processClassResourceAnnotations();
|
||||
processMethodResourceAnnotations();
|
||||
processFieldResourceAnnotations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class level Resource annotations declare a name in the
|
||||
* environment that will be looked up at runtime. They do
|
||||
* not specify an injection.
|
||||
*/
|
||||
public void processClassResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
List<Class<?>> classes = _finder.getClassesForAnnotation(Resource.class);
|
||||
for (Class<?> clazz:classes)
|
||||
{
|
||||
if (!isServletType(clazz))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type class "+clazz.getName());
|
||||
continue;
|
||||
}
|
||||
//Handle Resource annotation - add namespace entries
|
||||
Resource resource = (Resource)clazz.getAnnotation(Resource.class);
|
||||
if (resource != null)
|
||||
{
|
||||
String name = resource.name();
|
||||
String mappedName = resource.mappedName();
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
Class type = resource.type();
|
||||
boolean shareable = resource.shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
|
||||
try
|
||||
{
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name,mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name,mappedName))
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a Resource annotation on the Methods.
|
||||
*
|
||||
* This will generate a JNDI entry, and an Injection to be
|
||||
* processed when an instance of the class is created.
|
||||
* @param injections
|
||||
*/
|
||||
public void processMethodResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
//Get all methods that have a Resource annotation
|
||||
List<Method> methods = _finder.getMethodsForAnnotation(javax.annotation.Resource.class);
|
||||
|
||||
for (Method m: methods)
|
||||
{
|
||||
if (!isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type method "+m.getName());
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Commons Annotations Spec 2.3
|
||||
* " The Resource annotation is used to declare a reference to a resource.
|
||||
* It can be specified on a class, methods or on fields. When the
|
||||
* annotation is applied on a field or method, the container will
|
||||
* inject an instance of the requested resource into the application
|
||||
* when the application is initialized... Even though this annotation
|
||||
* is not marked Inherited, if used all superclasses MUST be examined
|
||||
* to discover all uses of this annotation. All such annotation instances
|
||||
* specify resources that are needed by the application. Note that this
|
||||
* annotation may appear on private fields and methods of the superclasses.
|
||||
* Injection of the declared resources needs to happen in these cases as
|
||||
* well, even if a method with such an annotation is overridden by a subclass."
|
||||
*
|
||||
* Which IMHO, put more succinctly means "If you find a @Resource on any method
|
||||
* or field, inject it!".
|
||||
*/
|
||||
Resource resource = (Resource)m.getAnnotation(Resource.class);
|
||||
if (resource == null)
|
||||
continue;
|
||||
|
||||
//JavaEE Spec 5.2.3: Method cannot be static
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" cannot be static");
|
||||
|
||||
|
||||
// Check it is a valid javabean
|
||||
if (!IntrospectionUtil.isJavaBeanCompliantSetter(m))
|
||||
throw new IllegalStateException(m+" is not a java bean compliant setter method");
|
||||
|
||||
//default name is the javabean property name
|
||||
String name = m.getName().substring(3);
|
||||
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||
name = m.getDeclaringClass().getCanonicalName()+"/"+name;
|
||||
//allow default name to be overridden
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
//get the mappedName if there is one
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
|
||||
Class type = m.getParameterTypes()[0];
|
||||
|
||||
//get other parts that can be specified in @Resource
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
boolean shareable = resource.shareable();
|
||||
|
||||
//if @Resource specifies a type, check it is compatible with setter param
|
||||
if ((resource.type() != null)
|
||||
&&
|
||||
!resource.type().equals(Object.class)
|
||||
&&
|
||||
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with method param="+type+ " for "+m);
|
||||
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = _injections.getInjection(m.getDeclaringClass(), m);
|
||||
if (webXmlInjection == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try binding name to environment
|
||||
//try the webapp's environment first
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName);
|
||||
|
||||
//try the server's environment
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName);
|
||||
|
||||
//try the jvm's environment
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||
|
||||
//TODO if it is an env-entry from web.xml it can be injected, in which case there will be no
|
||||
//NamingEntry, just a value bound in java:comp/env
|
||||
if (!bound)
|
||||
{
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||
bound = true;
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bound)
|
||||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(m.getDeclaringClass());
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
injection.setTarget(m);
|
||||
_injections.add(injection);
|
||||
}
|
||||
else if (!isEnvEntryType(type))
|
||||
{
|
||||
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!isEnvEntryType(type))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if an injection is already set up for this name, then the types must be compatible
|
||||
//JavaEE spec sec 5.2.4
|
||||
|
||||
Object value = webXmlInjection.lookupInjectedValue();
|
||||
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+value.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process @Resource annotation for a Field. These will both set up a
|
||||
* JNDI entry and generate an Injection. Or they can be the equivalent
|
||||
* of env-entries with default values
|
||||
*
|
||||
* @param injections
|
||||
*/
|
||||
public void processFieldResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
//Get all fields that have a Resource annotation
|
||||
List<Field> fields = _finder.getFieldsForAnnotation(Resource.class);
|
||||
for (Field f: fields)
|
||||
{
|
||||
if (!isServletType(f.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type field "+f.getName());
|
||||
continue;
|
||||
}
|
||||
Resource resource = (Resource)f.getAnnotation(Resource.class);
|
||||
if (resource == null)
|
||||
continue;
|
||||
|
||||
//JavaEE Spec 5.2.3: Field cannot be static
|
||||
if (Modifier.isStatic(f.getModifiers()))
|
||||
throw new IllegalStateException(f+" cannot be static");
|
||||
|
||||
//JavaEE Spec 5.2.3: Field cannot be final
|
||||
if (Modifier.isFinal(f.getModifiers()))
|
||||
throw new IllegalStateException(f+" cannot be final");
|
||||
|
||||
//work out default name
|
||||
String name = f.getDeclaringClass().getCanonicalName()+"/"+f.getName();
|
||||
//allow @Resource name= to override the field name
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
|
||||
//get the type of the Field
|
||||
Class type = f.getType();
|
||||
//if @Resource specifies a type, check it is compatible with field type
|
||||
if ((resource.type() != null)
|
||||
&&
|
||||
!resource.type().equals(Object.class)
|
||||
&&
|
||||
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with field type ="+f.getType());
|
||||
|
||||
//get the mappedName if there is one
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
//get other parts that can be specified in @Resource
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
boolean shareable = resource.shareable();
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = _injections.getInjection(f.getDeclaringClass(), f);
|
||||
if (webXmlInjection == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp, name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_webApp.getServer(), name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||
if (!bound)
|
||||
{
|
||||
//see if there is an env-entry value been bound from web.xml
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||
bound = true;
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
}
|
||||
//Check there is a JNDI entry for this annotation
|
||||
if (bound)
|
||||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it if the binding succeeded
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(f.getDeclaringClass());
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
injection.setTarget(f);
|
||||
_injections.add(injection);
|
||||
}
|
||||
else if (!isEnvEntryType(type))
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!isEnvEntryType(type))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if an injection is already set up for this name, then the types must be compatible
|
||||
//JavaEE spec sec 5.2.4
|
||||
Object value = webXmlInjection.lookupInjectedValue();
|
||||
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+value.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the presented method belongs to a class that is one
|
||||
* of the classes with which a servlet container should be concerned.
|
||||
* @param m
|
||||
* @return
|
||||
*/
|
||||
private boolean isServletType (Class c)
|
||||
{
|
||||
boolean isServlet = false;
|
||||
if (javax.servlet.Servlet.class.isAssignableFrom(c) ||
|
||||
javax.servlet.Filter.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletContextListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletContextAttributeListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletRequestListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c))
|
||||
|
||||
isServlet=true;
|
||||
|
||||
return isServlet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static boolean isEnvEntryType (Class type)
|
||||
{
|
||||
boolean result = false;
|
||||
for (int i=0;i<__envEntryTypes.length && !result;i++)
|
||||
{
|
||||
result = (type.equals(__envEntryTypes[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static String normalizePattern(String p)
|
||||
{
|
||||
if (p!=null && p.length()>0 && !p.startsWith("/") && !p.startsWith("*"))
|
||||
return "/"+p;
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.ClassHandler;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/**
|
||||
* ClassInheritanceHandler
|
||||
*
|
||||
* As asm scans for classes, remember the type hierarchy.
|
||||
*/
|
||||
public class ClassInheritanceHandler implements ClassHandler
|
||||
{
|
||||
|
||||
MultiMap _inheritanceMap = new MultiMap();
|
||||
|
||||
public ClassInheritanceHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(String className, int version, int access, String signature, String superName, String[] interfaces)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i=0; interfaces != null && i<interfaces.length;i++)
|
||||
{
|
||||
_inheritanceMap.add (interfaces[i], className);
|
||||
}
|
||||
//To save memory, we don't record classes that only extend Object, as that can be assumed
|
||||
if (!"java.lang.Object".equals(superName))
|
||||
_inheritanceMap.add(superName, className);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List getClassNamesExtendingOrImplementing (String className)
|
||||
{
|
||||
return _inheritanceMap.getValues(className);
|
||||
}
|
||||
|
||||
public MultiMap getMap ()
|
||||
{
|
||||
return _inheritanceMap;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PostConstructCallback;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class PostConstructAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
|
||||
public PostConstructAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@PostConstruct annotation not applicable to classes: "+className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PostConstruct annotation not applicable to fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
Method m = clazz.getDeclaredMethod(methodName, Util.convertTypes(params));
|
||||
|
||||
if (!Util.isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring "+m.getName()+" as non-servlet type");
|
||||
return;
|
||||
}
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
PostConstructCallback callback = new PostConstructCallback();
|
||||
callback.setTargetClass(m.getDeclaringClass());
|
||||
callback.setTarget(m);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class PreDestroyAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
WebAppContext _wac;
|
||||
|
||||
public PreDestroyAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PreDestroy annotation not applicable for classes: "+className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@PreDestroy annotation not applicable for fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_wac.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
|
||||
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
|
||||
Method m = clazz.getDeclaredMethod(methodName, Util.convertTypes(params));
|
||||
if (!Util.isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignored "+m.getName()+" as non-servlet type");
|
||||
return;
|
||||
}
|
||||
if (m.getParameterTypes().length != 0)
|
||||
throw new IllegalStateException(m+" has parameters");
|
||||
if (m.getReturnType() != Void.TYPE)
|
||||
throw new IllegalStateException(m+" is not void");
|
||||
if (m.getExceptionTypes().length != 0)
|
||||
throw new IllegalStateException(m+" throws checked exceptions");
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" is static");
|
||||
|
||||
PreDestroyCallback callback = new PreDestroyCallback();
|
||||
callback.setTargetClass(m.getDeclaringClass());
|
||||
callback.setTarget(m);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,369 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.util.IntrospectionUtil;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class ResourceAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
|
||||
public ResourceAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class level Resource annotations declare a name in the
|
||||
* environment that will be looked up at runtime. They do
|
||||
* not specify an injection.
|
||||
*/
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
if (!Util.isServletType(clazz))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type class "+clazz.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
//Handle Resource annotation - add namespace entries
|
||||
Resource resource = (Resource)clazz.getAnnotation(Resource.class);
|
||||
if (resource != null)
|
||||
{
|
||||
String name = resource.name();
|
||||
String mappedName = resource.mappedName();
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
Class type = resource.type();
|
||||
boolean shareable = resource.shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
throw new IllegalStateException ("Class level Resource annotations must contain a name (Common Annotations Spec Section 2.3)");
|
||||
|
||||
try
|
||||
{
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name,mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name,mappedName))
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
InjectionCollection injections = (InjectionCollection)_wac.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
Field f = clazz.getDeclaredField(fieldName);
|
||||
|
||||
if (!Util.isServletType(clazz))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type field "+fieldName);
|
||||
return;
|
||||
}
|
||||
Resource resource = (Resource)f.getAnnotation(Resource.class);
|
||||
if (resource == null)
|
||||
return;
|
||||
|
||||
//JavaEE Spec 5.2.3: Field cannot be static
|
||||
if (Modifier.isStatic(f.getModifiers()))
|
||||
throw new IllegalStateException(f+" cannot be static");
|
||||
|
||||
//JavaEE Spec 5.2.3: Field cannot be final
|
||||
if (Modifier.isFinal(f.getModifiers()))
|
||||
throw new IllegalStateException(f+" cannot be final");
|
||||
|
||||
//work out default name
|
||||
String name = f.getDeclaringClass().getCanonicalName()+"/"+f.getName();
|
||||
//allow @Resource name= to override the field name
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
|
||||
//get the type of the Field
|
||||
Class type = f.getType();
|
||||
//if @Resource specifies a type, check it is compatible with field type
|
||||
if ((resource.type() != null)
|
||||
&&
|
||||
!resource.type().equals(Object.class)
|
||||
&&
|
||||
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with field type ="+f.getType());
|
||||
|
||||
//get the mappedName if there is one
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
//get other parts that can be specified in @Resource
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
boolean shareable = resource.shareable();
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = injections.getInjection(f.getDeclaringClass(), f);
|
||||
if (webXmlInjection == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName);
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||
if (!bound)
|
||||
{
|
||||
//see if there is an env-entry value been bound from web.xml
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||
bound = true;
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
}
|
||||
//Check there is a JNDI entry for this annotation
|
||||
if (bound)
|
||||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it if the binding succeeded
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(f.getDeclaringClass());
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
injection.setTarget(f);
|
||||
injections.add(injection);
|
||||
}
|
||||
else if (!Util.isEnvEntryType(type))
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!Util.isEnvEntryType(type))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if an injection is already set up for this name, then the types must be compatible
|
||||
//JavaEE spec sec 5.2.4
|
||||
Object val = webXmlInjection.lookupInjectedValue();
|
||||
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+val.getClass());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a Resource annotation on a Method.
|
||||
*
|
||||
* This will generate a JNDI entry, and an Injection to be
|
||||
* processed when an instance of the class is created.
|
||||
* @param injections
|
||||
*/
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
InjectionCollection injections = (InjectionCollection)_wac.getAttribute(InjectionCollection.INJECTION_COLLECTION);
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
|
||||
Class[] args = Util.convertTypes(params);
|
||||
Method m = clazz.getDeclaredMethod(methodName, args);
|
||||
|
||||
if (!Util.isServletType(m.getDeclaringClass()))
|
||||
{
|
||||
Log.debug("Ignoring @Resource annotation on on-servlet type method "+m.getName());
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Commons Annotations Spec 2.3
|
||||
* " The Resource annotation is used to declare a reference to a resource.
|
||||
* It can be specified on a class, methods or on fields. When the
|
||||
* annotation is applied on a field or method, the container will
|
||||
* inject an instance of the requested resource into the application
|
||||
* when the application is initialized... Even though this annotation
|
||||
* is not marked Inherited, if used all superclasses MUST be examined
|
||||
* to discover all uses of this annotation. All such annotation instances
|
||||
* specify resources that are needed by the application. Note that this
|
||||
* annotation may appear on private fields and methods of the superclasses.
|
||||
* Injection of the declared resources needs to happen in these cases as
|
||||
* well, even if a method with such an annotation is overridden by a subclass."
|
||||
*
|
||||
* Which IMHO, put more succinctly means "If you find a @Resource on any method
|
||||
* or field, inject it!".
|
||||
*/
|
||||
Resource resource = (Resource)m.getAnnotation(Resource.class);
|
||||
if (resource == null)
|
||||
return;
|
||||
|
||||
//JavaEE Spec 5.2.3: Method cannot be static
|
||||
if (Modifier.isStatic(m.getModifiers()))
|
||||
throw new IllegalStateException(m+" cannot be static");
|
||||
|
||||
|
||||
// Check it is a valid javabean
|
||||
if (!IntrospectionUtil.isJavaBeanCompliantSetter(m))
|
||||
throw new IllegalStateException(m+" is not a java bean compliant setter method");
|
||||
|
||||
//default name is the javabean property name
|
||||
String name = m.getName().substring(3);
|
||||
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||
name = m.getDeclaringClass().getCanonicalName()+"/"+name;
|
||||
//allow default name to be overridden
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
//get the mappedName if there is one
|
||||
String mappedName = (resource.mappedName()!=null && !resource.mappedName().trim().equals("")?resource.mappedName():null);
|
||||
|
||||
Class type = m.getParameterTypes()[0];
|
||||
|
||||
//get other parts that can be specified in @Resource
|
||||
Resource.AuthenticationType auth = resource.authenticationType();
|
||||
boolean shareable = resource.shareable();
|
||||
|
||||
//if @Resource specifies a type, check it is compatible with setter param
|
||||
if ((resource.type() != null)
|
||||
&&
|
||||
!resource.type().equals(Object.class)
|
||||
&&
|
||||
(!IntrospectionUtil.isTypeCompatible(type, resource.type(), false)))
|
||||
throw new IllegalStateException("@Resource incompatible type="+resource.type()+ " with method param="+type+ " for "+m);
|
||||
|
||||
//check if an injection has already been setup for this target by web.xml
|
||||
Injection webXmlInjection = injections.getInjection(m.getDeclaringClass(), m);
|
||||
if (webXmlInjection == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try binding name to environment
|
||||
//try the webapp's environment first
|
||||
boolean bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName);
|
||||
|
||||
//try the server's environment
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName);
|
||||
|
||||
//try the jvm's environment
|
||||
if (!bound)
|
||||
bound = org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(null, name, mappedName);
|
||||
|
||||
//TODO if it is an env-entry from web.xml it can be injected, in which case there will be no
|
||||
//NamingEntry, just a value bound in java:comp/env
|
||||
if (!bound)
|
||||
{
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
String nameInEnvironment = (mappedName!=null?mappedName:name);
|
||||
ic.lookup("java:comp/env/"+nameInEnvironment);
|
||||
bound = true;
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
bound = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bound)
|
||||
{
|
||||
Log.debug("Bound "+(mappedName==null?name:mappedName) + " as "+ name);
|
||||
// Make the Injection for it
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(m.getDeclaringClass());
|
||||
injection.setJndiName(name);
|
||||
injection.setMappingName(mappedName);
|
||||
injection.setTarget(m);
|
||||
injections.add(injection);
|
||||
}
|
||||
else if (!Util.isEnvEntryType(type))
|
||||
{
|
||||
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
//if this is an env-entry type resource and there is no value bound for it, it isn't
|
||||
//an error, it just means that perhaps the code will use a default value instead
|
||||
// JavaEE Spec. sec 5.4.1.3
|
||||
if (!Util.isEnvEntryType(type))
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if an injection is already set up for this name, then the types must be compatible
|
||||
//JavaEE spec sec 5.2.4
|
||||
|
||||
Object value = webXmlInjection.lookupInjectedValue();
|
||||
if (!IntrospectionUtil.isTypeCompatible(type, value.getClass(), false))
|
||||
throw new IllegalStateException("Type of field="+type+" is not compatible with Resource type="+value.getClass());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.Resources;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class ResourcesAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
|
||||
protected WebAppContext _wac;
|
||||
|
||||
public ResourcesAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null,className);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
return;
|
||||
}
|
||||
if (!Util.isServletType(clazz))
|
||||
{
|
||||
Log.debug("@Resources annotation ignored on on-servlet type class "+clazz.getName());
|
||||
return;
|
||||
}
|
||||
//Handle Resources annotation - add namespace entries
|
||||
Resources resources = (Resources)clazz.getAnnotation(Resources.class);
|
||||
if (resources == null)
|
||||
return;
|
||||
|
||||
Resource[] resArray = resources.value();
|
||||
if (resArray==null||resArray.length==0)
|
||||
return;
|
||||
|
||||
for (int j=0;j<resArray.length;j++)
|
||||
{
|
||||
String name = resArray[j].name();
|
||||
String mappedName = resArray[j].mappedName();
|
||||
Resource.AuthenticationType auth = resArray[j].authenticationType();
|
||||
Class type = resArray[j].type();
|
||||
boolean shareable = resArray[j].shareable();
|
||||
|
||||
if (name==null || name.trim().equals(""))
|
||||
{
|
||||
Log.warn ("@Resource annotations on classes must contain a name (Common Annotations Spec Section 2.3)");
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
//TODO don't ignore the shareable, auth etc etc
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac, name, mappedName))
|
||||
if (!org.eclipse.jetty.plus.jndi.NamingEntryUtil.bindToENC(_wac.getServer(), name, mappedName))
|
||||
throw new IllegalStateException("No resource bound at "+(mappedName==null?name:mappedName));
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@Resources not applicable for fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@Resources not applicable for methods: "+className+"."+methodName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.security.RunAs;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class RunAsAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
protected WebAppContext _wac;
|
||||
|
||||
public RunAsAnnotationHandler (WebAppContext wac)
|
||||
{
|
||||
_wac = wac;
|
||||
}
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
RunAsCollection runAsCollection = (RunAsCollection)_wac.getAttribute(RunAsCollection.RUNAS_COLLECTION);
|
||||
Class clazz = null;
|
||||
try
|
||||
{
|
||||
clazz = Loader.loadClass(null, className);
|
||||
if (!javax.servlet.Servlet.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Log.debug("@RunAs annotation ignored on on-servlet class "+clazz.getName());
|
||||
return;
|
||||
}
|
||||
RunAs runAs = (RunAs)clazz.getAnnotation(RunAs.class);
|
||||
if (runAs != null)
|
||||
{
|
||||
String role = runAs.value();
|
||||
if (role != null)
|
||||
{
|
||||
org.eclipse.jetty.plus.annotation.RunAs ra = new org.eclipse.jetty.plus.annotation.RunAs();
|
||||
ra.setTargetClass(clazz);
|
||||
ra.setRoleName(role);
|
||||
runAsCollection.add(ra);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn ("@RunAs annotation not applicable for fields: "+className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
Log.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,37 +13,143 @@
|
|||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
/**
|
||||
* Util
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Util
|
||||
{
|
||||
{
|
||||
private static Class[] __envEntryTypes =
|
||||
new Class[] {String.class, Character.class, Integer.class, Boolean.class, Double.class, Byte.class, Short.class, Long.class, Float.class};
|
||||
|
||||
/**
|
||||
* Check if the presented method belongs to a class that is one
|
||||
* of the classes with which a servlet container should be concerned.
|
||||
* @param m
|
||||
* @return
|
||||
*/
|
||||
public static boolean isServletType (Class c)
|
||||
{
|
||||
boolean isServlet = false;
|
||||
if (javax.servlet.Servlet.class.isAssignableFrom(c) ||
|
||||
javax.servlet.Filter.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletContextListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletContextAttributeListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletRequestListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c))
|
||||
|
||||
isServlet=true;
|
||||
|
||||
return isServlet;
|
||||
}
|
||||
|
||||
public static boolean isEnvEntryType (Class type)
|
||||
{
|
||||
boolean result = false;
|
||||
for (int i=0;i<__envEntryTypes.length && !result;i++)
|
||||
{
|
||||
result = (type.equals(__envEntryTypes[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String normalizePattern(String p)
|
||||
{
|
||||
if (p!=null && p.length()>0 && !p.startsWith("/") && !p.startsWith("*"))
|
||||
return "/"+p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find all annotations directly and inherited on a class.
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public List findMethodAnnotations (Class clazz)
|
||||
public static Class[] convertTypes (String params)
|
||||
throws Exception
|
||||
{
|
||||
//TODO
|
||||
|
||||
return null;
|
||||
return convertTypes(Type.getArgumentTypes(params));
|
||||
}
|
||||
|
||||
public List findFieldAnnotations (Class clazz)
|
||||
|
||||
public static Class[] convertTypes (Type[] types)
|
||||
throws Exception
|
||||
{
|
||||
//TODO
|
||||
if (types==null)
|
||||
return new Class[0];
|
||||
|
||||
return null;
|
||||
Class[] classArray = new Class[types.length];
|
||||
|
||||
for (int i=0; i<types.length; i++)
|
||||
{
|
||||
classArray[i] = convertType(types[i]);
|
||||
}
|
||||
return classArray;
|
||||
}
|
||||
|
||||
public static Class convertType (Type t)
|
||||
throws Exception
|
||||
{
|
||||
if (t == null)
|
||||
return (Class)null;
|
||||
|
||||
switch (t.getSort())
|
||||
{
|
||||
case Type.BOOLEAN:
|
||||
{
|
||||
return Boolean.TYPE;
|
||||
}
|
||||
case Type.ARRAY:
|
||||
{
|
||||
Class clazz = convertType(t.getElementType());
|
||||
return Array.newInstance(clazz, 0).getClass();
|
||||
}
|
||||
case Type.BYTE:
|
||||
{
|
||||
return Byte.TYPE;
|
||||
}
|
||||
case Type.CHAR:
|
||||
{
|
||||
return Character.TYPE;
|
||||
}
|
||||
case Type.DOUBLE:
|
||||
{
|
||||
return Double.TYPE;
|
||||
}
|
||||
case Type.FLOAT:
|
||||
{
|
||||
return Float.TYPE;
|
||||
}
|
||||
case Type.INT:
|
||||
{
|
||||
return Integer.TYPE;
|
||||
}
|
||||
case Type.LONG:
|
||||
{
|
||||
return Long.TYPE;
|
||||
}
|
||||
case Type.OBJECT:
|
||||
{
|
||||
return (Loader.loadClass(null, t.getClassName()));
|
||||
}
|
||||
case Type.SHORT:
|
||||
{
|
||||
return Short.TYPE;
|
||||
}
|
||||
case Type.VOID:
|
||||
{
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,11 +21,13 @@ package org.eclipse.jetty.annotations;
|
|||
*
|
||||
*/
|
||||
@Sample(value=50)
|
||||
public class ClassB extends ClassA
|
||||
@Multi({"do", "re", "mi"})
|
||||
public class ClassB extends ClassA implements InterfaceD
|
||||
{
|
||||
|
||||
//test override of public scope method
|
||||
@Sample(value=51)
|
||||
@Multi({"fa", "so", "la"})
|
||||
public void a()
|
||||
{
|
||||
System.err.println("ClassB.public");
|
||||
|
|
|
@ -18,15 +18,20 @@ import javax.annotation.PostConstruct;
|
|||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.RunAs;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
|
||||
@RunAs("admin")
|
||||
public class ClassC
|
||||
public class FilterC implements Filter
|
||||
{
|
||||
@Resource (mappedName="foo")
|
||||
private Double foo;
|
||||
|
@ -42,23 +47,25 @@ public class ClassC
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
public void anything (HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
response.getWriter().println("<h1>Pojo Servlet</h1>");
|
||||
response.getWriter().println("Acting like a Servlet.");
|
||||
}
|
||||
|
||||
|
||||
public void doFilter (HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws java.io.IOException, javax.servlet.ServletException
|
||||
|
||||
|
||||
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpServletRequest request = (HttpServletRequest)arg0;
|
||||
HttpServletResponse response = (HttpServletResponse)arg1;
|
||||
HttpSession session = request.getSession(true);
|
||||
String val = request.getParameter("action");
|
||||
if (val!=null)
|
||||
session.setAttribute("action", val);
|
||||
chain.doFilter(request, response);
|
||||
arg2.doFilter(request, response);
|
||||
}
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
public void init(FilterConfig arg0) throws ServletException
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 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;
|
||||
|
||||
/**
|
||||
* InterfaceD
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface InterfaceD
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
|
||||
|
||||
public class ListenerC implements ServletContextListener
|
||||
{
|
||||
|
||||
public void contextDestroyed(ServletContextEvent arg0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void contextInitialized(ServletContextEvent arg0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface Multi
|
||||
{
|
||||
String[] value();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.RunAs;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@RunAs("admin")
|
||||
public class ServletC extends HttpServlet
|
||||
{
|
||||
@Resource (mappedName="foo")
|
||||
private Double foo;
|
||||
|
||||
@PreDestroy
|
||||
public void pre ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void post()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
response.getWriter().println("<h1>Annotated Servlet</h1>");
|
||||
response.getWriter().println("An annotated Servlet.");
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestAnnotationFinder extends TestCase
|
||||
{
|
||||
|
||||
public void testNormalize()
|
||||
{
|
||||
assertEquals("org.eclipse.test.Foo", AnnotationFinder.normalize("Lorg/eclipse/test/Foo;"));
|
||||
assertEquals("org.eclipse.test.Foo.Bar", AnnotationFinder.normalize("org/eclipse/test/Foo$Bar.class"));
|
||||
}
|
||||
|
||||
public void testConvertType ()
|
||||
throws Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testSampleAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassA"};
|
||||
AnnotationFinder finder = new AnnotationFinder();
|
||||
|
||||
finder.find(classNames, new ClassNameResolver ()
|
||||
{
|
||||
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.err.println("Time to parse class: "+((end-start)));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
List<Class<?>> classes = finder.getClassesForAnnotation(Sample.class);
|
||||
end = System.currentTimeMillis();
|
||||
System.err.println("Time to find classes matching annotation: "+((end-start)));
|
||||
|
||||
assertNotNull(classes);
|
||||
assertEquals(1, classes.size());
|
||||
assertTrue(classes.contains(org.eclipse.jetty.annotations.ClassA.class));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
List<Method> methods = finder.getMethodsForAnnotation(Sample.class);
|
||||
end = System.currentTimeMillis();
|
||||
System.err.println("Time to find methods matching annotation : "+((end-start)));
|
||||
|
||||
assertNotNull(methods);
|
||||
assertEquals (5, methods.size());
|
||||
|
||||
Method a = ClassA.class.getDeclaredMethod("a", new Class[]{Array.newInstance(Integer.class, 0).getClass()});
|
||||
Method b = ClassA.class.getDeclaredMethod("b", new Class[]{Array.newInstance(ClassA.Foo.class, 0).getClass()});
|
||||
Method c = ClassA.class.getDeclaredMethod("c", new Class[]{Array.newInstance(Integer.TYPE, 0).getClass()});
|
||||
Method d = ClassA.class.getDeclaredMethod("d", new Class[]{Integer.TYPE, String.class});
|
||||
Method l = ClassA.class.getDeclaredMethod("l", new Class[]{});
|
||||
|
||||
assertTrue(methods.contains(a));
|
||||
assertTrue(methods.contains(b));
|
||||
assertTrue(methods.contains(c));
|
||||
assertTrue(methods.contains(d));
|
||||
assertTrue(methods.contains(l));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
List<Field> fields = finder.getFieldsForAnnotation(Sample.class);
|
||||
end = System.currentTimeMillis();
|
||||
System.err.println("Time to find fields matching annotation : "+((end-start)));
|
||||
|
||||
assertNotNull(fields);
|
||||
assertEquals(1, fields.size());
|
||||
|
||||
Field m = ClassA.class.getDeclaredField("m");
|
||||
assertTrue(fields.contains(m));
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.Resources;
|
||||
|
@ -26,6 +27,8 @@ import javax.naming.InitialContext;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
import org.eclipse.jetty.annotations.resources.ResourceA;
|
||||
import org.eclipse.jetty.annotations.resources.ResourceB;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
|
@ -33,6 +36,8 @@ import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
|||
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
|
||||
import org.eclipse.jetty.plus.annotation.RunAsCollection;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
|
@ -43,6 +48,32 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
public class TestAnnotationInheritance extends TestCase
|
||||
{
|
||||
List<String> classNames = new ArrayList<String>();
|
||||
|
||||
|
||||
class SampleHandler implements AnnotationHandler
|
||||
{
|
||||
public final List<String> annotatedClassNames = new ArrayList<String>();
|
||||
public final List<String> annotatedMethods = new ArrayList<String>();
|
||||
public final List<String> annotatedFields = new ArrayList<String>();
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
annotatedClassNames.add(className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
annotatedFields.add(className+"."+fieldName);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
annotatedMethods.add(className+"."+methodName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void tearDown () throws Exception
|
||||
|
@ -53,14 +84,17 @@ public class TestAnnotationInheritance extends TestCase
|
|||
comp.destroySubcontext("env");
|
||||
}
|
||||
|
||||
public void testInheritance ()
|
||||
|
||||
public void testParseClassNames ()
|
||||
throws Exception
|
||||
{
|
||||
classNames.add(ClassA.class.getName());
|
||||
classNames.add(ClassB.class.getName());
|
||||
|
||||
AnnotationFinder finder = new AnnotationFinder();
|
||||
finder.find(classNames, new ClassNameResolver ()
|
||||
SampleHandler handler = new SampleHandler();
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
|
||||
parser.parse(classNames, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
|
@ -72,24 +106,73 @@ public class TestAnnotationInheritance extends TestCase
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
List<Class<?>> classes = finder.getClassesForAnnotation(Sample.class);
|
||||
assertEquals(2, classes.size());
|
||||
|
||||
//check we got 2 class annotations
|
||||
assertEquals(2, handler.annotatedClassNames.size());
|
||||
|
||||
//check methods
|
||||
//List methods = collection.getMethods();
|
||||
List<Method> methods = finder.getMethodsForAnnotation(Sample.class);
|
||||
//check we got all annotated methods on each class
|
||||
assertEquals (7, handler.annotatedMethods.size());
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.a"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.b"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.c"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.d"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.l"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.a"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.c"));
|
||||
|
||||
//check we got all annotated fields on each class
|
||||
assertEquals(1, handler.annotatedFields.size());
|
||||
assertEquals("org.eclipse.jetty.annotations.ClassA.m", handler.annotatedFields.get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void testParseClass ()
|
||||
throws Exception
|
||||
{
|
||||
SampleHandler handler = new SampleHandler();
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
|
||||
parser.parse(ClassB.class, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
|
||||
assertTrue(methods!=null);
|
||||
assertFalse(methods.isEmpty());
|
||||
//check we got 2 class annotations
|
||||
assertEquals(2, handler.annotatedClassNames.size());
|
||||
|
||||
//check we got all annotated methods on each class
|
||||
assertEquals (7, handler.annotatedMethods.size());
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.a"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.b"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.c"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.d"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassA.l"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.a"));
|
||||
assertTrue (handler.annotatedMethods.contains("org.eclipse.jetty.annotations.ClassB.c"));
|
||||
|
||||
//check we got all annotated fields on each class
|
||||
assertEquals(1, handler.annotatedFields.size());
|
||||
assertEquals("org.eclipse.jetty.annotations.ClassA.m", handler.annotatedFields.get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testExclusions()
|
||||
throws Exception
|
||||
{
|
||||
AnnotationFinder finder = new AnnotationFinder();
|
||||
finder.find(ClassA.class.getName(), new ClassNameResolver()
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
SampleHandler handler = new SampleHandler();
|
||||
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
|
||||
parser.parse(ClassA.class.getName(), new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
|
@ -101,9 +184,15 @@ public class TestAnnotationInheritance extends TestCase
|
|||
return false;
|
||||
}
|
||||
});
|
||||
assertTrue(finder.getClassesForAnnotation(Sample.class).isEmpty());
|
||||
|
||||
finder.find (ClassA.class.getName(), new ClassNameResolver()
|
||||
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 (ClassA.class.getName(), new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
|
@ -115,136 +204,45 @@ public class TestAnnotationInheritance extends TestCase
|
|||
return false;
|
||||
}
|
||||
});
|
||||
assertEquals(1, finder.getClassesForAnnotation(Sample.class).size());
|
||||
assertEquals (1, handler.annotatedClassNames.size());
|
||||
}
|
||||
|
||||
|
||||
public void testResourceAnnotations ()
|
||||
|
||||
public void testTypeInheritanceHandling ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
ClassInheritanceHandler handler = new ClassInheritanceHandler();
|
||||
parser.registerClassHandler(handler);
|
||||
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||
|
||||
|
||||
classNames.add(ResourceA.class.getName());
|
||||
classNames.add(ResourceB.class.getName());
|
||||
AnnotationFinder finder = new AnnotationFinder();
|
||||
finder.find(classNames, new ClassNameResolver()
|
||||
class Foo implements InterfaceD
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
List<Class<?>> resourcesClasses = finder.getClassesForAnnotation(Resources.class);
|
||||
assertNotNull(resourcesClasses);
|
||||
assertEquals(1, resourcesClasses.size());
|
||||
|
||||
List<Class<?>> annotatedClasses = finder.getClassesForAnnotation(Resource.class);
|
||||
List<Method> annotatedMethods = finder.getMethodsForAnnotation(Resource.class);
|
||||
List<Field> annotatedFields = finder.getFieldsForAnnotation(Resource.class);
|
||||
assertNotNull(annotatedClasses);
|
||||
assertEquals(0, annotatedClasses.size());
|
||||
assertEquals(3, annotatedMethods.size());
|
||||
assertEquals(6, annotatedFields.size());
|
||||
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
LifeCycleCallbackCollection callbacks = new LifeCycleCallbackCollection();
|
||||
wac.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, callbacks);
|
||||
RunAsCollection runAses = new RunAsCollection();
|
||||
wac.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAses);
|
||||
AnnotationProcessor processor = new AnnotationProcessor(wac, finder);
|
||||
//process with all the specific annotations turned into injections, callbacks etc
|
||||
processor.process();
|
||||
|
||||
//processing classA should give us these jndi name bindings:
|
||||
// java:comp/env/myf
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/g
|
||||
// java:comp/env/mye
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/h
|
||||
// java:comp/env/resA
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceB/f
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/n
|
||||
//
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("myf"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("mye"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("resA"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n"));
|
||||
|
||||
//we should have Injections
|
||||
assertNotNull(injections);
|
||||
|
||||
List<Injection> fieldInjections = injections.getFieldInjections(ResourceB.class);
|
||||
assertNotNull(fieldInjections);
|
||||
|
||||
Iterator itor = fieldInjections.iterator();
|
||||
System.err.println("Field injections:");
|
||||
while (itor.hasNext())
|
||||
{
|
||||
System.err.println(itor.next());
|
||||
|
||||
}
|
||||
//only 1 field injection because the other has no Resource mapping
|
||||
assertEquals(1, fieldInjections.size());
|
||||
|
||||
fieldInjections = injections.getFieldInjections(ResourceA.class);
|
||||
assertNotNull(fieldInjections);
|
||||
assertEquals(4, fieldInjections.size());
|
||||
classNames.clear();
|
||||
classNames.add(ClassA.class.getName());
|
||||
classNames.add(ClassB.class.getName());
|
||||
classNames.add(InterfaceD.class.getName());
|
||||
classNames.add(Foo.class.getName());
|
||||
|
||||
|
||||
List<Injection> methodInjections = injections.getMethodInjections(ResourceB.class);
|
||||
itor = methodInjections.iterator();
|
||||
System.err.println("Method injections:");
|
||||
while (itor.hasNext())
|
||||
System.err.println(itor.next());
|
||||
parser.parse(classNames, null);
|
||||
|
||||
assertNotNull(methodInjections);
|
||||
assertEquals(0, methodInjections.size());
|
||||
|
||||
methodInjections = injections.getMethodInjections(ResourceA.class);
|
||||
assertNotNull(methodInjections);
|
||||
assertEquals(3, methodInjections.size());
|
||||
|
||||
//test injection
|
||||
ResourceB binst = new ResourceB();
|
||||
injections.inject(binst);
|
||||
|
||||
//check injected values
|
||||
Field f = ResourceB.class.getDeclaredField ("f");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceB.getObjectToBind() , f.get(binst));
|
||||
|
||||
//@Resource(mappedName="resA") //test the default naming scheme but using a mapped name from the environment
|
||||
f = ResourceA.class.getDeclaredField("g");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceA.getObjectToBind(), f.get(binst));
|
||||
|
||||
//@Resource(name="resA") //test using the given name as the name from the environment
|
||||
f = ResourceA.class.getDeclaredField("j");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceA.getObjectToBind(), f.get(binst));
|
||||
|
||||
//@Resource(mappedName="resB") //test using the default name on an inherited field
|
||||
f = ResourceA.class.getDeclaredField("n");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceB.getObjectToBind(), f.get(binst));
|
||||
MultiMap map = handler.getMap();
|
||||
assertNotNull(map);
|
||||
assertFalse(map.isEmpty());
|
||||
assertEquals(2, map.size());
|
||||
Map stringArrayMap = map.toStringArrayMap();
|
||||
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
|
||||
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
|
||||
String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA");
|
||||
assertEquals(1, classes.length);
|
||||
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
|
||||
|
||||
classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD");
|
||||
assertEquals(2, classes.length);
|
||||
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
|
||||
assertEquals(Foo.class.getName(), classes[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.annotations;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
|
||||
|
||||
|
||||
|
||||
public class TestAnnotationParser extends TestCase
|
||||
{
|
||||
|
||||
public void testSampleAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
|
||||
|
||||
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassA"};
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
|
||||
class SampleAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
List<String> methods = Arrays.asList("a", "b", "c", "d", "l");
|
||||
|
||||
|
||||
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("org.eclipse.jetty.annotations.ClassA", className);
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("m", fieldName);
|
||||
assertEquals (org.objectweb.asm.Type.OBJECT, org.objectweb.asm.Type.getType(fieldType).getSort());
|
||||
assertEquals (1, values.size());
|
||||
Value anv1 = values.get(0);
|
||||
assertEquals ("value", anv1.getName());
|
||||
assertEquals (7, anv1.getValue());
|
||||
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals("org.eclipse.jetty.annotations.ClassA", className);
|
||||
assertTrue(methods.contains(methodName));
|
||||
assertEquals("org.eclipse.jetty.annotations.Sample", annotation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", new SampleAnnotationHandler());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
parser.parse(classNames, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.err.println("Time to parse class: "+((end-start)));
|
||||
}
|
||||
|
||||
|
||||
public void testMultiAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
String[] classNames = new String[]{"org.eclipse.jetty.annotations.ClassB"};
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
|
||||
class MultiAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
|
||||
|
||||
for (Value anv: values)
|
||||
{
|
||||
System.err.println(anv.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
//there should not be any
|
||||
fail();
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
|
||||
assertTrue("a".equals(methodName));
|
||||
for (Value anv: values)
|
||||
{
|
||||
System.err.println(anv.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Multi", new MultiAnnotationHandler());
|
||||
parser.parse(classNames, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.AnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.Value;
|
||||
|
||||
/**
|
||||
* TestServletAnnotations
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TestServletAnnotations extends TestCase
|
||||
{
|
||||
|
||||
|
||||
public void testServletAnnotation()
|
||||
throws Exception
|
||||
{
|
||||
List<String> classes = new ArrayList<String>();
|
||||
classes.add("org.eclipse.jetty.annotations.ServletC");
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
|
||||
|
||||
|
||||
class ResourceAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("org.eclipse.jetty.annotations.ServletC", className);
|
||||
|
||||
assertEquals ("foo",fieldName);
|
||||
assertNotNull (values);
|
||||
assertNotNull (annotation);
|
||||
assertTrue (annotation.endsWith("Resource"));
|
||||
assertEquals (1, values.size());
|
||||
Value anv = values.get(0);
|
||||
assertEquals ("mappedName", anv.getName());
|
||||
assertEquals ("foo", anv.getValue());
|
||||
System.err.print(annotation+": ");
|
||||
System.err.println(anv);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CallbackAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertEquals ("org.eclipse.jetty.annotations.ServletC", className);
|
||||
assertNotNull(methodName);
|
||||
if (methodName.endsWith("pre"))
|
||||
{
|
||||
assertTrue(annotation.endsWith("PreDestroy"));
|
||||
assertTrue(values.isEmpty());
|
||||
}
|
||||
else if (methodName.endsWith("post"))
|
||||
{
|
||||
assertTrue(annotation.endsWith("PostConstruct"));
|
||||
assertTrue(values.isEmpty());
|
||||
}
|
||||
System.err.println(annotation+": "+methodName);
|
||||
|
||||
}
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
}
|
||||
|
||||
class RunAsAnnotationHandler implements AnnotationHandler
|
||||
{
|
||||
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
|
||||
List<Value> values)
|
||||
{
|
||||
assertNotNull (values);
|
||||
assertEquals(1, values.size());
|
||||
Value anv = values.get(0);
|
||||
assertEquals("value", anv.getName());
|
||||
assertEquals("admin", anv.getValue());
|
||||
System.err.print(annotation+": ");
|
||||
System.err.println(anv);
|
||||
}
|
||||
|
||||
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
|
||||
List<Value> values)
|
||||
{}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", new ResourceAnnotationHandler ());
|
||||
parser.registerAnnotationHandler("javax.annotation.PostConstruct", new CallbackAnnotationHandler());
|
||||
parser.registerAnnotationHandler("javax.annotation.PreDestroy", new CallbackAnnotationHandler());
|
||||
parser.registerAnnotationHandler("javax.annotation.security.RunAs", new RunAsAnnotationHandler());
|
||||
|
||||
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
parser.parse(classes, new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.err.println("Time to parse class: "+((end-start)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package org.eclipse.jetty.annotations.resources;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser;
|
||||
import org.eclipse.jetty.annotations.ClassNameResolver;
|
||||
import org.eclipse.jetty.annotations.ResourceAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.ResourcesAnnotationHandler;
|
||||
import org.eclipse.jetty.plus.annotation.Injection;
|
||||
import org.eclipse.jetty.plus.annotation.InjectionCollection;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestResourceAnnotations extends TestCase
|
||||
{
|
||||
|
||||
public void testResourceAnnotations ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||
|
||||
|
||||
ArrayList<String> classNames = new ArrayList<String>();
|
||||
classNames.add(ResourceA.class.getName());
|
||||
classNames.add(ResourceB.class.getName());
|
||||
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac);
|
||||
parser.registerAnnotationHandler("javax.annotation.Resource", handler);
|
||||
parser.parse(classNames, new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
//processing classA should give us these jndi name bindings:
|
||||
// java:comp/env/myf
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/g
|
||||
// java:comp/env/mye
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/h
|
||||
// java:comp/env/resA
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceB/f
|
||||
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/n
|
||||
//
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("myf"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("mye"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("resA"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g"));
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n"));
|
||||
|
||||
//we should have Injections
|
||||
assertNotNull(injections);
|
||||
|
||||
List<Injection> fieldInjections = injections.getFieldInjections(ResourceB.class);
|
||||
assertNotNull(fieldInjections);
|
||||
|
||||
//only 1 field injection because the other has no Resource mapping
|
||||
assertEquals(1, fieldInjections.size());
|
||||
|
||||
Injection fi = fieldInjections.get(0);
|
||||
assertEquals ("f", fi.getTarget().getName());
|
||||
|
||||
fieldInjections = injections.getFieldInjections(ResourceA.class);
|
||||
assertNotNull(fieldInjections);
|
||||
assertEquals(4, fieldInjections.size());
|
||||
|
||||
|
||||
//no method injections on class ResourceB
|
||||
List<Injection> methodInjections = injections.getMethodInjections(ResourceB.class);
|
||||
assertNotNull(methodInjections);
|
||||
assertEquals(0, methodInjections.size());
|
||||
|
||||
//3 method injections on class ResourceA
|
||||
methodInjections = injections.getMethodInjections(ResourceA.class);
|
||||
assertNotNull(methodInjections);
|
||||
assertEquals(3, methodInjections.size());
|
||||
|
||||
//test injection
|
||||
ResourceB binst = new ResourceB();
|
||||
injections.inject(binst);
|
||||
|
||||
//check injected values
|
||||
Field f = ResourceB.class.getDeclaredField ("f");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceB.getObjectToBind() , f.get(binst));
|
||||
|
||||
//@Resource(mappedName="resA") //test the default naming scheme but using a mapped name from the environment
|
||||
f = ResourceA.class.getDeclaredField("g");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceA.getObjectToBind(), f.get(binst));
|
||||
|
||||
//@Resource(name="resA") //test using the given name as the name from the environment
|
||||
f = ResourceA.class.getDeclaredField("j");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceA.getObjectToBind(), f.get(binst));
|
||||
|
||||
//@Resource(mappedName="resB") //test using the default name on an inherited field
|
||||
f = ResourceA.class.getDeclaredField("n");
|
||||
f.setAccessible(true);
|
||||
assertEquals(resourceB.getObjectToBind(), f.get(binst));
|
||||
|
||||
comp.destroySubcontext("env");
|
||||
}
|
||||
|
||||
|
||||
public void testResourcesAnnotation ()
|
||||
throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setServer(server);
|
||||
InjectionCollection injections = new InjectionCollection();
|
||||
wac.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
InitialContext ic = new InitialContext();
|
||||
Context comp = (Context)ic.lookup("java:comp");
|
||||
Context env = comp.createSubcontext("env");
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
|
||||
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
|
||||
|
||||
|
||||
ArrayList<String> classNames = new ArrayList<String>();
|
||||
classNames.add(ResourceA.class.getName());
|
||||
classNames.add(ResourceB.class.getName());
|
||||
|
||||
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac);
|
||||
parser.registerAnnotationHandler("javax.annotation.Resources", handler);
|
||||
parser.parse(classNames, new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride(String name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(resourceA.getObjectToBind(), env.lookup("fluff"));
|
||||
assertEquals(resourceB.getObjectToBind(), env.lookup("stuff"));
|
||||
}
|
||||
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor.Descriptor;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
|
@ -54,8 +55,6 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
public abstract void bindUserTransaction (WebAppContext context) throws Exception;
|
||||
|
||||
public abstract void bindMessageDestinationRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
protected abstract void parseAnnotations (WebAppContext context) throws Exception;
|
||||
|
||||
|
||||
public class PlusWebXmlProcessor
|
||||
|
@ -66,7 +65,13 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
public void process (Descriptor d)
|
||||
throws Exception
|
||||
{
|
||||
if (d != null)
|
||||
process(d.getRoot());
|
||||
}
|
||||
|
||||
public void process (XmlParser.Node root)
|
||||
throws Exception
|
||||
|
@ -403,7 +408,7 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
InjectionCollection injections = new InjectionCollection();
|
||||
context.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
|
||||
RunAsCollection runAsCollection = new RunAsCollection();
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
|
||||
context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
|
||||
}
|
||||
|
||||
public void configure (WebAppContext context)
|
||||
|
@ -420,20 +425,16 @@ public abstract class AbstractConfiguration implements Configuration
|
|||
PlusWebXmlProcessor plusProcessor = new PlusWebXmlProcessor(context);
|
||||
plusProcessor.process(webXmlProcessor.getWebDefault());
|
||||
plusProcessor.process(webXmlProcessor.getWebXml());
|
||||
|
||||
//TODO: can web-fragment contain resource-ref and injection-targets?
|
||||
for (XmlParser.Node frag: webXmlProcessor.getFragments())
|
||||
|
||||
//Process plus-elements of each descriptor
|
||||
for (Descriptor frag: webXmlProcessor.getFragments())
|
||||
{
|
||||
plusProcessor.process(frag);
|
||||
|
||||
}
|
||||
|
||||
//process the override-web.xml descriptor
|
||||
plusProcessor.process(webXmlProcessor.getOverrideWeb());
|
||||
|
||||
|
||||
//parse classes for annotations, if necessary
|
||||
if (!webXmlProcessor.isMetaDataComplete())
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Processing annotations");
|
||||
parseAnnotations(context);
|
||||
}
|
||||
|
||||
//configure injections and callbacks to be called by the FilterHolder and ServletHolder
|
||||
//when they lazily instantiate the Filter/Servlet.
|
||||
|
|
|
@ -143,7 +143,7 @@ public class Configuration extends AbstractConfiguration
|
|||
//lock this webapp's java:comp namespace as per J2EE spec
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
lockCompEnv();
|
||||
lockCompEnv(context);
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
|
||||
|
@ -151,42 +151,52 @@ public class Configuration extends AbstractConfiguration
|
|||
{
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
unlockCompEnv();
|
||||
unlockCompEnv(context);
|
||||
_key = null;
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
super.deconfigure (context);
|
||||
}
|
||||
|
||||
protected void lockCompEnv ()
|
||||
protected void lockCompEnv (WebAppContext wac)
|
||||
throws Exception
|
||||
{
|
||||
Random random = new Random ();
|
||||
_key = new Integer(random.nextInt());
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup("java:comp");
|
||||
compCtx.addToEnvironment("org.eclipse.jndi.lock", _key);
|
||||
ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
try
|
||||
{
|
||||
Random random = new Random ();
|
||||
_key = new Integer(random.nextInt());
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup("java:comp");
|
||||
compCtx.addToEnvironment("org.eclipse.jndi.lock", _key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
|
||||
protected void unlockCompEnv ()
|
||||
protected void unlockCompEnv (WebAppContext wac)
|
||||
throws Exception
|
||||
{
|
||||
if (_key!=null)
|
||||
{ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
|
||||
try
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup("java:comp");
|
||||
compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
|
||||
*/
|
||||
public void parseAnnotations(WebAppContext context) throws Exception
|
||||
{
|
||||
//Noop unless you want to do annotation discovery.
|
||||
//Use org.eclipse.jetty.annotations.Configuration instead.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind a resource with the given name from web.xml of the given type
|
||||
* with a jndi resource from either the server or the webapp's naming
|
||||
|
|
|
@ -58,7 +58,8 @@ public class EnvConfiguration implements Configuration
|
|||
*/
|
||||
public void preConfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
|
||||
//create a java:comp/env
|
||||
createEnvContext(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,9 +67,6 @@ public class EnvConfiguration implements Configuration
|
|||
*/
|
||||
public void configure (WebAppContext context) throws Exception
|
||||
{
|
||||
//create a java:comp/env - do this here instead of preConfigure because it needs the
|
||||
//webapp classloader set up, which only happens in WebInfConfiguration.configure() step.
|
||||
createEnvContext();
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Created java:comp/env for webapp "+context.getContextPath());
|
||||
|
||||
|
@ -96,7 +94,7 @@ public class EnvConfiguration implements Configuration
|
|||
XmlConfiguration configuration = new XmlConfiguration(jettyEnvXmlUrl);
|
||||
configuration.configure(context);
|
||||
}
|
||||
|
||||
|
||||
//add java:comp/env entries for any EnvEntries that have been defined so far
|
||||
bindEnvEntries(context);
|
||||
}
|
||||
|
@ -193,11 +191,20 @@ public class EnvConfiguration implements Configuration
|
|||
}
|
||||
}
|
||||
|
||||
protected void createEnvContext ()
|
||||
protected void createEnvContext (WebAppContext wac)
|
||||
throws NamingException
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup ("java:comp");
|
||||
compCtx.createSubcontext("env");
|
||||
ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
try
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
Context compCtx = (Context)context.lookup ("java:comp");
|
||||
compCtx.createSubcontext("env");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.eclipse.jetty.plus.jndi.EnvEntry;
|
|||
import org.eclipse.jetty.plus.jndi.NamingEntry;
|
||||
import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class TestConfiguration extends TestCase
|
||||
|
@ -37,84 +38,96 @@ public class TestConfiguration extends TestCase
|
|||
public void testIt ()
|
||||
throws Exception
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
|
||||
Server server = new Server();
|
||||
|
||||
WebAppContext wac = new MyWebAppContext();
|
||||
wac.setServer(server);
|
||||
|
||||
//bind some EnvEntrys at the server level
|
||||
EnvEntry ee1 = new EnvEntry(server, "xxx/a", "100", true);
|
||||
EnvEntry ee2 = new EnvEntry(server, "yyy/b", "200", false);
|
||||
EnvEntry ee3 = new EnvEntry(server, "zzz/c", "300", false);
|
||||
EnvEntry ee4 = new EnvEntry(server, "zzz/d", "400", false);
|
||||
EnvEntry ee5 = new EnvEntry(server, "zzz/f", "500", true);
|
||||
|
||||
//bind some EnvEntrys at the webapp level
|
||||
EnvEntry ee6 = new EnvEntry(wac, "xxx/a", "900", true);
|
||||
EnvEntry ee7 = new EnvEntry(wac, "yyy/b", "910", true);
|
||||
EnvEntry ee8 = new EnvEntry(wac, "zzz/c", "920", false);
|
||||
EnvEntry ee9 = new EnvEntry(wac, "zzz/e", "930", false);
|
||||
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "xxx/a"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "yyy/b"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "zzz/c"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "zzz/d"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "xxx/a"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "yyy/b"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/c"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/e"));
|
||||
|
||||
Configuration config = new Configuration();
|
||||
|
||||
EnvConfiguration envConfig = new EnvConfiguration();
|
||||
|
||||
envConfig.preConfigure(wac);
|
||||
envConfig.configure(wac);
|
||||
envConfig.bindEnvEntries(wac);
|
||||
|
||||
String val = (String)ic.lookup("java:comp/env/xxx/a");
|
||||
assertEquals("900", val); //webapp naming overrides server
|
||||
val = (String)ic.lookup("java:comp/env/yyy/b");
|
||||
assertEquals("910", val);//webapp overrides server
|
||||
val = (String)ic.lookup("java:comp/env/zzz/c");
|
||||
assertEquals("920",val);//webapp overrides server
|
||||
val = (String)ic.lookup("java:comp/env/zzz/d");
|
||||
assertEquals("400", val);//from server naming
|
||||
val = (String)ic.lookup("java:comp/env/zzz/e");
|
||||
assertEquals("930", val);//from webapp naming
|
||||
|
||||
NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/xxx/a");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/yyy/b");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/c");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/d");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/e");
|
||||
assertNotNull(ne);
|
||||
|
||||
config.bindEnvEntry(wac, "foo", "99");
|
||||
assertEquals("99",ic.lookup( "java:comp/env/foo"));
|
||||
|
||||
config.bindEnvEntry(wac, "xxx/a", "7");
|
||||
assertEquals("900", ic.lookup("java:comp/env/xxx/a")); //webapp overrides web.xml
|
||||
config.bindEnvEntry(wac, "yyy/b", "7");
|
||||
assertEquals("910", ic.lookup("java:comp/env/yyy/b"));//webapp overrides web.xml
|
||||
config.bindEnvEntry(wac,"zzz/c", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/c"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/d", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/d"));//server does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/e", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/e"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/f", "7");
|
||||
assertEquals("500", ic.lookup("java:comp/env/zzz/f"));//server overrides web.xml
|
||||
|
||||
((Context)ic.lookup("java:comp")).destroySubcontext("env");
|
||||
ic.destroySubcontext("xxx");
|
||||
ic.destroySubcontext("yyy");
|
||||
ic.destroySubcontext("zzz");
|
||||
ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
try
|
||||
{
|
||||
InitialContext ic = new InitialContext();
|
||||
|
||||
Server server = new Server();
|
||||
|
||||
WebAppContext wac = new MyWebAppContext();
|
||||
wac.setServer(server);
|
||||
wac.setClassLoader(new WebAppClassLoader(Thread.currentThread().getContextClassLoader(), wac));
|
||||
|
||||
//bind some EnvEntrys at the server level
|
||||
EnvEntry ee1 = new EnvEntry(server, "xxx/a", "100", true);
|
||||
EnvEntry ee2 = new EnvEntry(server, "yyy/b", "200", false);
|
||||
EnvEntry ee3 = new EnvEntry(server, "zzz/c", "300", false);
|
||||
EnvEntry ee4 = new EnvEntry(server, "zzz/d", "400", false);
|
||||
EnvEntry ee5 = new EnvEntry(server, "zzz/f", "500", true);
|
||||
|
||||
//bind some EnvEntrys at the webapp level
|
||||
EnvEntry ee6 = new EnvEntry(wac, "xxx/a", "900", true);
|
||||
EnvEntry ee7 = new EnvEntry(wac, "yyy/b", "910", true);
|
||||
EnvEntry ee8 = new EnvEntry(wac, "zzz/c", "920", false);
|
||||
EnvEntry ee9 = new EnvEntry(wac, "zzz/e", "930", false);
|
||||
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "xxx/a"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "yyy/b"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "zzz/c"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(server, "zzz/d"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "xxx/a"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "yyy/b"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/c"));
|
||||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/e"));
|
||||
|
||||
Configuration config = new Configuration();
|
||||
|
||||
EnvConfiguration envConfig = new EnvConfiguration();
|
||||
|
||||
|
||||
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
|
||||
envConfig.preConfigure(wac);
|
||||
envConfig.configure(wac);
|
||||
envConfig.bindEnvEntries(wac);
|
||||
|
||||
String val = (String)ic.lookup("java:comp/env/xxx/a");
|
||||
assertEquals("900", val); //webapp naming overrides server
|
||||
val = (String)ic.lookup("java:comp/env/yyy/b");
|
||||
assertEquals("910", val);//webapp overrides server
|
||||
val = (String)ic.lookup("java:comp/env/zzz/c");
|
||||
assertEquals("920",val);//webapp overrides server
|
||||
val = (String)ic.lookup("java:comp/env/zzz/d");
|
||||
assertEquals("400", val);//from server naming
|
||||
val = (String)ic.lookup("java:comp/env/zzz/e");
|
||||
assertEquals("930", val);//from webapp naming
|
||||
|
||||
NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/xxx/a");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/yyy/b");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/c");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/d");
|
||||
assertNotNull(ne);
|
||||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/e");
|
||||
assertNotNull(ne);
|
||||
|
||||
config.bindEnvEntry(wac, "foo", "99");
|
||||
assertEquals("99",ic.lookup( "java:comp/env/foo"));
|
||||
|
||||
config.bindEnvEntry(wac, "xxx/a", "7");
|
||||
assertEquals("900", ic.lookup("java:comp/env/xxx/a")); //webapp overrides web.xml
|
||||
config.bindEnvEntry(wac, "yyy/b", "7");
|
||||
assertEquals("910", ic.lookup("java:comp/env/yyy/b"));//webapp overrides web.xml
|
||||
config.bindEnvEntry(wac,"zzz/c", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/c"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/d", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/d"));//server does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/e", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/e"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry(wac,"zzz/f", "7");
|
||||
assertEquals("500", ic.lookup("java:comp/env/zzz/f"));//server overrides web.xml
|
||||
|
||||
((Context)ic.lookup("java:comp")).destroySubcontext("env");
|
||||
ic.destroySubcontext("xxx");
|
||||
ic.destroySubcontext("yyy");
|
||||
ic.destroySubcontext("zzz");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old_loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<name>Jetty :: Web Applications</name>
|
||||
<description>Jetty web application</description>
|
||||
<name>Jetty :: Webapp Application Support</name>
|
||||
<description>Jetty web application support</description>
|
||||
<build>
|
||||
<resources>
|
||||
<resource><directory>src/main/resources</directory></resource>
|
||||
|
|
|
@ -91,7 +91,7 @@ public class FragmentConfiguration implements Configuration
|
|||
{
|
||||
for (Resource frag : frags)
|
||||
{
|
||||
processor.parseFragment("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml");
|
||||
processor.parseFragment(Resource.newResource("jar:"+frag.getURL()+"!/META-INF/web-fragment.xml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,9 @@ package org.eclipse.jetty.webapp;
|
|||
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
@ -39,12 +37,17 @@ public class MetaInfConfiguration implements Configuration
|
|||
public static final String METAINF_TLDS = TagLibConfiguration.TLD_RESOURCES;
|
||||
public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES;
|
||||
public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_URLS;
|
||||
public static final String JAR_RESOURCES = WebInfConfiguration.JAR_RESOURCES;
|
||||
public static final String CONTAINER_JAR_RESOURCES = WebInfConfiguration.CONTAINER_JAR_RESOURCES;
|
||||
public static final String WEB_INF_JAR_RESOURCES = WebInfConfiguration.WEB_INF_JAR_RESOURCES;
|
||||
|
||||
public void preConfigure(final WebAppContext context) throws Exception
|
||||
{
|
||||
|
||||
//Merge all container and webinf lib jars to look for META-INF resources
|
||||
|
||||
ArrayList<Resource> jars = new ArrayList<Resource>();
|
||||
jars.addAll((List<Resource>)context.getAttribute(CONTAINER_JAR_RESOURCES));
|
||||
jars.addAll((List<Resource>)context.getAttribute(WEB_INF_JAR_RESOURCES));
|
||||
|
||||
JarScanner scanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URI jarUri, JarEntry entry)
|
||||
|
@ -60,14 +63,13 @@ public class MetaInfConfiguration implements Configuration
|
|||
}
|
||||
};
|
||||
|
||||
List<Resource> jarResources = (List<Resource>)context.getAttribute(JAR_RESOURCES);
|
||||
|
||||
//Scan jars for META-INF information
|
||||
if (jarResources != null)
|
||||
if (jars != null)
|
||||
{
|
||||
URI[] uris = new URI[jarResources.size()];
|
||||
URI[] uris = new URI[jars.size()];
|
||||
int i=0;
|
||||
for (Resource r : jarResources)
|
||||
for (Resource r : jars)
|
||||
{
|
||||
uris[i++] = r.getURI();
|
||||
}
|
||||
|
|
|
@ -50,9 +50,6 @@ public class TagLibConfiguration implements Configuration
|
|||
{
|
||||
public static final String TLD_RESOURCES = "org.eclipse.jetty.tlds";
|
||||
|
||||
// TODO support patterns
|
||||
private static final String __web_inf_pattern = "org.eclipse.jetty.webapp.WebInfIncludeTLDJarPattern";
|
||||
private static final String __container_pattern = "org.eclipse.jetty.server.webapp.ContainerIncludeTLDJarPattern";
|
||||
|
||||
public class TldProcessor
|
||||
{
|
||||
|
@ -240,7 +237,9 @@ public class TagLibConfiguration implements Configuration
|
|||
}
|
||||
|
||||
|
||||
// Add in tlds found in META-INF of jars
|
||||
// Add in tlds found in META-INF of jars. The jars that will be scanned are controlled by
|
||||
// the patterns defined in the context attributes: org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern,
|
||||
// and org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern
|
||||
Collection<Resource> tld_resources=(Collection<Resource>)context.getAttribute(TLD_RESOURCES);
|
||||
if (tld_resources!=null)
|
||||
tlds.addAll(tld_resources);
|
||||
|
|
|
@ -21,10 +21,6 @@ import java.util.EventListener;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSessionActivationListener;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
@ -39,13 +35,11 @@ import org.eclipse.jetty.server.session.SessionHandler;
|
|||
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.JarResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -115,7 +109,7 @@ public class WebAppContext extends ServletContextHandler
|
|||
|
||||
private Map _resourceAliases;
|
||||
private boolean _ownClassLoader=false;
|
||||
private boolean _configurationDiscovered=false;
|
||||
private boolean _configurationDiscovered=true;
|
||||
|
||||
public static ContextHandler getCurrentWebAppContext()
|
||||
{
|
||||
|
@ -338,6 +332,8 @@ public class WebAppContext extends ServletContextHandler
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Prepare for configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].preConfigure(this);
|
||||
|
|
|
@ -21,7 +21,8 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
|
|||
public class WebInfConfiguration implements Configuration
|
||||
{
|
||||
public static final String TEMPDIR_CREATED = "org.eclipse.jetty.tmpdirCreated";
|
||||
public static final String JAR_RESOURCES = "org.eclipse.jetty.jarList";
|
||||
public static final String CONTAINER_JAR_RESOURCES = "org.eclipse.jetty.containerJars";
|
||||
public static final String WEB_INF_JAR_RESOURCES = "org.eclipse.jetty.webInfJars";
|
||||
public static final String CONTAINER_JAR_PATTERN = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
|
||||
public static final String WEBINF_JAR_PATTERN = "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern";
|
||||
|
||||
|
@ -53,19 +54,18 @@ public class WebInfConfiguration implements Configuration
|
|||
tmp = (String)context.getAttribute(CONTAINER_JAR_PATTERN);
|
||||
Pattern containerPattern = (tmp==null?null:Pattern.compile(tmp));
|
||||
|
||||
final ArrayList jarResources = new ArrayList<Resource>();
|
||||
context.setAttribute(JAR_RESOURCES, jarResources);
|
||||
|
||||
PatternMatcher jarNameMatcher = new PatternMatcher ()
|
||||
final ArrayList containerJarResources = new ArrayList<Resource>();
|
||||
context.setAttribute(CONTAINER_JAR_RESOURCES, containerJarResources);
|
||||
|
||||
//Apply ordering to container jars - if no pattern is specified, we won't
|
||||
//match any of the container jars
|
||||
PatternMatcher containerJarNameMatcher = new PatternMatcher ()
|
||||
{
|
||||
public void matched(URI uri) throws Exception
|
||||
{
|
||||
jarResources.add(Resource.newResource(uri));
|
||||
}
|
||||
|
||||
containerJarResources.add(Resource.newResource(uri));
|
||||
}
|
||||
};
|
||||
|
||||
//Apply ordering to container jars
|
||||
ClassLoader loader = context.getClassLoader();
|
||||
while (loader != null && (loader instanceof URLClassLoader))
|
||||
{
|
||||
|
@ -78,13 +78,21 @@ public class WebInfConfiguration implements Configuration
|
|||
{
|
||||
containerUris[i++] = u.toURI();
|
||||
}
|
||||
jarNameMatcher.match(containerPattern, containerUris, false);
|
||||
containerJarNameMatcher.match(containerPattern, containerUris, false);
|
||||
}
|
||||
loader = loader.getParent();
|
||||
}
|
||||
|
||||
//Apply ordering to WEB-INF/lib jars
|
||||
//Find all jars in WEB-INF
|
||||
final ArrayList webInfJarResources = new ArrayList<Resource>();
|
||||
context.setAttribute(WEB_INF_JAR_RESOURCES, webInfJarResources);
|
||||
PatternMatcher webInfJarNameMatcher = new PatternMatcher ()
|
||||
{
|
||||
public void matched(URI uri) throws Exception
|
||||
{
|
||||
webInfJarResources.add(Resource.newResource(uri));
|
||||
}
|
||||
};
|
||||
List<Resource> jars = findJars(context);
|
||||
//Convert to uris for matching
|
||||
URI[] uris = null;
|
||||
|
@ -97,7 +105,7 @@ public class WebInfConfiguration implements Configuration
|
|||
uris[i++] = r.getURI();
|
||||
}
|
||||
}
|
||||
jarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
|
||||
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintAware;
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
|
@ -71,9 +70,16 @@ public class WebXmlConfiguration implements Configuration
|
|||
Resource dftResource = Resource.newSystemResource(defaultsDescriptor);
|
||||
if (dftResource == null)
|
||||
dftResource = context.newResource(defaultsDescriptor);
|
||||
processor.parseDefaults (dftResource.getURL());
|
||||
processor.parseDefaults (dftResource);
|
||||
processor.processDefaults();
|
||||
}
|
||||
|
||||
//parse, but don't process web.xml
|
||||
Resource webxml = findWebXml(context);
|
||||
if (webxml != null)
|
||||
{
|
||||
processor.parseWebXml(webxml);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -98,13 +104,9 @@ public class WebXmlConfiguration implements Configuration
|
|||
context.setAttribute(WebXmlProcessor.WEB_PROCESSOR, processor);
|
||||
}
|
||||
|
||||
//process web.xml
|
||||
URL webxml = findWebXml(context);
|
||||
if (webxml != null)
|
||||
{
|
||||
processor.parseWebXml(webxml);
|
||||
processor.processWebXml();
|
||||
}
|
||||
//process web.xml (the effective web.xml???)
|
||||
processor.processWebXml();
|
||||
|
||||
|
||||
//process override-web.xml
|
||||
String overrideDescriptor = context.getOverrideDescriptor();
|
||||
|
@ -113,7 +115,7 @@ public class WebXmlConfiguration implements Configuration
|
|||
Resource orideResource = Resource.newSystemResource(overrideDescriptor);
|
||||
if (orideResource == null)
|
||||
orideResource = context.newResource(overrideDescriptor);
|
||||
processor.parseOverride(orideResource.getURL());
|
||||
processor.parseOverride(orideResource);
|
||||
processor.processOverride();
|
||||
}
|
||||
}
|
||||
|
@ -128,13 +130,13 @@ public class WebXmlConfiguration implements Configuration
|
|||
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
protected URL findWebXml(WebAppContext context) throws IOException, MalformedURLException
|
||||
protected Resource findWebXml(WebAppContext context) throws IOException, MalformedURLException
|
||||
{
|
||||
String descriptor = context.getDescriptor();
|
||||
if (descriptor != null)
|
||||
{
|
||||
Resource web = context.newResource(descriptor);
|
||||
if (web.exists() && !web.isDirectory()) return web.getURL();
|
||||
if (web.exists() && !web.isDirectory()) return web;
|
||||
}
|
||||
|
||||
Resource web_inf = context.getWebInf();
|
||||
|
@ -142,7 +144,7 @@ public class WebXmlConfiguration implements Configuration
|
|||
{
|
||||
// do web.xml file
|
||||
Resource web = web_inf.addPath("web.xml");
|
||||
if (web.exists()) return web.getURL();
|
||||
if (web.exists()) return web;
|
||||
Log.debug("No WEB-INF/web.xml in " + context.getWar() + ". Serving files and default/dynamic servlets only");
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -56,15 +56,16 @@ import org.eclipse.jetty.xml.XmlParser;
|
|||
public class WebXmlProcessor
|
||||
{
|
||||
public static final String WEB_PROCESSOR = "org.eclipse.jetty.webProcessor";
|
||||
public static final String METADATA_COMPLETE = "org.eclipse.jetty.metadataComplete";
|
||||
public static final String WEBXML_VERSION = "org.eclipse.jetty.webXmlVersion";
|
||||
public static final String WEBXML_CLASSNAMES = "org.eclipse.jetty.webXmlClassNames";
|
||||
|
||||
protected WebAppContext _context;
|
||||
protected XmlParser _xmlParser;
|
||||
protected XmlParser.Node _webDefaultsRoot;
|
||||
protected XmlParser.Node _webXmlRoot;
|
||||
protected List<XmlParser.Node> _webFragmentRoots = new ArrayList<XmlParser.Node>();
|
||||
protected XmlParser.Node _webOverrideRoot;
|
||||
protected int _version;
|
||||
protected boolean _metaDataComplete = false;
|
||||
protected Descriptor _webDefaultsRoot;
|
||||
protected Descriptor _webXmlRoot;
|
||||
protected List<Descriptor> _webFragmentRoots = new ArrayList<Descriptor>();
|
||||
protected Descriptor _webOverrideRoot;
|
||||
|
||||
protected ServletHandler _servletHandler;
|
||||
protected SecurityHandler _securityHandler;
|
||||
|
@ -83,6 +84,126 @@ public class WebXmlProcessor
|
|||
protected boolean _defaultWelcomeFileList;
|
||||
|
||||
|
||||
public class Descriptor
|
||||
{
|
||||
protected Resource _xml;
|
||||
protected XmlParser.Node _root;
|
||||
protected boolean _metadataComplete;
|
||||
protected boolean _hasOrdering;
|
||||
protected int _version;
|
||||
protected ArrayList<String> _classNames;
|
||||
|
||||
public Descriptor (Resource xml)
|
||||
{
|
||||
_xml = xml;
|
||||
}
|
||||
|
||||
public void parse ()
|
||||
throws Exception
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
_root = _xmlParser.parse(_xml.getURL().toString());
|
||||
processVersion();
|
||||
processOrdering();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMetaDataComplete()
|
||||
{
|
||||
return _metadataComplete;
|
||||
}
|
||||
|
||||
|
||||
public XmlParser.Node getRoot ()
|
||||
{
|
||||
return _root;
|
||||
}
|
||||
|
||||
public int getVersion ()
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
public Resource getResource ()
|
||||
{
|
||||
return _xml;
|
||||
}
|
||||
|
||||
public void process()
|
||||
throws Exception
|
||||
{
|
||||
WebXmlProcessor.this.process(_root);
|
||||
}
|
||||
|
||||
private void processVersion ()
|
||||
{
|
||||
String version = _root.getAttribute("version", "DTD");
|
||||
if ("2.5".equals(version))
|
||||
_version = 25;
|
||||
else if ("2.4".equals(version))
|
||||
_version = 24;
|
||||
else if ("3.0".equals(version))
|
||||
_version = 30;
|
||||
else if ("DTD".equals(version))
|
||||
{
|
||||
_version = 23;
|
||||
String dtd = _xmlParser.getDTD();
|
||||
if (dtd != null && dtd.indexOf("web-app_2_2") >= 0) _version = 22;
|
||||
}
|
||||
|
||||
if (_version < 25)
|
||||
_metadataComplete = true; // does not apply before 2.5
|
||||
else
|
||||
_metadataComplete = Boolean.valueOf((String)_root.getAttribute("metadata-complete", "false")).booleanValue();
|
||||
|
||||
Log.debug(_xml.toString()+": Calculated metadatacomplete = " + _metadataComplete + " with version=" + version);
|
||||
}
|
||||
|
||||
private void processOrdering ()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
private void processClassNames ()
|
||||
{
|
||||
_classNames = new ArrayList<String>();
|
||||
Iterator iter = _root.iterator();
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
XmlParser.Node node = (XmlParser.Node) o;
|
||||
String name = node.getTag();
|
||||
if ("servlet".equals(name))
|
||||
{
|
||||
String className = node.getString("servlet-class", false, true);
|
||||
if (className != null)
|
||||
_classNames.add(className);
|
||||
}
|
||||
else if ("filter".equals(name))
|
||||
{
|
||||
String className = node.getString("filter-class", false, true);
|
||||
if (className != null)
|
||||
_classNames.add(className);
|
||||
}
|
||||
else if ("listener".equals(name))
|
||||
{
|
||||
String className = node.getString("listener-class", false, true);
|
||||
if (className != null)
|
||||
_classNames.add(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<String> getClassNames ()
|
||||
{
|
||||
return _classNames;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static XmlParser webXmlParser() throws ClassNotFoundException
|
||||
|
@ -171,124 +292,89 @@ public class WebXmlProcessor
|
|||
_xmlParser = webXmlParser();
|
||||
}
|
||||
|
||||
|
||||
public int getVersion ()
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
public boolean isMetaDataComplete ()
|
||||
{
|
||||
return _metaDataComplete;
|
||||
}
|
||||
|
||||
public void processForVersion (XmlParser.Node config)
|
||||
{
|
||||
String version = config.getAttribute("version", "DTD");
|
||||
if ("2.5".equals(version))
|
||||
_version = 25;
|
||||
else if ("2.4".equals(version))
|
||||
_version = 24;
|
||||
else if ("3.0".equals(version))
|
||||
_version = 30;
|
||||
else if ("DTD".equals(version))
|
||||
{
|
||||
_version = 23;
|
||||
String dtd = _xmlParser.getDTD();
|
||||
if (dtd != null && dtd.indexOf("web-app_2_2") >= 0) _version = 22;
|
||||
}
|
||||
|
||||
if (_version < 25)
|
||||
_metaDataComplete = true; // does not apply before 2.5
|
||||
else
|
||||
_metaDataComplete = Boolean.valueOf((String) config.getAttribute("metadata-complete", "false")).booleanValue();
|
||||
|
||||
Log.debug("Calculated metadatacomplete = " + _metaDataComplete + " with version=" + version);
|
||||
|
||||
_context.setAttribute("metadata-complete", String.valueOf(_metaDataComplete));
|
||||
}
|
||||
|
||||
public XmlParser.Node parseDefaults (URL webDefaults)
|
||||
public void parseDefaults (Resource webDefaults)
|
||||
throws Exception
|
||||
{
|
||||
_webDefaultsRoot = _xmlParser.parse(webDefaults.toString());
|
||||
return _webDefaultsRoot;
|
||||
|
||||
_webDefaultsRoot = new Descriptor(webDefaults);
|
||||
_webDefaultsRoot.parse();
|
||||
}
|
||||
|
||||
public XmlParser.Node parseWebXml (URL webXml)
|
||||
public void parseWebXml (Resource webXml)
|
||||
throws Exception
|
||||
{
|
||||
_webXmlRoot = _xmlParser.parse(webXml.toString());
|
||||
processForVersion(_webXmlRoot);
|
||||
return _webXmlRoot;
|
||||
_webXmlRoot = new Descriptor(webXml);
|
||||
_webXmlRoot.parse();
|
||||
_webXmlRoot.processClassNames();
|
||||
_context.setAttribute(METADATA_COMPLETE, Boolean.valueOf(_webXmlRoot.isMetaDataComplete()));
|
||||
_context.setAttribute(WEBXML_VERSION, Integer.valueOf(_webXmlRoot.getVersion()));
|
||||
_context.setAttribute(WEBXML_CLASSNAMES, _webXmlRoot.getClassNames());
|
||||
}
|
||||
|
||||
public XmlParser.Node parseFragment (String fragment)
|
||||
public void parseFragment (Resource fragment)
|
||||
throws Exception
|
||||
{
|
||||
if (isMetaDataComplete())
|
||||
return null; //do not process anything else if main web.xml file is complete
|
||||
if (_webXmlRoot.isMetaDataComplete())
|
||||
return; //do not process anything else if main web.xml file is complete
|
||||
|
||||
//Metadata-complete is not set, or there is no web.xml
|
||||
XmlParser.Node root = _xmlParser.parse(fragment);
|
||||
_webFragmentRoots.add(root);
|
||||
return root;
|
||||
Descriptor frag = new Descriptor(fragment);
|
||||
frag.parse();
|
||||
_webFragmentRoots.add(frag);
|
||||
}
|
||||
|
||||
public XmlParser.Node parseOverride (URL override)
|
||||
public void parseOverride (Resource override)
|
||||
throws Exception
|
||||
{
|
||||
_xmlParser.setValidating(false);
|
||||
_webOverrideRoot = _xmlParser.parse(override.toString());
|
||||
return _webOverrideRoot;
|
||||
_webOverrideRoot = new Descriptor(override);
|
||||
_webOverrideRoot.parse();
|
||||
}
|
||||
|
||||
|
||||
public void processDefaults ()
|
||||
throws Exception
|
||||
{
|
||||
process (_webDefaultsRoot);
|
||||
_webDefaultsRoot.process();
|
||||
_defaultWelcomeFileList = _context.getWelcomeFiles() != null;
|
||||
}
|
||||
|
||||
public void processWebXml ()
|
||||
throws Exception
|
||||
{
|
||||
process (_webXmlRoot);
|
||||
_webXmlRoot.process();
|
||||
}
|
||||
|
||||
public void processFragments ()
|
||||
throws Exception
|
||||
{
|
||||
for (XmlParser.Node frag : _webFragmentRoots)
|
||||
for (Descriptor frag : _webFragmentRoots)
|
||||
{
|
||||
process (frag);
|
||||
frag.process();
|
||||
}
|
||||
}
|
||||
|
||||
public void processOverride ()
|
||||
throws Exception
|
||||
{
|
||||
process(_webOverrideRoot);
|
||||
_webOverrideRoot.process();
|
||||
}
|
||||
|
||||
public XmlParser.Node getWebXml ()
|
||||
public Descriptor getWebXml ()
|
||||
{
|
||||
return _webXmlRoot;
|
||||
}
|
||||
|
||||
public XmlParser.Node getOverrideWeb ()
|
||||
public Descriptor getOverrideWeb ()
|
||||
{
|
||||
return _webOverrideRoot;
|
||||
}
|
||||
|
||||
public XmlParser.Node getWebDefault ()
|
||||
public Descriptor getWebDefault ()
|
||||
{
|
||||
return _webDefaultsRoot;
|
||||
}
|
||||
|
||||
public List<XmlParser.Node> getFragments ()
|
||||
public List<Descriptor> getFragments ()
|
||||
{
|
||||
return _webFragmentRoots;
|
||||
}
|
||||
|
@ -469,9 +555,12 @@ public class WebXmlProcessor
|
|||
holder.setInitParameter(pname, pvalue);
|
||||
}
|
||||
|
||||
String async=node.getString("async-support",false,true);
|
||||
String async=node.getString("async-supported",false,true);
|
||||
if (async!=null)
|
||||
holder.setAsyncSupported(Boolean.valueOf(async));
|
||||
holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
|
||||
|
||||
String timeout=node.getString("async-timeout",false,true);
|
||||
// TODO set it
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -640,9 +729,12 @@ public class WebXmlProcessor
|
|||
holder.setRunAsRole(roleName);
|
||||
}
|
||||
|
||||
String async=node.getString("async-support",false,true);
|
||||
String async=node.getString("async-supported",false,true);
|
||||
if (async!=null)
|
||||
holder.setAsyncSupported(Boolean.valueOf(async));
|
||||
holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
|
||||
|
||||
String timeout=node.getString("async-timeout",false,true);
|
||||
// TODO set it
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
Loading…
Reference in New Issue