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

Reply via email to