View | Details | Raw Unified | Return to bug 53333
Collapse All | Expand All

(-)java/org/apache/catalina/deploy/LocalStrings.properties (+1 lines)
Lines 50-52 Link Here
50
namingResources.cleanupNoResource=Failed to retrieve JNDI resource [{0}] for container [{1}] so no cleanup was performed for that resource
50
namingResources.cleanupNoResource=Failed to retrieve JNDI resource [{0}] for container [{1}] so no cleanup was performed for that resource
51
namingResources.mbeanCreateFail=Failed to create MBean for naming resource [{0}]
51
namingResources.mbeanCreateFail=Failed to create MBean for naming resource [{0}]
52
namingResources.mbeanDestroyFail=Failed to destroy MBean for naming resource [{0}]
52
namingResources.mbeanDestroyFail=Failed to destroy MBean for naming resource [{0}]
53
namingResources.indeterminateResourceType=Cannot determine the resource type for Resource [{0}]
(-)java/org/apache/catalina/deploy/NamingResources.java (+223 lines)
Lines 22-31 Link Here
22
import java.beans.PropertyChangeListener;
22
import java.beans.PropertyChangeListener;
23
import java.beans.PropertyChangeSupport;
23
import java.beans.PropertyChangeSupport;
24
import java.io.Serializable;
24
import java.io.Serializable;
25
import java.lang.reflect.Field;
25
import java.lang.reflect.InvocationTargetException;
26
import java.lang.reflect.InvocationTargetException;
26
import java.lang.reflect.Method;
27
import java.lang.reflect.Method;
27
import java.util.HashMap;
28
import java.util.HashMap;
28
import java.util.Hashtable;
29
import java.util.Hashtable;
30
import java.util.List;
29
31
30
import javax.naming.NamingException;
32
import javax.naming.NamingException;
31
33
Lines 35-41 Link Here
35
import org.apache.catalina.LifecycleException;
37
import org.apache.catalina.LifecycleException;
36
import org.apache.catalina.LifecycleState;
38
import org.apache.catalina.LifecycleState;
37
import org.apache.catalina.Server;
39
import org.apache.catalina.Server;
40
import org.apache.catalina.core.DefaultInstanceManager;
38
import org.apache.catalina.mbeans.MBeanUtils;
41
import org.apache.catalina.mbeans.MBeanUtils;
42
import org.apache.catalina.startup.WebAnnotationSet;
39
import org.apache.catalina.util.LifecycleMBeanBase;
43
import org.apache.catalina.util.LifecycleMBeanBase;
40
import org.apache.juli.logging.Log;
44
import org.apache.juli.logging.Log;
41
import org.apache.juli.logging.LogFactory;
45
import org.apache.juli.logging.LogFactory;
Lines 251-256 Link Here
251
            }
255
            }
252
        }
256
        }
253
        
257
        
258
        // 14.4 Deployment Descriptor Diagram
259
        // If an injection-target is specified for the environment entry, 
260
        // the env-entry-type may be omitted or MUST match the type of the injection target. 
261
        // If no injection-target is specified, the env-entry-type is required.
262
        try {
263
            String type = processResourceType(environment, true);
264
            if (type != null) {
265
                environment.setType(type);
266
            } else {
267
                log.warn(sm.getString("namingResources.indeterminateResourceType", environment));
268
                return;
269
            }
270
        } catch (IllegalArgumentException e) {
271
            log.warn(sm.getString("namingResources.indeterminateResourceType", environment), e);
272
            return;
273
        }
274
        
254
        entries.put(environment.getName(), environment.getType());
275
        entries.put(environment.getName(), environment.getType());
