ASF Bugzilla – Attachment 28864 Details for
Bug 53333
NPE is thrown for env-entry without env-entry-type but with injection-target specified
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch proposal
53333.patch (text/plain), 13.92 KB, created by
Violeta Georgieva
on 2012-05-30 19:41:54 UTC
(
hide
)
Description:
Patch proposal
Filename:
MIME Type:
Creator:
Violeta Georgieva
Created:
2012-05-30 19:41:54 UTC
Size:
13.92 KB
patch
obsolete
>Index: java/org/apache/catalina/deploy/LocalStrings.properties >=================================================================== >--- java/org/apache/catalina/deploy/LocalStrings.properties (revision 1344406) >+++ java/org/apache/catalina/deploy/LocalStrings.properties (working copy) >@@ -50,3 +50,4 @@ > namingResources.cleanupNoResource=Failed to retrieve JNDI resource [{0}] for container [{1}] so no cleanup was performed for that resource > namingResources.mbeanCreateFail=Failed to create MBean for naming resource [{0}] > namingResources.mbeanDestroyFail=Failed to destroy MBean for naming resource [{0}] >+namingResources.indeterminateResourceType=Cannot determine the resource type for Resource [{0}] >Index: java/org/apache/catalina/deploy/NamingResources.java >=================================================================== >--- java/org/apache/catalina/deploy/NamingResources.java (revision 1344406) >+++ java/org/apache/catalina/deploy/NamingResources.java (working copy) >@@ -22,10 +22,12 @@ > import java.beans.PropertyChangeListener; > import java.beans.PropertyChangeSupport; > import java.io.Serializable; >+import java.lang.reflect.Field; > import java.lang.reflect.InvocationTargetException; > import java.lang.reflect.Method; > import java.util.HashMap; > import java.util.Hashtable; >+import java.util.List; > > import javax.naming.NamingException; > >@@ -35,7 +37,9 @@ > import org.apache.catalina.LifecycleException; > import org.apache.catalina.LifecycleState; > import org.apache.catalina.Server; >+import org.apache.catalina.core.DefaultInstanceManager; > import org.apache.catalina.mbeans.MBeanUtils; >+import org.apache.catalina.startup.WebAnnotationSet; > import org.apache.catalina.util.LifecycleMBeanBase; > import org.apache.juli.logging.Log; > import org.apache.juli.logging.LogFactory; >@@ -251,6 +255,23 @@ > } > } > >+ // 14.4 Deployment Descriptor Diagram >+ // If an injection-target is specified for the environment entry, >+ // the env-entry-type may be omitted or MUST match the type of the injection target. >+ // If no injection-target is specified, the env-entry-type is required. >+ try { >+ String type = processResourceType(environment, true); >+ if (type != null) { >+ environment.setType(type); >+ } else { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", environment)); >+ return; >+ } >+ } catch (IllegalArgumentException e) { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", environment), e); >+ return; >+ } >+ > entries.put(environment.getName(), environment.getType()); > > synchronized (envs) { >@@ -317,6 +338,22 @@ > if (entries.containsKey(mdr.getName())) { > return; > } else { >+ // 14.4 Deployment Descriptor Diagram >+ // The message-destination-type MUST be specified unless an injection target is specified, >+ // in which case the type of the target is used. >+ // If both are specified, the type MUST be assignment compatible with the type of the injection target. >+ try { >+ String type = processResourceType(mdr, false); >+ if (type != null) { >+ mdr.setType(type); >+ } else { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", mdr)); >+ return; >+ } >+ } catch (IllegalArgumentException e) { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", mdr), e); >+ return; >+ } > entries.put(mdr.getName(), mdr.getType()); > } > >@@ -351,6 +388,18 @@ > if (entries.containsKey(resource.getName())) { > return; > } else { >+ try { >+ String type = processResourceType(resource, false); >+ if (type != null) { >+ resource.setType(type); >+ } else { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", resource)); >+ return; >+ } >+ } catch (IllegalArgumentException e) { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", resource), e); >+ return; >+ } > entries.put(resource.getName(), resource.getType()); > } > >@@ -382,6 +431,22 @@ > if (entries.containsKey(resource.getName())) { > return; > } else { >+ // 14.4 Deployment Descriptor Diagram >+ // The resource-env-ref-type MUST be supplied unless an injection target is specified, >+ // in which case the type of the target is used. >+ // If both are specified, the type MUST be assignment compatible with the type of the injection target. >+ try { >+ String type = processResourceType(resource, false); >+ if (type != null) { >+ resource.setType(type); >+ } else { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", resource)); >+ return; >+ } >+ } catch (IllegalArgumentException e) { >+ log.warn(sm.getString("namingResources.indeterminateResourceType", resource), e); >+ return; >+ } > entries.put(resource.getName(), resource.getType()); > } > >@@ -907,7 +972,165 @@ > > } > >+ /** >+ * Determines the resource type. >+ * >+ * @param resourceBase the resource >+ * @param exactMatch true if the resource type must match the type of the injection target, >+ * false if the type must be assignment compatible with the type of the injection target >+ * @return resource type >+ */ >+ private String processResourceType(ResourceBase resourceBase, boolean exactMatch) { >+ String type = resourceBase.getType(); >+ if (!(container instanceof Context)) { >+ return type; >+ } > >+ Context context = (Context) container; >+ >+ if (context.getLoader() == null || context.getLoader().getClassLoader() == null) { >+ return type; >+ } >+ >+ Class<?> typeClass = null; >+ if (type != null) { >+ typeClass = WebAnnotationSet.loadClass(context, type); >+ if (typeClass == null) { >+ // Cannot load the class >+ return type; >+ } >+ } >+ >+ Class<?> injectionTargetType = getInjectionTargetType(context, resourceBase.getInjectionTargets(), resourceBase); >+ >+ if (typeClass != null) { >+ if (injectionTargetType != null) { >+ boolean typeMatches = (exactMatch) ? typeClass.equals(injectionTargetType) : injectionTargetType.isAssignableFrom(typeClass); >+ if(!typeMatches) { >+ throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " + >+ "Resource type '" + typeClass.getCanonicalName() + "' must match the type or assignment " + >+ "compatible with the type '" + injectionTargetType.getCanonicalName() + "' of the injection target."); >+ } >+ } >+ } else if (injectionTargetType != null) { >+ type = injectionTargetType.getCanonicalName(); >+ } else { >+ throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " + >+ "The resource type and the injection target are missing."); >+ } >+ >+ return type; >+ } >+ >+ /** >+ * An injection-target specifies a class and a name within that class into which a resource should be injected. >+ * The injection-target-class specifies the fully qualified class name that is the target of the injection. >+ * The injection-target-name specifies the target within the specified class. >+ * The target is first looked for as a JavaBean property name. If not found, the target is looked for as a field name. >+ * >+ * @param context context that will be use for loading injection target classes >+ * @param injectionTargets list with all injection targets specified for the resource. >+ * @param resourceBase the resource >+ * >+ * @return the type of the specified injection-target-name >+ */ >+ private Class<?> getInjectionTargetType(Context context, List<InjectionTarget> injectionTargets, ResourceBase resourceBase) { >+ Class<?> type = null; >+ >+ if (injectionTargets != null && injectionTargets.size() > 0) { >+ for (InjectionTarget injectionTarget : injectionTargets) { >+ Class<?> clazz = WebAnnotationSet.loadClass(context, injectionTarget.getTargetClass()); >+ if (clazz == null) { >+ continue; >+ } >+ >+ Class<?> propertyType = getPropertyType(injectionTarget, clazz); >+ if (propertyType != null) { >+ propertyType = convertPrimitiveType(propertyType); >+ if (type == null) { >+ type = propertyType; >+ } else if (!type.equals(propertyType)) { >+ // The Servlet Specification does not describe >+ // how servlet container should handle multiple injection targets with different types >+ throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " + >+ "Resource type amongst injections targets is not the same."); >+ } >+ continue; >+ } >+ >+ Class<?> fieldType = getFieldType(injectionTarget, clazz); >+ if (fieldType != null) { >+ fieldType = convertPrimitiveType(fieldType); >+ if (type == null) { >+ type = fieldType; >+ } else if (!type.equals(fieldType)) { >+ // The Servlet Specification does not describe >+ // how servlet container should handle multiple injection targets with different types >+ throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " + >+ "Resource type amongst injections targets is not the same."); >+ } >+ continue; >+ } >+ } >+ } >+ >+ return type; >+ } >+ >+ private Class<?> getPropertyType(InjectionTarget injectionTarget, Class<?> clazz) { >+ Method[] methods = WebAnnotationSet.getDeclaredMethods(clazz); >+ if (methods != null && methods.length > 0) { >+ for (Method method : methods) { >+ String methodName = method.getName(); >+ if (methodName.startsWith("set") >+ && methodName.length() > 3 >+ && method.getParameterTypes().length == 1 >+ && method.getReturnType().getName().equals("void")) { >+ String fieldName = DefaultInstanceManager.getName(method); >+ if (injectionTarget.getTargetName().equals(fieldName)) { >+ return (method.getParameterTypes()[0]); >+ } >+ } >+ } >+ } >+ return null; >+ } >+ >+ private Class<?> getFieldType(InjectionTarget injectionTarget, Class<?> clazz) { >+ Field[] fields = WebAnnotationSet.getDeclaredFields(clazz); >+ if (fields != null && fields.length > 0) { >+ for (Field field : fields) { >+ if (injectionTarget.getTargetName().equals(field.getName())) { >+ return field.getType(); >+ } >+ } >+ } >+ return null; >+ } >+ >+ private Class<?> convertPrimitiveType(Class<?> clazz) { >+ Class<?> convertedClass = clazz; >+ if (clazz.equals(char.class)) { >+ convertedClass = Character.class; >+ } else if (clazz.equals(int.class)) { >+ convertedClass = Integer.class; >+ } else if (clazz.equals(boolean.class)) { >+ convertedClass = Boolean.class; >+ } else if (clazz.equals(double.class)) { >+ convertedClass = Double.class; >+ } else if (clazz.equals(byte.class)) { >+ convertedClass = Byte.class; >+ } else if (clazz.equals(short.class)) { >+ convertedClass = Short.class; >+ } else if (clazz.equals(long.class)) { >+ convertedClass = Long.class; >+ } else if (clazz.equals(float.class)) { >+ convertedClass = Float.class; >+ } >+ >+ return convertedClass; >+ } >+ > // ------------------------------------------------------- Lifecycle methods > > @Override >Index: java/org/apache/catalina/startup/WebAnnotationSet.java >=================================================================== >--- java/org/apache/catalina/startup/WebAnnotationSet.java (revision 1344406) >+++ java/org/apache/catalina/startup/WebAnnotationSet.java (working copy) >@@ -437,7 +437,7 @@ > } > > >- private static Field[] getDeclaredFields(Class<?> classClass) { >+ public static Field[] getDeclaredFields(Class<?> classClass) { > Field[] fields = null; > if (Globals.IS_SECURITY_ENABLED) { > final Class<?> clazz = classClass; >@@ -455,7 +455,7 @@ > } > > >- private static Method[] getDeclaredMethods(Class<?> classClass) { >+ public static Method[] getDeclaredMethods(Class<?> classClass) { > Method[] methods = null; > if (Globals.IS_SECURITY_ENABLED) { > final Class<?> clazz = classClass; >@@ -473,7 +473,7 @@ > } > > >- private static Class<?> loadClass(Context context, String fileString) { >+ public static Class<?> loadClass(Context context, String fileString) { > ClassLoader classLoader = context.getLoader().getClassLoader(); > Class<?> classClass = null; > try {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 53333
:
28863
| 28864