Author: markt Date: Fri Jun 1 22:03:10 2012 New Revision: 1345367 URL: http://svn.apache.org/viewvc?rev=1345367&view=rev Log: Refactor some duplicate code into an new utility class with an eye to the proposed patch for BZ 53333
Added: tomcat/trunk/java/org/apache/catalina/util/Introspection.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties Modified: tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java?rev=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java Fri Jun 1 22:03:10 2012 @@ -14,11 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - package org.apache.catalina.core; - import java.beans.Introspector; import java.io.IOException; import java.io.InputStream; @@ -52,6 +49,7 @@ import javax.xml.ws.WebServiceRef; import org.apache.catalina.ContainerServlet; import org.apache.catalina.Globals; import org.apache.catalina.security.SecurityUtil; +import org.apache.catalina.util.Introspection; import org.apache.tomcat.InstanceManager; import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.res.StringManager; @@ -61,6 +59,16 @@ import org.apache.tomcat.util.res.String */ public class DefaultInstanceManager implements InstanceManager { + // Used when there are no annotations in a class + private static final AnnotationCacheEntry[] ANNOTATIONS_EMPTY + = new AnnotationCacheEntry[0]; + + /** + * The string manager for this package. + */ + protected static final StringManager sm = + StringManager.getManager(Constants.Package); + private final Context context; private final Map<String, Map<String, String>> injectionMap; protected final ClassLoader classLoader; @@ -73,10 +81,6 @@ public class DefaultInstanceManager impl private final Map<Class<?>, AnnotationCacheEntry[]> annotationCache = new WeakHashMap<Class<?>, AnnotationCacheEntry[]>(); - // Used when there are no annotations in a class - private static final AnnotationCacheEntry[] ANNOTATIONS_EMPTY - = new AnnotationCacheEntry[0]; - public DefaultInstanceManager(Context context, Map<String, Map<String, String>> injectionMap, org.apache.catalina.Context catalinaContext, ClassLoader containerClassLoader) { classLoader = catalinaContext.getLoader().getClassLoader(); privileged = catalinaContext.getPrivileged(); @@ -286,19 +290,7 @@ public class DefaultInstanceManager impl if (context != null) { // Initialize fields annotations for resource injection if // JNDI is enabled - Field[] fields = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class<?> clazz2 = clazz; - fields = AccessController.doPrivileged( - new PrivilegedAction<Field[]>(){ - @Override - public Field[] run(){ - return clazz2.getDeclaredFields(); - } - }); - } else { - fields = clazz.getDeclaredFields(); - } + Field[] fields = Introspection.getDeclaredFields(clazz); for (Field field : fields) { if (injections != null && injections.containsKey(field.getName())) { annotations.add(new AnnotationCacheEntry( @@ -338,30 +330,15 @@ public class DefaultInstanceManager impl } // Initialize methods annotations - Method[] methods = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class<?> clazz2 = clazz; - methods = AccessController.doPrivileged( - new PrivilegedAction<Method[]>(){ - @Override - public Method[] run(){ - return clazz2.getDeclaredMethods(); - } - }); - } else { - methods = clazz.getDeclaredMethods(); - } + Method[] methods = Introspection.getDeclaredMethods(clazz); Method postConstruct = null; Method preDestroy = null; for (Method method : methods) { - String methodName = method.getName(); if (context != null) { // Resource injection only if JNDI is enabled - if (injections != null && methodName.startsWith("set") - && methodName.length() > 3 - && method.getParameterTypes().length == 1 - && method.getReturnType().getName().equals("void")) { - String fieldName = getName(method); + if (injections != null && + Introspection.isValidSetter(method)) { + String fieldName = Introspection.getName(method); if (injections.containsKey(fieldName)) { annotations.add(new AnnotationCacheEntry( method.getName(), @@ -634,11 +611,9 @@ public class DefaultInstanceManager impl Object instance, Method method, String name, Class<?> clazz) throws NamingException, IllegalAccessException, InvocationTargetException { - if (!method.getName().startsWith("set") - || method.getName().length() < 4 - || method.getParameterTypes().length != 1 - || !method.getReturnType().getName().equals("void")) { - throw new IllegalArgumentException("Invalid method resource injection annotation"); + if (!Introspection.isValidSetter(method)) { + throw new IllegalArgumentException( + sm.getString("defaultInstanceManager.invalidInjection")); } Object lookedupResource; @@ -650,7 +625,7 @@ public class DefaultInstanceManager impl lookedupResource = context.lookup(normalizedName); } else { lookedupResource = context.lookup( - clazz.getName() + "/" + getName(method)); + clazz.getName() + "/" + Introspection.getName(method)); } synchronized (method) { @@ -661,7 +636,8 @@ public class DefaultInstanceManager impl } } - public static String getName(Method setter) { + @Deprecated + public static String XXXgetName(Method setter) { // Note: method signature has already been checked for correctness. // The method name always starts with "set". return Introspector.decapitalize(setter.getName().substring(3)); Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Fri Jun 1 22:03:10 2012 @@ -68,6 +68,7 @@ containerBase.backgroundProcess.loader=E containerBase.backgroundProcess.manager=Exception processing manager {0} background process containerBase.backgroundProcess.realm=Exception processing realm {0} background process containerBase.backgroundProcess.valve=Exception processing valve {0} background process +defaultInstanceManager.invalidInjection=Invalid method resource injection annotation filterChain.filter=Filter execution threw an exception filterChain.servlet=Servlet execution threw an exception jreLeakListener.gcDaemonFail=Failed to trigger creation of the GC Daemon thread during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs. 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=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Fri Jun 1 22:03:10 2012 @@ -75,6 +75,7 @@ import org.apache.catalina.deploy.Securi import org.apache.catalina.deploy.ServletDef; import org.apache.catalina.deploy.WebXml; import org.apache.catalina.util.ContextName; +import org.apache.catalina.util.Introspection; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.naming.resources.DirContextURLConnection; @@ -2021,7 +2022,7 @@ public class ContextConfig implements Li } if (entry.getSciSet().size() > 0) { // Need to try and load the class - clazz = loadClass(className); + clazz = Introspection.loadClass(context, className); if (clazz == null) { // Can't load the class so no point continuing return; @@ -2049,7 +2050,8 @@ public class ContextConfig implements Li if (entry.getKey().getName().equals( getClassName(annotationEntry.getAnnotationType()))) { if (clazz == null) { - clazz = loadClass(className); + clazz = Introspection.loadClass( + context, className); if (clazz == null) { // Can't load the class so no point // continuing @@ -2163,31 +2165,6 @@ public class ContextConfig implements Li 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 null; - } catch (ClassNotFoundException e) { - log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", - className), e); - return null; - } catch (ClassFormatError e) { - log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", - className), e); - return null; - } catch (Throwable t) { - ExceptionUtils.handleThrowable(t); - log.debug(sm.getString("contextConfig.invalidSciHandlesTypes", - className), t); - return null; - } - return clazz; - } - private static final String getClassName(String internalForm) { if (!internalForm.startsWith("L")) { return internalForm; 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=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Fri Jun 1 22:03:10 2012 @@ -44,7 +44,6 @@ contextConfig.inputStreamFile=Unable to contextConfig.inputStreamJar=Unable to process Jar entry [{0}] from Jar [{1}] for annotations contextConfig.inputStreamJndi=Unable to process resource element [{0}] for annotations contextConfig.invalidSci=The ServletContentInitializer [{0}] could not be created -contextConfig.invalidSciHandlesTypes=Unable to load class [{0}] to check against the @HandlesTypes annotation of one or more ServletContentInitializers. contextConfig.jndiUrl=Unable to process JNDI URL [{0}] for annotations contextConfig.jndiUrlNotDirContextConn=The connection created for URL [{0}] was not a DirContextURLConnection contextConfig.jspFile.error=JSP file {0} must start with a ''/' @@ -122,6 +121,7 @@ userConfig.error=Error deploying web app userConfig.start=UserConfig: Processing START userConfig.stop=UserConfig: Processing STOP userConfig.deploy.threaded.error=Error waiting for multi-thread deployment of user directories to complete +webAnnotationSet.invalidInjection=Invalid method resource injection annotation. webRuleSet.absoluteOrdering=<absolute-ordering> element not valid in web-fragment.xml and will be ignored webRuleSet.absoluteOrderingCount=<absolute-ordering> element is limited to 1 occurrence webRuleSet.nameCount=<name> element is limited to 1 occurrence Modified: tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java?rev=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java Fri Jun 1 22:03:10 2012 @@ -14,15 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - package org.apache.catalina.startup; - import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.annotation.Resource; import javax.annotation.Resources; @@ -31,15 +26,15 @@ import javax.annotation.security.RunAs; import org.apache.catalina.Container; import org.apache.catalina.Context; -import org.apache.catalina.Globals; import org.apache.catalina.Wrapper; -import org.apache.catalina.core.DefaultInstanceManager; import org.apache.catalina.deploy.ContextEnvironment; import org.apache.catalina.deploy.ContextResource; import org.apache.catalina.deploy.ContextResourceEnvRef; import org.apache.catalina.deploy.ContextService; import org.apache.catalina.deploy.FilterDef; import org.apache.catalina.deploy.MessageDestinationRef; +import org.apache.catalina.util.Introspection; +import org.apache.tomcat.util.res.StringManager; /** * <p><strong>AnnotationSet</strong> for processing the annotations of the web application @@ -53,9 +48,15 @@ public class WebAnnotationSet { private static final String SEPARATOR = "/"; - // --------------------------------------------------------- Public Methods + /** + * The string resources for this package. + */ + protected static final StringManager sm = + StringManager.getManager(Constants.Package); + // --------------------------------------------------------- Public Methods + /** * Process the annotations on a context. */ @@ -79,7 +80,8 @@ public class WebAnnotationSet { Class<?> classClass = null; String[] applicationListeners = context.findApplicationListeners(); for (int i = 0; i < applicationListeners.length; i++) { - classClass = loadClass(context, applicationListeners[i]); + classClass = Introspection.loadClass(context, + applicationListeners[i]); if (classClass == null) { continue; } @@ -98,7 +100,8 @@ public class WebAnnotationSet { Class<?> classClass = null; FilterDef[] filterDefs = context.findFilterDefs(); for (int i = 0; i < filterDefs.length; i++) { - classClass = loadClass(context, (filterDefs[i]).getFilterClass()); + classClass = Introspection.loadClass(context, + (filterDefs[i]).getFilterClass()); if (classClass == null) { continue; } @@ -127,7 +130,8 @@ public class WebAnnotationSet { continue; } - classClass = loadClass(context, wrapper.getServletClass()); + classClass = Introspection.loadClass(context, + wrapper.getServletClass()); if (classClass == null) { continue; } @@ -254,7 +258,7 @@ public class WebAnnotationSet { protected static void loadFieldsAnnotation(Context context, Class<?> classClass) { // Initialize the annotations - Field[] fields = getDeclaredFields(classClass); + Field[] fields = Introspection.getDeclaredFields(classClass); if (fields != null && fields.length > 0) { for (Field field : fields) { if (field.isAnnotationPresent(Resource.class)) { @@ -272,16 +276,19 @@ public class WebAnnotationSet { protected static void loadMethodsAnnotation(Context context, Class<?> classClass) { // Initialize the annotations - Method[] methods = getDeclaredMethods(classClass); + Method[] methods = Introspection.getDeclaredMethods(classClass); if (methods != null && methods.length > 0) { for (Method method : methods) { if (method.isAnnotationPresent(Resource.class)) { Resource annotation = method.getAnnotation(Resource.class); - checkBeanNamingConventions(method); + if (!Introspection.isValidSetter(method)) { + throw new IllegalArgumentException(sm.getString( + "webAnnotationSet.invalidInjection")); + } String defaultName = classClass.getName() + SEPARATOR + - DefaultInstanceManager.getName(method); + Introspection.getName(method); String defaultType = (method.getParameterTypes()[0]).getCanonicalName(); @@ -405,16 +412,6 @@ public class WebAnnotationSet { } - private static void checkBeanNamingConventions(Method method) { - if (!method.getName().startsWith("set") - || method.getName().length() < 4 - || method.getParameterTypes().length != 1 - || !method.getReturnType().getName().equals("void")) { - throw new IllegalArgumentException("Invalid method resource injection annotation."); - } - } - - private static String getType(Resource annotation, String defaultType) { String type = annotation.type().getCanonicalName(); if (type == null || type.equals("java.lang.Object")) { @@ -435,54 +432,4 @@ public class WebAnnotationSet { } return name; } - - - private static Field[] getDeclaredFields(Class<?> classClass) { - Field[] fields = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class<?> clazz = classClass; - fields = AccessController.doPrivileged( - new PrivilegedAction<Field[]>(){ - @Override - public Field[] run(){ - return clazz.getDeclaredFields(); - } - }); - } else { - fields = classClass.getDeclaredFields(); - } - return fields; - } - - - private static Method[] getDeclaredMethods(Class<?> classClass) { - Method[] methods = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class<?> clazz = classClass; - methods = AccessController.doPrivileged( - new PrivilegedAction<Method[]>(){ - @Override - public Method[] run(){ - return clazz.getDeclaredMethods(); - } - }); - } else { - methods = classClass.getDeclaredMethods(); - } - return methods; - } - - - private static Class<?> loadClass(Context context, String fileString) { - ClassLoader classLoader = context.getLoader().getClassLoader(); - Class<?> classClass = null; - try { - classClass = classLoader.loadClass(fileString); - } catch (ClassNotFoundException e) { - // We do nothing - } catch (NoClassDefFoundError e) { - // We do nothing - } - return classClass; - } } Added: tomcat/trunk/java/org/apache/catalina/util/Introspection.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/Introspection.java?rev=1345367&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/util/Introspection.java (added) +++ tomcat/trunk/java/org/apache/catalina/util/Introspection.java Fri Jun 1 22:03:10 2012 @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.util; + +import java.beans.Introspector; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.catalina.Container; +import org.apache.catalina.Globals; +import org.apache.juli.logging.Log; +import org.apache.tomcat.util.ExceptionUtils; +import org.apache.tomcat.util.res.StringManager; + +/** + * Provides introspection utilities that either require knowledge of Tomcat + * internals or are solely used by Tomcat internals. + */ +public class Introspection { + + private static StringManager sm = + StringManager.getManager("org.apache.catalina.util"); + + + /** + * Extract the Java Bean field name from the setter name. + * + * Note: This method assumes that the method name has already been checked + * for correctness. + */ + public static String getName(Method setter) { + return Introspector.decapitalize(setter.getName().substring(3)); + } + + + /** + * Determines if a method has a valid name and signature for a Java Bean + * setter. + * + * @param method The method to test + * + * @return <code>true</code> if the method does have a valid name and + * signature, else <code>false</code> + */ + public static boolean isValidSetter(Method method) { + if (method.getName().startsWith("set") + && method.getName().length() > 3 + && method.getParameterTypes().length == 1 + && method.getReturnType().getName().equals("void")) { + return true; + } + return false; + } + + + /** + * Obtain the declared fields for a class taking account of any security + * manager that may be configured. + */ + public static Field[] getDeclaredFields(final Class<?> clazz) { + Field[] fields = null; + if (Globals.IS_SECURITY_ENABLED) { + fields = AccessController.doPrivileged( + new PrivilegedAction<Field[]>(){ + @Override + public Field[] run(){ + return clazz.getDeclaredFields(); + } + }); + } else { + fields = clazz.getDeclaredFields(); + } + return fields; + } + + + /** + * Obtain the declared methods for a class taking account of any security + * manager that may be configured. + */ + public static Method[] getDeclaredMethods(final Class<?> clazz) { + Method[] methods = null; + if (Globals.IS_SECURITY_ENABLED) { + methods = AccessController.doPrivileged( + new PrivilegedAction<Method[]>(){ + @Override + public Method[] run(){ + return clazz.getDeclaredMethods(); + } + }); + } else { + methods = clazz.getDeclaredMethods(); + } + return methods; + } + + + /** + * Attempt to load a class using the given Container's class loader. If the + * class cannot be loaded, a debug level log message will be written to the + * Container's log and null will be returned. + */ + public static Class<?> loadClass(Container container, String className) { + ClassLoader cl = container.getLoader().getClassLoader(); + Log log = container.getLogger(); + Class<?> clazz = null; + try { + clazz = cl.loadClass(className); + } catch (ClassNotFoundException e) { + log.debug(sm.getString("introspection.classLoadFailed"), e); + } catch (NoClassDefFoundError e) { + log.debug(sm.getString("introspection.classLoadFailed"), e); + } catch (ClassFormatError e) { + log.debug(sm.getString("introspection.classLoadFailed"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.debug(sm.getString("introspection.classLoadFailed"), t); + } + return clazz; + } +} Propchange: tomcat/trunk/java/org/apache/catalina/util/Introspection.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties?rev=1345367&r1=1345366&r2=1345367&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties Fri Jun 1 22:03:10 2012 @@ -22,6 +22,7 @@ extensionValidator.web-application-manif extensionValidator.extension-not-found-error=ExtensionValidator[{0}][{1}]: Required extension [{2}] not found. extensionValidator.extension-validation-error=ExtensionValidator[{0}]: Failure to find [{1}] required extension(s). extensionValidator.failload=Failure loading extension [{0}] +introspection.classLoadFailed=Failed to load class [{0}] lifecycleBase.alreadyDestroyed=The destroy() method was called on component [{0}] after destroy() had already been called. The second call will be ignored. lifecycleBase.alreadyStarted=The start() method was called on component [{0}] after start() had already been called. The second call will be ignored. lifecycleBase.alreadyStopped=The stop() method was called on component [{0}] after stop() had already been called. The second call will be ignored. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org