255
276
256
        synchronized (envs) {
277
        synchronized (envs) {
Lines 317-322 Link Here
317
        if (entries.containsKey(mdr.getName())) {
338
        if (entries.containsKey(mdr.getName())) {
318
            return;
339
            return;
319
        } else {
340
        } else {
341
            // 14.4 Deployment Descriptor Diagram
342
            // The message-destination-type MUST be specified unless an injection target is specified, 
343
            // in which case the type of the target is used. 
344
            // If both are specified, the type MUST be assignment compatible with the type of the injection target.
345
            try {
346
                String type = processResourceType(mdr, false);
347
                if (type != null) {
348
                    mdr.setType(type);
349
                } else {
350
                    log.warn(sm.getString("namingResources.indeterminateResourceType", mdr));
351
                    return;
352
                }
353
            } catch (IllegalArgumentException e) {
354
                log.warn(sm.getString("namingResources.indeterminateResourceType", mdr), e);
355
                return;
356
            }
320
            entries.put(mdr.getName(), mdr.getType());
357
            entries.put(mdr.getName(), mdr.getType());
321
        }
358
        }
322
359
Lines 351-356 Link Here
351
        if (entries.containsKey(resource.getName())) {
388
        if (entries.containsKey(resource.getName())) {
352
            return;
389
            return;
353
        } else {
390
        } else {
391
            try {
392
                String type = processResourceType(resource, false);
393
                if (type != null) {
394
                    resource.setType(type);
395
                } else {
396
                    log.warn(sm.getString("namingResources.indeterminateResourceType", resource));
397
                    return;
398
                }
399
            } catch (IllegalArgumentException e) {
400
                log.warn(sm.getString("namingResources.indeterminateResourceType", resource), e);
401
                return;
402
            }
354
            entries.put(resource.getName(), resource.getType());
403
            entries.put(resource.getName(), resource.getType());
355
        }
404
        }
356
405
Lines 382-387 Link Here
382
        if (entries.containsKey(resource.getName())) {
431
        if (entries.containsKey(resource.getName())) {
383
            return;
432
            return;
384
        } else {
433
        } else {
434
            // 14.4 Deployment Descriptor Diagram
435
            // The resource-env-ref-type MUST be supplied unless an injection target is specified, 
436
            // in which case the type of the target is used. 
437
            // If both are specified, the type MUST be assignment compatible with the type of the injection target.
438
            try {
439
                String type = processResourceType(resource, false);
440
                if (type != null) {
441
                    resource.setType(type);
442
                } else {
443
                    log.warn(sm.getString("namingResources.indeterminateResourceType", resource));
444
                    return;
445
                }
446
            } catch (IllegalArgumentException e) {
447
                log.warn(sm.getString("namingResources.indeterminateResourceType", resource), e);
448
                return;
449
            }
385
            entries.put(resource.getName(), resource.getType());
450
            entries.put(resource.getName(), resource.getType());
386
        }
451
        }
387
452
Lines 907-913 Link Here
907
        
972
        
908
    }
973
    }
909
974
975
    /**
976
     * Determines the resource type.
977
     * 
978
     * @param resourceBase the resource
979
     * @param exactMatch true if the resource type must match the type of the injection target, 
980
     * false if the type must be assignment compatible with the type of the injection target
981
     * @return resource type
982
     */
983
    private String processResourceType(ResourceBase resourceBase, boolean exactMatch) {
984
        String type = resourceBase.getType(); 
985
        if (!(container instanceof Context)) {
986
            return type;
987
        }
910
988
989
        Context context = (Context) container;
990
        
991
        if (context.getLoader() == null || context.getLoader().getClassLoader() == null) {
992
            return type;
993
        }
994
995
        Class<?> typeClass = null;
996
        if (type != null) {
997
            typeClass = WebAnnotationSet.loadClass(context, type);
998
            if (typeClass == null) {
999
                // Cannot load the class
1000
                return type;
1001
            }
1002
        }
1003
1004
        Class<?> injectionTargetType = getInjectionTargetType(context, resourceBase.getInjectionTargets(), resourceBase);
1005
1006
        if (typeClass != null) {
1007
            if (injectionTargetType != null) {
1008
                boolean typeMatches = (exactMatch) ? typeClass.equals(injectionTargetType) : injectionTargetType.isAssignableFrom(typeClass);
1009
                if(!typeMatches) {
1010
                    throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " +
1011
                            "Resource type '" + typeClass.getCanonicalName() + "' must match the type or assignment " +
1012
                            "compatible with the type '" + injectionTargetType.getCanonicalName() + "' of the injection target.");
1013
                }
1014
            }
1015
        } else if (injectionTargetType != null) {
1016
            type = injectionTargetType.getCanonicalName();
1017
        } else {
1018
            throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " +
1019
                    "The resource type and the injection target are missing.");
1020
        }
1021
        
1022
        return type;
1023
    }
1024
1025
    /**
1026
     * An injection-target specifies a class and a name within that class into which a resource should be injected. 
1027
     * The injection-target-class specifies the fully qualified class name that is the target of the injection. 
1028
     * The injection-target-name specifies the target within the specified class. 
1029
     * The target is first looked for as a JavaBean property name. If not found, the target is looked for as a field name.
1030
     * 
1031
     * @param context context that will be use for loading injection target classes
1032
     * @param injectionTargets list with all injection targets specified for the resource.
1033
     * @param resourceBase the resource
1034
     * 
1035
     * @return the type of the specified injection-target-name
1036
     */
1037
    private Class<?> getInjectionTargetType(Context context, List<InjectionTarget> injectionTargets, ResourceBase resourceBase) {
1038
        Class<?> type = null;
1039
1040
        if (injectionTargets != null && injectionTargets.size() > 0) {
1041
            for (InjectionTarget injectionTarget : injectionTargets) {
1042
                Class<?> clazz = WebAnnotationSet.loadClass(context, injectionTarget.getTargetClass());
1043
                if (clazz == null) {
1044
                    continue;
1045
                }
1046
1047
                Class<?> propertyType = getPropertyType(injectionTarget, clazz);
1048
                if (propertyType != null) {
1049
                    propertyType = convertPrimitiveType(propertyType);
1050
                    if (type == null) {
1051
                        type = propertyType;
1052
                    } else if (!type.equals(propertyType)) {
1053
                        // The Servlet Specification does not describe
1054
                        // how servlet container should handle multiple injection targets with different types
1055
                        throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " +
1056
                                "Resource type amongst injections targets is not the same.");
1057
                    }
1058
                    continue;
1059
                }
1060
1061
                Class<?> fieldType = getFieldType(injectionTarget, clazz);
1062
                if (fieldType != null) {
1063
                    fieldType = convertPrimitiveType(fieldType);
1064
                    if (type == null) {
1065
                        type = fieldType;
1066
                    } else if (!type.equals(fieldType)) {
1067
                        // The Servlet Specification does not describe
1068
                        // how servlet container should handle multiple injection targets with different types
1069
                        throw new IllegalArgumentException("Resource " + resourceBase + " cannot be processed. " +
1070
                                "Resource type amongst injections targets is not the same.");
1071
                    }
1072
                    continue;
1073
                }
1074
            }
1075
        }
