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 |