src/share/jaxws_classes/com/sun/xml/internal/ws/util/InjectionPlan.java

changeset 0
373ffda63c9a
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.ws.util;
27
28 import java.lang.reflect.Field;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 import java.security.AccessController;
33 import java.security.PrivilegedAction;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.List;
37 import java.util.concurrent.Callable;
38
39 import javax.annotation.Resource;
40 import javax.xml.ws.WebServiceException;
41
42 /**
43 * Encapsulates which field/method the injection is done, and performs the
44 * injection.
45 */
46 public abstract class InjectionPlan<T, R> {
47 /**
48 * Perform injection
49 *
50 * @param instance
51 * Instance
52 * @param resource
53 * Resource
54 */
55 public abstract void inject(T instance, R resource);
56
57 /**
58 * Perform injection, but resource is only generated if injection is
59 * necessary.
60 *
61 * @param instance
62 * @param resource
63 */
64 public void inject(T instance, Callable<R> resource) {
65 try {
66 inject(instance, resource.call());
67 } catch(Exception e) {
68 throw new WebServiceException(e);
69 }
70 }
71
72 /*
73 * Injects to a field.
74 */
75 public static class FieldInjectionPlan<T, R> extends
76 InjectionPlan<T, R> {
77 private final Field field;
78
79 public FieldInjectionPlan(Field field) {
80 this.field = field;
81 }
82
83 public void inject(final T instance, final R resource) {
84 AccessController.doPrivileged(new PrivilegedAction<Object>() {
85 public Object run() {
86 try {
87 if (!field.isAccessible()) {
88 field.setAccessible(true);
89 }
90 field.set(instance, resource);
91 return null;
92 } catch (IllegalAccessException e) {
93 throw new WebServiceException(e);
94 }
95 }
96 });
97 }
98 }
99
100 /*
101 * Injects to a method.
102 */
103 public static class MethodInjectionPlan<T, R> extends
104 InjectionPlan<T, R> {
105 private final Method method;
106
107 public MethodInjectionPlan(Method method) {
108 this.method = method;
109 }
110
111 public void inject(T instance, R resource) {
112 invokeMethod(method, instance, resource);
113 }
114 }
115
116 /*
117 * Helper for invoking a method with elevated privilege.
118 */
119 private static void invokeMethod(final Method method, final Object instance, final Object... args) {
120 if(method==null) return;
121 AccessController.doPrivileged(new PrivilegedAction<Void>() {
122 public Void run() {
123 try {
124 if (!method.isAccessible()) {
125 method.setAccessible(true);
126 }
127 method.invoke(instance,args);
128 } catch (IllegalAccessException e) {
129 throw new WebServiceException(e);
130 } catch (InvocationTargetException e) {
131 throw new WebServiceException(e);
132 }
133 return null;
134 }
135 });
136 }
137
138 /*
139 * Combines multiple {@link InjectionPlan}s into one.
140 */
141 private static class Compositor<T, R> extends InjectionPlan<T, R> {
142 private final Collection<InjectionPlan<T, R>> children;
143
144 public Compositor(Collection<InjectionPlan<T, R>> children) {
145 this.children = children;
146 }
147
148 public void inject(T instance, R res) {
149 for (InjectionPlan<T, R> plan : children)
150 plan.inject(instance, res);
151 }
152
153 public void inject(T instance, Callable<R> resource) {
154 if (!children.isEmpty()) {
155 super.inject(instance, resource);
156 }
157 }
158 }
159
160 /*
161 * Creates an {@link InjectionPlan} that injects the given resource type to the given class.
162 *
163 * @param isStatic
164 * Only look for static field/method
165 *
166 */
167 public static <T,R>
168 InjectionPlan<T,R> buildInjectionPlan(Class<? extends T> clazz, Class<R> resourceType, boolean isStatic) {
169 List<InjectionPlan<T,R>> plan = new ArrayList<InjectionPlan<T,R>>();
170
171 Class<?> cl = clazz;
172 while(cl != Object.class) {
173 for(Field field: cl.getDeclaredFields()) {
174 Resource resource = field.getAnnotation(Resource.class);
175 if (resource != null) {
176 if(isInjectionPoint(resource, field.getType(),
177 "Incorrect type for field"+field.getName(),
178 resourceType)) {
179
180 if(isStatic && !Modifier.isStatic(field.getModifiers()))
181 throw new WebServiceException("Static resource "+resourceType+" cannot be injected to non-static "+field);
182
183 plan.add(new FieldInjectionPlan<T,R>(field));
184 }
185 }
186 }
187 cl = cl.getSuperclass();
188 }
189
190 cl = clazz;
191 while(cl != Object.class) {
192 for(Method method : cl.getDeclaredMethods()) {
193 Resource resource = method.getAnnotation(Resource.class);
194 if (resource != null) {
195 Class[] paramTypes = method.getParameterTypes();
196 if (paramTypes.length != 1)
197 throw new WebServiceException("Incorrect no of arguments for method "+method);
198 if(isInjectionPoint(resource,paramTypes[0],
199 "Incorrect argument types for method"+method.getName(),
200 resourceType)) {
201
202 if(isStatic && !Modifier.isStatic(method.getModifiers()))
203 throw new WebServiceException("Static resource "+resourceType+" cannot be injected to non-static "+method);
204
205 plan.add(new MethodInjectionPlan<T,R>(method));
206 }
207 }
208 }
209 cl = cl.getSuperclass();
210 }
211
212 return new Compositor<T,R>(plan);
213 }
214
215 /*
216 * Returns true if the combination of {@link Resource} and the field/method type
217 * are consistent for {@link WebServiceContext} injection.
218 */
219 private static boolean isInjectionPoint(Resource resource, Class fieldType, String errorMessage, Class resourceType ) {
220 Class t = resource.type();
221 if (t.equals(Object.class)) {
222 return fieldType.equals(resourceType);
223 } else if (t.equals(resourceType)) {
224 if (fieldType.isAssignableFrom(resourceType)) {
225 return true;
226 } else {
227 // type compatibility error
228 throw new WebServiceException(errorMessage);
229 }
230 }
231 return false;
232 }
233 }

mercurial