Author: markt Date: Fri Jun 22 08:46:55 2012 New Revision: 1352803 URL: http://svn.apache.org/viewvc?rev=1352803&view=rev Log: metadata-complete does not control the processing of ServletContainerInitializers
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestContextConfigAnnotation.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1352799 Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1352803&r1=1352802&r2=1352803&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java Fri Jun 22 08:46:55 2012 @@ -1210,8 +1210,15 @@ public class ContextConfig implements Li * - As per SRV.1.6.2, Tomcat will scan for annotations regardless of * which Servlet spec version is declared in web.xml. The EG has * confirmed this is the expected behaviour. - * - This is not yet complete. Further clarifications (and possible code - * changes to follow). + * - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main + * web.xml is marked as metadata-complete, JARs are still processed + * for SCIs. + * - TBD. If metadata-complete=true and an absolute ordering is + * specified, are JARs excluded from the ordering also excluded from + * the SCI processing? Current assumption is that they are. + * - If an SCI has a @HandlesType annotation then all classes (except + * those in JARs excluded from an absolute ordering) need to be + * scanned to check if they match. */ Set<WebXml> defaults = new HashSet<WebXml>(); defaults.add(getDefaultWebXmlFragment()); @@ -1231,20 +1238,17 @@ public class ContextConfig implements Li // point. Map<String,WebXml> fragments = processJarsForWebFragments(); - // Only need to process fragments and annotations if metadata is - // not complete + // Step 2. Order the fragments. Set<WebXml> orderedFragments = null; - if (!webXml.isMetadataComplete()) { - // Step 2. Order the fragments. - orderedFragments = WebXml.orderWebFragments(webXml, fragments); + orderedFragments = WebXml.orderWebFragments(webXml, fragments); - // Step 3. Look for ServletContainerInitializer implementations - if (ok) { - processServletContainerInitializers(orderedFragments); - } + // Step 3. Look for ServletContainerInitializer implementations + if (ok) { + processServletContainerInitializers(orderedFragments); + } + if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) { // Step 4. Process /WEB-INF/classes for annotations - // This will add any matching classes to the typeInitializerMap if (ok) { // Hack required by Eclipse's "serve modules without // publishing" feature since this backs WEB-INF/classes by @@ -1263,13 +1267,15 @@ public class ContextConfig implements Li if (binding.getObject() instanceof FileDirContext) { File webInfClassDir = new File( ((FileDirContext) binding.getObject()).getDocBase()); - processAnnotationsFile(webInfClassDir, webXml); + processAnnotationsFile(webInfClassDir, webXml, + webXml.isMetadataComplete()); } else { String resource = "/WEB-INF/classes/" + binding.getName(); try { URL url = sContext.getResource(resource); - processAnnotationsUrl(url, webXml); + processAnnotationsUrl(url, webXml, + webXml.isMetadataComplete()); } catch (MalformedURLException e) { log.error(sm.getString( "contextConfig.webinfClassesUrl", @@ -1286,14 +1292,16 @@ public class ContextConfig implements Li // Step 5. Process JARs for annotations - only need to process // those fragments we are going to use - // This will add any matching classes to the typeInitializerMap if (ok) { - processAnnotations(orderedFragments); + processAnnotations( + orderedFragments, webXml.isMetadataComplete()); } // Cache, if used, is no longer required so clear it javaClassCache.clear(); + } + if (!webXml.isMetadataComplete()) { // Step 6. Merge web-fragment.xml files into the main web.xml // file. if (ok) { @@ -1352,22 +1360,18 @@ public class ContextConfig implements Li // WEB-INF/classes/META-INF/resources configuration } - // Only look for ServletContainerInitializer if metadata is not - // complete - if (!webXml.isMetadataComplete()) { - // Step 11. Apply the ServletContainerInitializer config to the - // context - if (ok) { - for (Map.Entry<ServletContainerInitializer, - Set<Class<?>>> entry : - initializerClassMap.entrySet()) { - if (entry.getValue().isEmpty()) { - context.addServletContainerInitializer( - entry.getKey(), null); - } else { - context.addServletContainerInitializer( - entry.getKey(), entry.getValue()); - } + // Step 11. Apply the ServletContainerInitializer config to the + // context + if (ok) { + for (Map.Entry<ServletContainerInitializer, + Set<Class<?>>> entry : + initializerClassMap.entrySet()) { + if (entry.getValue().isEmpty()) { + context.addServletContainerInitializer( + entry.getKey(), null); + } else { + context.addServletContainerInitializer( + entry.getKey(), entry.getValue()); } } } @@ -1879,33 +1883,35 @@ public class ContextConfig implements Li return callback.getFragments(); } - protected void processAnnotations(Set<WebXml> fragments) { + protected void processAnnotations(Set<WebXml> fragments, + boolean handlesTypesOnly) { for(WebXml fragment : fragments) { - if (!fragment.isMetadataComplete()) { - WebXml annotations = new WebXml(); - // no impact on distributable - annotations.setDistributable(true); - URL url = fragment.getURL(); - processAnnotationsUrl(url, annotations); - Set<WebXml> set = new HashSet<WebXml>(); - set.add(annotations); - // Merge annotations into fragment - fragment takes priority - fragment.merge(set); - } + WebXml annotations = new WebXml(); + // no impact on distributable + annotations.setDistributable(true); + URL url = fragment.getURL(); + processAnnotationsUrl(url, annotations, + (handlesTypesOnly || fragment.isMetadataComplete())); + Set<WebXml> set = new HashSet<WebXml>(); + set.add(annotations); + // Merge annotations into fragment - fragment takes priority + fragment.merge(set); } } - protected void processAnnotationsUrl(URL url, WebXml fragment) { + protected void processAnnotationsUrl(URL url, WebXml fragment, + boolean handlesTypesOnly) { if (url == null) { // Nothing to do. return; } else if ("jar".equals(url.getProtocol())) { - processAnnotationsJar(url, fragment); + processAnnotationsJar(url, fragment, handlesTypesOnly); } else if ("jndi".equals(url.getProtocol())) { - processAnnotationsJndi(url, fragment); + processAnnotationsJndi(url, fragment, handlesTypesOnly); } else if ("file".equals(url.getProtocol())) { try { - processAnnotationsFile(new File(url.toURI()), fragment); + processAnnotationsFile( + new File(url.toURI()), fragment, handlesTypesOnly); } catch (URISyntaxException e) { log.error(sm.getString("contextConfig.fileUrl", url), e); } @@ -1917,7 +1923,8 @@ public class ContextConfig implements Li } - protected void processAnnotationsJar(URL url, WebXml fragment) { + protected void processAnnotationsJar(URL url, WebXml fragment, + boolean handlesTypesOnly) { Jar jar = null; InputStream is; @@ -1932,7 +1939,8 @@ public class ContextConfig implements Li is = null; try { is = jar.getEntryInputStream(); - processAnnotationsStream(is, fragment); + processAnnotationsStream( + is, fragment, handlesTypesOnly); } catch (IOException e) { log.error(sm.getString("contextConfig.inputStreamJar", entryName, url),e); @@ -1962,7 +1970,8 @@ public class ContextConfig implements Li } - protected void processAnnotationsJndi(URL url, WebXml fragment) { + protected void processAnnotationsJndi(URL url, WebXml fragment, + boolean handlesTypesOnly) { try { URLConnection urlConn = url.openConnection(); DirContextURLConnection dcUrlConn; @@ -1982,7 +1991,7 @@ public class ContextConfig implements Li while (dirs.hasMoreElements()) { String dir = dirs.nextElement(); URL dirUrl = new URL(url.toString() + '/' + dir); - processAnnotationsJndi(dirUrl, fragment); + processAnnotationsJndi(dirUrl, fragment, handlesTypesOnly); } } else { @@ -1991,7 +2000,8 @@ public class ContextConfig implements Li InputStream is = null; try { is = dcUrlConn.getInputStream(); - processAnnotationsStream(is, fragment); + processAnnotationsStream( + is, fragment, handlesTypesOnly); } catch (IOException e) { log.error(sm.getString("contextConfig.inputStreamJndi", url),e); @@ -2015,18 +2025,20 @@ public class ContextConfig implements Li } - protected void processAnnotationsFile(File file, WebXml fragment) { + protected void processAnnotationsFile(File file, WebXml fragment, + boolean handlesTypesOnly) { if (file.isDirectory()) { String[] dirs = file.list(); for (String dir : dirs) { - processAnnotationsFile(new File(file,dir), fragment); + processAnnotationsFile( + new File(file,dir), fragment, handlesTypesOnly); } } else if (file.canRead() && file.getName().endsWith(".class")) { FileInputStream fis = null; try { fis = new FileInputStream(file); - processAnnotationsStream(fis, fragment); + processAnnotationsStream(fis, fragment, handlesTypesOnly); } catch (IOException e) { log.error(sm.getString("contextConfig.inputStreamFile", file.getAbsolutePath()),e); @@ -2046,7 +2058,8 @@ public class ContextConfig implements Li } - protected void processAnnotationsStream(InputStream is, WebXml fragment) + protected void processAnnotationsStream(InputStream is, WebXml fragment, + boolean handlesTypesOnly) throws ClassFormatException, IOException { ClassParser parser = new ClassParser(is, null); @@ -2054,6 +2067,10 @@ public class ContextConfig implements Li checkHandlesTypes(clazz); + if (handlesTypesOnly) { + return; + } + String className = clazz.getClassName(); AnnotationEntry[] annotationsEntries = clazz.getAnnotationEntries(); Modified: tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestContextConfigAnnotation.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestContextConfigAnnotation.java?rev=1352803&r1=1352802&r2=1352803&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestContextConfigAnnotation.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestContextConfigAnnotation.java Fri Jun 22 08:46:55 2012 @@ -60,7 +60,7 @@ public class TestContextConfigAnnotation File pFile = paramClassResource( "org/apache/catalina/startup/ParamServlet"); assertTrue(pFile.exists()); - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); ServletDef servletDef = webxml.getServlets().get("param"); assertNotNull(servletDef); assertEquals("Hello", servletDef.getParameterMap().get("foo")); @@ -99,7 +99,7 @@ public class TestContextConfigAnnotation File pFile = paramClassResource( "org/apache/catalina/startup/ParamServlet"); assertTrue(pFile.exists()); - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); assertEquals(servletDef, webxml.getServlets().get("param")); @@ -126,12 +126,12 @@ public class TestContextConfigAnnotation File pFile = paramClassResource( "org/apache/catalina/startup/NoMappingParamServlet"); assertTrue(pFile.exists()); - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); ServletDef servletDef = webxml.getServlets().get("param1"); assertNull(servletDef); webxml.addServletMapping("/param", "param1"); - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); servletDef = webxml.getServlets().get("param1"); assertNull(servletDef); @@ -152,7 +152,7 @@ public class TestContextConfigAnnotation File pFile = paramClassResource( "org/apache/catalina/startup/NoMappingParamServlet"); assertTrue(pFile.exists()); - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); assertEquals("tomcat", servletDef.getParameterMap().get("foo")); assertEquals("World!", servletDef.getParameterMap().get("bar")); ServletDef servletDef1 = webxml.getServlets().get("param1"); @@ -168,7 +168,7 @@ public class TestContextConfigAnnotation "org/apache/catalina/startup/DuplicateMappingParamServlet"); assertTrue(pFile.exists()); try { - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); fail(); } catch (IllegalArgumentException ex) { // ignore @@ -183,10 +183,10 @@ public class TestContextConfigAnnotation ContextConfig config = new ContextConfig(); File sFile = paramClassResource( "org/apache/catalina/startup/ParamServlet"); - config.processAnnotationsFile(sFile, webxml); + config.processAnnotationsFile(sFile, webxml, false); File fFile = paramClassResource( "org/apache/catalina/startup/ParamFilter"); - config.processAnnotationsFile(fFile, webxml); + config.processAnnotationsFile(fFile, webxml, false); FilterDef fdef = webxml.getFilters().get("paramFilter"); assertNotNull(fdef); assertEquals("Servlet says: ",fdef.getParameterMap().get("message")); @@ -215,10 +215,10 @@ public class TestContextConfigAnnotation ContextConfig config = new ContextConfig(); File sFile = paramClassResource( "org/apache/catalina/startup/ParamServlet"); - config.processAnnotationsFile(sFile, webxml); + config.processAnnotationsFile(sFile, webxml, false); File fFile = paramClassResource( "org/apache/catalina/startup/ParamFilter"); - config.processAnnotationsFile(fFile, webxml); + config.processAnnotationsFile(fFile, webxml, false); FilterDef fdef = webxml.getFilters().get("paramFilter"); assertNotNull(fdef); assertEquals(filterDef,fdef); @@ -255,7 +255,7 @@ public class TestContextConfigAnnotation "org/apache/catalina/startup/DuplicateMappingParamFilter"); assertTrue(pFile.exists()); try { - config.processAnnotationsFile(pFile, webxml); + config.processAnnotationsFile(pFile, webxml, false); fail(); } catch (IllegalArgumentException ex) { // ignore @@ -297,13 +297,13 @@ public class TestContextConfigAnnotation WebXml ignore = new WebXml(); File file = paramClassResource( "org/apache/catalina/startup/ParamServlet"); - config.processAnnotationsFile(file, ignore); + config.processAnnotationsFile(file, ignore, false); file = paramClassResource("org/apache/catalina/startup/ParamFilter"); - config.processAnnotationsFile(file, ignore); + config.processAnnotationsFile(file, ignore, false); file = paramClassResource("org/apache/catalina/startup/TesterServlet"); - config.processAnnotationsFile(file, ignore); + config.processAnnotationsFile(file, ignore, false); file = paramClassResource("org/apache/catalina/startup/TestListener"); - config.processAnnotationsFile(file, ignore); + config.processAnnotationsFile(file, ignore, false); // Check right number of classes were noted to be handled assertEquals(0, config.initializerClassMap.get(sciNone).size()); Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1352803&r1=1352802&r2=1352803&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Fri Jun 22 08:46:55 2012 @@ -77,6 +77,11 @@ Annotation scanning is now always performed - regardless of the version declared in web.xml - unless metadata complete is set to true. (markt) </fix> + <fix> + As per clarification from the Servlet Expert Group, JARs are always + checked for ServletContainerInitializers regardless of the setting of + metadata complete. (markt) + </fix> </changelog> </subsection> <subsection name="Web applications"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org