Author: markt Date: Mon Dec 7 14:18:29 2009 New Revision: 887929 URL: http://svn.apache.org/viewvc?rev=887929&view=rev Log: Add annotation support for WebServlet
Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=887929&r1=887928&r2=887929&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Mon Dec 7 14:18:29 2009 @@ -29,6 +29,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -40,6 +41,14 @@ import javax.servlet.ServletContext; +import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.ArrayElementValue; +import org.apache.tomcat.util.bcel.classfile.ClassFormatException; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.ElementValuePair; +import org.apache.tomcat.util.bcel.classfile.JavaClass; import org.apache.catalina.Authenticator; import org.apache.catalina.Container; import org.apache.catalina.Context; @@ -61,6 +70,7 @@ import org.apache.catalina.deploy.FilterMap; import org.apache.catalina.deploy.LoginConfig; import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.catalina.deploy.ServletDef; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.naming.resources.DirContextURLConnection; @@ -1586,8 +1596,8 @@ dcUrlConn = (DirContextURLConnection) urlConn; dcUrlConn.setUseCaches(false); - String ct = dcUrlConn.getContentType(); - if (ResourceAttributes.COLLECTION_TYPE.equals(ct)) { + String type = dcUrlConn.getHeaderField(ResourceAttributes.TYPE); + if (ResourceAttributes.COLLECTION_TYPE.equals(type)) { // Collection Enumeration<String> dirs = dcUrlConn.list(); while (dirs.hasMoreElements()) { @@ -1618,7 +1628,7 @@ } } } catch (IOException e) { - log.error(sm.getString("contextConfig.jarFile", url), e); + log.error(sm.getString("contextConfig.jndiUrl", url), e); } } @@ -1651,10 +1661,123 @@ } - protected void processAnnotationsStream(InputStream is, WebXml fragment) { - // TODO SERVLET 3 + protected void processAnnotationsStream(InputStream is, WebXml fragment) + throws ClassFormatException, IOException { + + ClassParser parser = new ClassParser(is, null); + JavaClass clazz = parser.parse(); + String className = clazz.getClassName(); + AnnotationEntry[] annotationsEntries = clazz.getAnnotationEntries(); + + for (AnnotationEntry ae : annotationsEntries) { + String type = ae.getAnnotationType(); + if ("Ljavax/servlet/annotation/WebServlet;".equals(type)) { + processAnnotationWebServlet(className, ae, fragment); + } else { + // TODO SERVLET 3 - Other annotations + // Unknown annotation - ignore + } + } + } + + protected void processAnnotationWebServlet(String className, + AnnotationEntry ae, WebXml fragment) { + if (fragment.getServlets().containsKey(className)) { + // Skip this annotation. Entry in web.xml takes priority + return; + } + boolean mappingSet = false; + ServletDef servletDef = new ServletDef(); + servletDef.setServletName(className); + servletDef.setServletClass(className); + String[] mappings = null; + + ElementValuePair[] evps = ae.getElementValuePairs(); + for (ElementValuePair evp : evps) { + String name = evp.getNameString(); + if ("value".equals(name) || "urlPatterns".equals(name)) { + if (mappingSet) { + throw new IllegalArgumentException(sm.getString( + "contextConfig.urlPatternValue", className)); + } + mappingSet = true; + mappings = processAnnotationsUrlPatterns(evp.getValue()); + } else if ("name".equals(name)) { + servletDef.setServletName(evp.getValue().stringifyValue()); + } else if ("description".equals(name)) { + servletDef.setDescription(evp.getValue().stringifyValue()); + } else if ("displayName".equals(name)) { + servletDef.setDisplayName(evp.getValue().stringifyValue()); + } else if ("largeIcon".equals(name)) { + servletDef.setLargeIcon(evp.getValue().stringifyValue()); + } else if ("smallIcon".equals(name)) { + servletDef.setSmallIcon(evp.getValue().stringifyValue()); + } else if ("asyncSupported".equals(name)) { + servletDef.setAsyncSupported(evp.getValue().stringifyValue()); + } else if ("loadOnStartup".equals(name)) { + servletDef.setLoadOnStartup(evp.getValue().stringifyValue()); + } else if ("initParams".equals(name)) { + Map<String,String> initParams = + processAnnotationWebInitParams(evp.getValue()); + for (String paramName : initParams.keySet()) { + servletDef.addInitParameter(paramName, + initParams.get(paramName)); + } + } else { + // Ignore + } + } + if (mappings != null) { + fragment.addServlet(servletDef); + for (String mapping : mappings) { + fragment.addServletMapping(mapping, + servletDef.getServletName()); + } + } } + protected String[] processAnnotationsUrlPatterns(ElementValue ev) { + ArrayList<String> values = new ArrayList<String>(); + if (ev instanceof ArrayElementValue) { + ElementValue[] arrayValues = + ((ArrayElementValue) ev).getElementValuesArray(); + for (ElementValue value : arrayValues) { + values.add(value.stringifyValue()); + } + } else { + values.add(ev.stringifyValue()); + } + String[] result = new String[values.size()]; + return values.toArray(result); + } + + protected Map<String,String> processAnnotationWebInitParams( + ElementValue ev) { + Map<String, String> result = new HashMap<String,String>(); + if (ev instanceof ArrayElementValue) { + ElementValue[] arrayValues = + ((ArrayElementValue) ev).getElementValuesArray(); + for (ElementValue value : arrayValues) { + if (value instanceof AnnotationElementValue) { + ElementValuePair[] evps = ((AnnotationElementValue) + value).getAnnotationEntry().getElementValuePairs(); + String initParamName = null; + String initParamValue = null; + for (ElementValuePair evp : evps) { + if ("name".equals(evp.getNameString())) { + initParamName = evp.getValue().stringifyValue(); + } else if ("value".equals(evp.getNameString())) { + initParamValue = evp.getValue().stringifyValue(); + } else { + // Ignore + } + } + result.put(initParamName, initParamValue); + } + } + } + return result; + } private class FragmentJarScannerCallback implements JarScannerCallback { Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=887929&r1=887928&r2=887929&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Mon Dec 7 14:18:29 2009 @@ -39,7 +39,7 @@ contextConfig.inputStreamFile=Unable to process file [{0}] for annotations contextConfig.inputStreamJar=Unable to process Jar entry [{0}] from Jar [{1}] for annotations contextConfig.inputStreamJndi=Unable to process resource element [{0}] for annotations -contextConfig.jarFile=Unable to process Jar [{0}] for annotations +contextConfig.jndiUrl=Unable to process JNDI URL [{0}] for annotations contextConfig.jarUrl=The connection created for URL [{0}] was not a JarUrlConnection contextConfig.jar=Unable to process resource [{0}] for annotations contextConfig.jndiUrl=The connection created for URL [{0}] was not a DirContextURLConnection @@ -51,6 +51,7 @@ contextConfig.stop=ContextConfig: Processing STOP contextConfig.unavailable=Marking this application unavailable due to previous error(s) contextConfig.unknownUrlProtocol=The URL protocol [{0}] was not recognised during annotation processing. URL [{1}] was ignored. +contextConfig.urlPatternValue=Both the UrlPattern and value attribute were set for the WebServlet annotation on class [{0}] contextConfig.webinfClassesUrl=Unable to determine URL for WEB-INF/classes contextConfig.xmlSettings=Context [{0}] will parse web.xml and web-fragment.xml files with validation:{1} and namespaceAware:{2} embedded.alreadyStarted=Embedded service has already been started --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org