Author: markt Date: Mon Jan 30 11:34:30 2012 New Revision: 1237607 URL: http://svn.apache.org/viewvc?rev=1237607&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52444 Remove need to load classes unless they actually match an HandlesTypes entry
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/java/org/apache/tomcat/util/bcel/classfile/JavaClass.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/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Mon Jan 30 11:34:30 2012 @@ -1 +1 @@ -/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096 ,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174975,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175798,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187 381,1187753,1187755,1187775,1187801,1187806,1187809,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034,1190185,1190279,1190339,1190371,1190388-1190389,1190474,1190481,1194915,1195222-1195223,1195531,1195899,1195905,1195943,1195949,1195953,1195955,1195965,1195968,1196175,1196212,1196223,1196304-1196305,1196735,1196825,1196827,1197158,1197261,1197263,1197299-1197300,1197305,1197339-1197340,1197343,1197382,1197386-1197387,1197480,1197578,1198497,1198528,1198552,1198602,1198604,1198607,1198622,1198640,1198696,1198707,1199418,1199432,1199436,1199513,1199529,1199980,1199996,1200056,1200089,1200106-1200107,1200263,1200316,1200320,1200398-1200399,1200445-1200446,1200555,1200627,1200696,1200725,1200937,1200941,1201069,1201087,1201180,1201235-1201237,1201508,1201521,1201542,1201545-1201546,1201548,1201555-1201556,1201568,1201576,1201608,1201921-1201922,1 201931,1202035,1202039,1202271,1202565,1202578,1202705,1202828,1202860,1203047-1203052,1203078,1203091,1203253,1203278,1204182,1204856,1204867,1204936,1204938,1204982,1205033,1205065,1205082,1205097,1205112,1206200,1207692,1208046,1208073,1208096,1208114,1208145,1208772,1209194,1209277-1209278,1209686-1209731,1210894,1212091,1212095,1212099,1212118,1213469,1213906,1214853,1214855,1214864,1215115,1215118-1215119,1215121,1220293,1220295,1221038,1221842,1222189,1222201,1222276,1222300,1222690,1222850,1222852,1222855,1224607,1224617,1224648-1224652,1224657,1224662-1224663,1224682,1224801,1224910,1225000,1225219,1225343,1225465,1225627,1225629,1225634,1226069,1226158-1226159,1226177,1226196,1226214-1226215,1226385,1226394,1226500,1226537-1226538,1226546,1226551,1226975,1228196,1228360,1228376,1228724,1228908,1228918,1228920,1228922,1228929,1228969,1229307,1229536,1229549,1229724,1229726-1229731,1229997,1230539,1230711,1230729,1230762-1230763,1230765,1230955,1230957,1231285,123129 0,1231308,1231310,1231337,1231460-1231461,1231542-1231543,1231546-1231547,1231620-1231621,1231624-1231625,1231630,1231654-1231655,1231738,1231740,1231762-1231763,1231856,1231886,1231923,1231947,1232345,1232368,1232380,1232447,1232760,1232813,1232842-1232843,1232869,1233413,1233423,1233426,1234143,1234567,1235207,1236906-1236907,1236914,1237146,1237154-1237156,1237332,1237334,1237425,1237427 +/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096 ,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174975,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175798,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187 381,1187753,1187755,1187775,1187801,1187806,1187809,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034,1190185,1190279,1190339,1190371,1190388-1190389,1190474,1190481,1194915,1195222-1195223,1195531,1195899,1195905,1195943,1195949,1195953,1195955,1195965,1195968,1196175,1196212,1196223,1196304-1196305,1196735,1196825,1196827,1197158,1197261,1197263,1197299-1197300,1197305,1197339-1197340,1197343,1197382,1197386-1197387,1197480,1197578,1198497,1198528,1198552,1198602,1198604,1198607,1198622,1198640,1198696,1198707,1199418,1199432,1199436,1199513,1199529,1199980,1199996,1200056,1200089,1200106-1200107,1200263,1200316,1200320,1200398-1200399,1200445-1200446,1200555,1200627,1200696,1200725,1200937,1200941,1201069,1201087,1201180,1201235-1201237,1201508,1201521,1201542,1201545-1201546,1201548,1201555-1201556,1201568,1201576,1201608,1201921-1201922,1 201931,1202035,1202039,1202271,1202565,1202578,1202705,1202828,1202860,1203047-1203052,1203078,1203091,1203253,1203278,1204182,1204856,1204867,1204936,1204938,1204982,1205033,1205065,1205082,1205097,1205112,1206200,1207692,1208046,1208073,1208096,1208114,1208145,1208772,1209194,1209277-1209278,1209686-1209731,1210894,1212091,1212095,1212099,1212118,1213469,1213906,1214853,1214855,1214864,1215115,1215118-1215119,1215121,1220293,1220295,1221038,1221842,1222189,1222201,1222276,1222300,1222690,1222850,1222852,1222855,1224607,1224617,1224648-1224652,1224657,1224662-1224663,1224682,1224801,1224910,1225000,1225219,1225343,1225465,1225627,1225629,1225634,1226069,1226158-1226159,1226177,1226196,1226214-1226215,1226385,1226394,1226500,1226537-1226538,1226546,1226551,1226975,1228196,1228360,1228376,1228724,1228908,1228918,1228920,1228922,1228929,1228969,1229307,1229536,1229549,1229724,1229726-1229731,1229997,1230539,1230711,1230729,1230762-1230763,1230765,1230955,1230957,1231285,123129 0,1231308,1231310,1231337,1231460-1231461,1231542-1231543,1231546-1231547,1231620-1231621,1231624-1231625,1231630,1231654-1231655,1231738,1231740,1231762-1231763,1231856,1231886,1231923,1231947,1232345,1232368,1232380,1232447,1232760,1232813,1232842-1232843,1232869,1233413,1233423,1233426,1234143,1234567,1235207,1236906-1236907,1236914,1237146,1237154-1237156,1237332,1237334,1237425,1237427,1237604 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=1237607&r1=1237606&r2=1237607&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 Mon Jan 30 11:34:30 2012 @@ -30,6 +30,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -192,14 +193,34 @@ public class ContextConfig implements Li * Map of ServletContainerInitializer to classes they expressed interest in. */ protected Map<ServletContainerInitializer, Set<Class<?>>> initializerClassMap = - new LinkedHashMap<ServletContainerInitializer, Set<Class<?>>>(); + new LinkedHashMap<ServletContainerInitializer, Set<Class<?>>>(); /** * Map of Types to ServletContainerInitializer that are interested in those * types. */ protected Map<Class<?>, Set<ServletContainerInitializer>> typeInitializerMap = - new HashMap<Class<?>, Set<ServletContainerInitializer>>(); + new HashMap<Class<?>, Set<ServletContainerInitializer>>(); + + /** + * Cache of JavaClass objects (byte code) by fully qualified class name. + * Only populated if it is necessary to scan the super types and interfaces + * as part of the processing for {@link HandlesTypes}. + */ + protected final Map<String,JavaClassCacheEntry> javaClassCache = + new HashMap<String,JavaClassCacheEntry>(); + + /** + * Flag that indicates if at least one {@link HandlesTypes} entry is present + * that represents an annotation. + */ + protected boolean handlesTypesAnnotations = false; + + /** + * Flag that indicates if at least one {@link HandlesTypes} entry is present + * that represents a non-annotation. + */ + protected boolean handlesTypesNonAnnotations = false; /** * The <code>Digester</code> we will use to process web application @@ -1230,6 +1251,9 @@ public class ContextConfig implements Li processAnnotations(orderedFragments); } + // Cache, if used, is no longer required so clear it + javaClassCache.clear(); + // Step 6. Merge web-fragment.xml files into the main web.xml // file. if (ok) { @@ -1506,6 +1530,11 @@ public class ContextConfig implements Li Class<?>[] types = ht.value(); if (types != null) { for (Class<?> type : types) { + if (type.isAnnotation()) { + handlesTypesAnnotations = true; + } else { + handlesTypesNonAnnotations = true; + } Set<ServletContainerInitializer> scis = typeInitializerMap.get(type); if (scis == null) { @@ -2021,59 +2050,180 @@ public class ContextConfig implements Li return; } - // No choice but to load the class String className = javaClass.getClassName(); Class<?> clazz = null; + if (handlesTypesNonAnnotations) { + // This *might* be match for a HandlesType. + populateJavaClassCache(className, javaClass); + JavaClassCacheEntry entry = javaClassCache.get(className); + if (entry.getSciSet() == null) { + populateSCIsForCacheEntry(entry); + } + if (entry.getSciSet().size() > 0) { + // Need to try and load the class + clazz = loadClass(className); + if (clazz == null) { + // Can't load the class so no point continuing + return; + } + + for (ServletContainerInitializer sci : + entry.getSciSet()) { + Set<Class<?>> classes = initializerClassMap.get(sci); + if (classes == null) { + classes = new HashSet<Class<?>>(); + initializerClassMap.put(sci, classes); + } + classes.add(clazz); + } + } + } + + if (handlesTypesAnnotations) { + for (Map.Entry<Class<?>, Set<ServletContainerInitializer>> entry : + typeInitializerMap.entrySet()) { + if (entry.getKey().isAnnotation()) { + AnnotationEntry[] annotationEntries = + javaClass.getAnnotationEntries(); + for (AnnotationEntry annotationEntry : annotationEntries) { + if (entry.getKey().getName().equals( + getClassName(annotationEntry.getAnnotationType()))) { + if (clazz == null) { + clazz = loadClass(className); + if (clazz == null) { + // Can't load the class so no point + // continuing + return; + } + } + for (ServletContainerInitializer sci : entry.getValue()) { + initializerClassMap.get(sci).add(clazz); + } + break; + } + } + } + } + } + } + + + private void populateJavaClassCache(String className, JavaClass javaClass) { + if (javaClassCache.containsKey(className)) { + return; + } + + // Add this class to the cache + javaClassCache.put(className, new JavaClassCacheEntry(javaClass)); + + populateJavaClassCache(javaClass.getSuperclassName()); + + for (String iterface : javaClass.getInterfaceNames()) { + populateJavaClassCache(iterface); + } + } + + private void populateJavaClassCache(String className) { + if (!javaClassCache.containsKey(className)) { + String name = className.replace('.', '/') + ".class"; + InputStream is = + context.getLoader().getClassLoader().getResourceAsStream(name); + ClassParser parser = new ClassParser(is, null); + try { + JavaClass clazz = parser.parse(); + populateJavaClassCache(clazz.getClassName(), clazz); + } catch (ClassFormatException e) { + log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", + className), e); + } catch (IOException e) { + log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", + className), e); + } + } + } + + private void populateSCIsForCacheEntry(JavaClassCacheEntry cacheEntry) { + Set<ServletContainerInitializer> result = + new HashSet<ServletContainerInitializer>(); + + JavaClass javaClass = cacheEntry.getJavaClass(); + + // Super class + String superClassName = javaClass.getSuperclassName(); + JavaClassCacheEntry superClassCacheEntry = + javaClassCache.get(superClassName); + + // Avoid an infinite loop with java.lang.Object + if (cacheEntry.equals(superClassCacheEntry)) { + cacheEntry.setSciSet(new HashSet<ServletContainerInitializer>()); + return; + } + + // May be null of the class is not present or could not be loaded. + if (superClassCacheEntry != null) { + if (superClassCacheEntry.getSciSet() == null) { + populateSCIsForCacheEntry(superClassCacheEntry); + } + result.addAll(superClassCacheEntry.getSciSet()); + } + result.addAll(getSCIsForClass(superClassName)); + + // Interfaces + for (String interfaceName : javaClass.getInterfaceNames()) { + JavaClassCacheEntry interfaceEntry = + javaClassCache.get(interfaceName); + // A null could mean that the class not present in application or + // that there is nothing of interest. Either way, nothing to do here + // so move along + if (interfaceEntry != null) { + if (interfaceEntry.getSciSet() == null) { + populateSCIsForCacheEntry(interfaceEntry); + } + result.addAll(interfaceEntry.getSciSet()); + } + result.addAll(getSCIsForClass(interfaceName)); + } + + cacheEntry.setSciSet(result); + } + + private Set<ServletContainerInitializer> getSCIsForClass(String className) { + for (Map.Entry<Class<?>, Set<ServletContainerInitializer>> entry : + typeInitializerMap.entrySet()) { + Class<?> clazz = entry.getKey(); + if (!clazz.isAnnotation()) { + if (clazz.getName().equals(className)) { + return entry.getValue(); + } + } + } + return Collections.emptySet(); + } + + private Class<?> loadClass(String className) { + Class<?> clazz = null; try { clazz = context.getLoader().getClassLoader().loadClass(className); } catch (NoClassDefFoundError e) { log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", className), e); - return; + return null; } catch (ClassNotFoundException e) { log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", className), e); - return; + return null; } catch (ClassFormatError e) { log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", className), e); - return; + return null; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", className), t); - return; - } - - if (clazz.isAnnotation()) { - // Skip - return; - } - - boolean match = false; - - for (Map.Entry<Class<?>, Set<ServletContainerInitializer>> entry : - typeInitializerMap.entrySet()) { - if (entry.getKey().isAnnotation()) { - AnnotationEntry[] annotationEntries = javaClass.getAnnotationEntries(); - for (AnnotationEntry annotationEntry : annotationEntries) { - if (entry.getKey().getName().equals( - getClassName(annotationEntry.getAnnotationType()))) { - match = true; - break; - } - } - } else if (entry.getKey().isAssignableFrom(clazz)) { - match = true; - } - if (match) { - for (ServletContainerInitializer sci : entry.getValue()) { - initializerClassMap.get(sci).add(clazz); - } - match = false; - } + return null; } + return clazz; } private static final String getClassName(String internalForm) { @@ -2483,4 +2633,25 @@ public class ContextConfig implements Li return hostTimeStamp; } } + + private static class JavaClassCacheEntry { + private final JavaClass javaClass; + private Set<ServletContainerInitializer> sciSet = null; + + public JavaClassCacheEntry(JavaClass javaClass) { + this.javaClass = javaClass; + } + + public JavaClass getJavaClass() { + return javaClass; + } + + public Set<ServletContainerInitializer> getSciSet() { + return sciSet; + } + + public void setSciSet(Set<ServletContainerInitializer> sciSet) { + this.sciSet = sciSet; + } + } } Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java?rev=1237607&r1=1237606&r2=1237607&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java Mon Jan 30 11:34:30 2012 @@ -180,6 +180,26 @@ public class JavaClass extends AccessFla /** + * @return Names of implemented interfaces. + */ + public String[] getInterfaceNames() { + return interface_names; + } + + + /** + * returns the super class name of this class. In the case that this class is + * java.lang.Object, it will return itself (java.lang.Object). This is probably incorrect + * but isn't fixed at this time to not break existing clients. + * + * @return Superclass name. + */ + public String getSuperclassName() { + return superclass_name; + } + + + /** * @return String representing class contents. */ @Override 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=1237607&r1=1237606&r2=1237607&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 Mon Jan 30 11:34:30 2012 @@ -267,6 +267,8 @@ public class TestContextConfigAnnotation @Test public void testCheckHandleTypes() throws Exception { ContextConfig config = new ContextConfig(); + config.handlesTypesAnnotations = true; + config.handlesTypesNonAnnotations = true; // Need a Context, Loader and ClassLoader for checkHandleTypes StandardContext context = new StandardContext(); 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=1237607&r1=1237606&r2=1237607&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Mon Jan 30 11:34:30 2012 @@ -61,6 +61,11 @@ these constants where appropriate. (markt) </scode> <fix> + <bug>52444</bug>: Only load classes during HandlesTypes processing if + the class is a match. Previously, every class in the web application was + loaded regardless of whether it was a match or not. (markt) + </fix> + <fix> <bug>52488</bug>: Correct typo: exipre -> expire. (markt) </fix> <add> @@ -72,11 +77,6 @@ that caused a harmless exception to be logged when scanning for annotations and <code>WEB-INF/classes</code> did not exist. (markt) </fix> - <fix> - <bug>52549</bug>: Partial fix for HandlesTypes processing that - previously loaded every class in the web application. The majority of - this issue remains to be fixed. (markt) - </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org