1076
1077
        return type;
1078
    }
1079
1080
    private Class<?> getPropertyType(InjectionTarget injectionTarget, Class<?> clazz) {
1081
        Method[] methods = WebAnnotationSet.getDeclaredMethods(clazz);
1082
        if (methods != null && methods.length > 0) {
1083
            for (Method method : methods) {
1084
                String methodName = method.getName();
1085
                if (methodName.startsWith("set") 
1086
                        && methodName.length() > 3 
1087
                        && method.getParameterTypes().length == 1 
1088
                        && method.getReturnType().getName().equals("void")) {
1089
                    String fieldName = DefaultInstanceManager.getName(method);
1090
                    if (injectionTarget.getTargetName().equals(fieldName)) {
1091
                        return (method.getParameterTypes()[0]);
1092
                    }
1093
                }
1094
            }
1095
        }
1096
        return null;
1097
    }
1098
1099
    private Class<?> getFieldType(InjectionTarget injectionTarget, Class<?> clazz) {
1100
        Field[] fields = WebAnnotationSet.getDeclaredFields(clazz);
1101
        if (fields != null && fields.length > 0) {
1102
            for (Field field : fields) {
1103
                if (injectionTarget.getTargetName().equals(field.getName())) {
1104
                    return field.getType();
1105
                }
1106
            }
1107
        }
1108
        return null;
1109
    }
1110
1111
    private Class<?> convertPrimitiveType(Class<?> clazz) {
1112
        Class<?> convertedClass = clazz;
1113
        if (clazz.equals(char.class)) {
1114
            convertedClass = Character.class;
1115
        } else if (clazz.equals(int.class)) {
1116
            convertedClass = Integer.class;
1117
        } else if (clazz.equals(boolean.class)) {
1118
            convertedClass = Boolean.class;
1119
        } else if (clazz.equals(double.class)) {
1120
            convertedClass = Double.class;
1121
        } else if (clazz.equals(byte.class)) {
1122
            convertedClass = Byte.class;
1123
        } else if (clazz.equals(short.class)) {
1124
            convertedClass = Short.class;
1125
        } else if (clazz.equals(long.class)) {
1126
            convertedClass = Long.class;
1127
        } else if (clazz.equals(float.class)) {
1128
            convertedClass = Float.class;
1129
        }
1130
1131
        return convertedClass;
1132
    }
1133
911
    // ------------------------------------------------------- Lifecycle methods
1134
    // ------------------------------------------------------- Lifecycle methods
912
    
1135
    
913
    @Override
1136
    @Override
(-)java/org/apache/catalina/startup/WebAnnotationSet.java (-3 / +3 lines)
Lines 437-443 Link Here
437
    }
437
    }
438
438
439
439
440
    private static Field[] getDeclaredFields(Class<?> classClass) {
440
    public static Field[] getDeclaredFields(Class<?> classClass) {
441
        Field[] fields = null;
441
        Field[] fields = null;
442
        if (Globals.IS_SECURITY_ENABLED) {
442
        if (Globals.IS_SECURITY_ENABLED) {
443
            final Class<?> clazz = classClass;
443
            final Class<?> clazz = classClass;
Lines 455-461 Link Here
455
    }
455
    }
456
456
457
457
458
    private static Method[] getDeclaredMethods(Class<?> classClass) {
458
    public static Method[] getDeclaredMethods(Class<?> classClass) {
459
        Method[] methods = null;
459
        Method[] methods = null;
460
        if (Globals.IS_SECURITY_ENABLED) {
460
        if (Globals.IS_SECURITY_ENABLED) {
461
            final Class<?> clazz = classClass;
461
            final Class<?> clazz = classClass;
Lines 473-479 Link Here
473
    }
473
    }
474
474
475
475
476
    private static Class<?> loadClass(Context context, String fileString) {
476
    public static Class<?> loadClass(Context context, String fileString) {
477
        ClassLoader classLoader = context.getLoader().getClassLoader();
477
        ClassLoader classLoader = context.getLoader().getClassLoader();
478
        Class<?> classClass = null;
478
        Class<?> classClass = null;
479
        try {
479
        try {

Return to bug 53333