src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/InstanceResolver.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2013, 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.api.server;
27
28 import com.sun.istack.internal.NotNull;
29 import com.sun.xml.internal.ws.api.message.Message;
30 import com.sun.xml.internal.ws.api.message.Packet;
31 import com.sun.xml.internal.ws.resources.ServerMessages;
32 import com.sun.xml.internal.ws.resources.WsservletMessages;
33 import com.sun.xml.internal.ws.server.ServerRtException;
34 import com.sun.xml.internal.ws.server.SingletonResolver;
35
36 import javax.xml.ws.Provider;
37 import javax.xml.ws.WebServiceContext;
38 import javax.xml.ws.WebServiceException;
39 import java.lang.annotation.Annotation;
40 import java.lang.reflect.InvocationTargetException;
41 import java.lang.reflect.Method;
42 import java.util.logging.Level;
43 import java.util.logging.Logger;
44
45 /**
46 * Determines the instance that serves
47 * the given request packet.
48 *
49 * <p>
50 * The JAX-WS spec always use a singleton instance
51 * to serve all the requests, but this hook provides
52 * a convenient way to route messages to a proper receiver.
53 *
54 * <p>
55 * Externally, an instance of {@link InstanceResolver} is
56 * associated with {@link WSEndpoint}.
57 *
58 * <h2>Possible Uses</h2>
59 * <p>
60 * One can use WS-Addressing message properties to
61 * decide which instance to deliver a message. This
62 * would be an important building block for a stateful
63 * web services.
64 *
65 * <p>
66 * One can associate an instance of a service
67 * with a specific WS-RM session.
68 *
69 * @author Kohsuke Kawaguchi
70 */
71 public abstract class InstanceResolver<T> {
72 /**
73 * Decides which instance of 'T' serves the given request message.
74 *
75 * <p>
76 * This method is called concurrently by multiple threads.
77 * It is also on a criticail path that affects the performance.
78 * A good implementation should try to avoid any synchronization,
79 * and should minimize the amount of work as much as possible.
80 *
81 * @param request
82 * Always non-null. Represents the request message to be served.
83 * The caller may not consume the {@link Message}.
84 */
85 public abstract @NotNull T resolve(@NotNull Packet request);
86
87 /**
88 * Called by the default {@link Invoker} after the method call is done.
89 * This gives {@link InstanceResolver} a chance to do clean up.
90 *
91 * <p>
92 * Alternatively, one could override {@link #createInvoker()} to
93 * create a custom invoker to do this in more flexible way.
94 *
95 * <p>
96 * The default implementation is a no-op.
97 *
98 * @param request
99 * The same request packet given to {@link #resolve(Packet)} method.
100 * @param servant
101 * The object returned from the {@link #resolve(Packet)} method.
102 * @since 2.1.2
103 */
104 public void postInvoke(@NotNull Packet request, @NotNull T servant) {
105 }
106
107 /**
108 * Called by {@link WSEndpoint} when it's set up.
109 *
110 * <p>
111 * This is an opportunity for {@link InstanceResolver}
112 * to do a endpoint-specific initialization process.
113 *
114 * @param wsc
115 * The {@link WebServiceContext} instance to be injected
116 * to the user instances (assuming {@link InstanceResolver}
117 */
118 public void start(@NotNull WSWebServiceContext wsc, @NotNull WSEndpoint endpoint) {
119 // backward compatibility
120 start(wsc);
121 }
122
123 /**
124 * @deprecated
125 * Use {@link #start(WSWebServiceContext,WSEndpoint)}.
126 */
127 public void start(@NotNull WebServiceContext wsc) {}
128
129 /**
130 * Called by {@link WSEndpoint}
131 * when {@link WSEndpoint#dispose()} is called.
132 *
133 * This allows {@link InstanceResolver} to do final clean up.
134 *
135 * <p>
136 * This method is guaranteed to be only called once by {@link WSEndpoint}.
137 */
138 public void dispose() {}
139
140
141 /**
142 * Creates a {@link InstanceResolver} implementation that always
143 * returns the specified singleton instance.
144 */
145 public static <T> InstanceResolver<T> createSingleton(T singleton) {
146 assert singleton!=null;
147 InstanceResolver ir = createFromInstanceResolverAnnotation(singleton.getClass());
148 if(ir==null)
149 ir = new SingletonResolver<T>(singleton);
150 return ir;
151 }
152
153 /**
154 * @deprecated
155 * This is added here because a Glassfish integration happened
156 * with this signature. Please do not use this. Will be removed
157 * after the next GF integration.
158 */
159 public static <T> InstanceResolver<T> createDefault(@NotNull Class<T> clazz, boolean bool) {
160 return createDefault(clazz);
161 }
162
163 /**
164 * Creates a default {@link InstanceResolver} that serves the given class.
165 */
166 public static <T> InstanceResolver<T> createDefault(@NotNull Class<T> clazz) {
167 InstanceResolver<T> ir = createFromInstanceResolverAnnotation(clazz);
168 if(ir==null)
169 ir = new SingletonResolver<T>(createNewInstance(clazz));
170 return ir;
171 }
172
173 /**
174 * Checks for {@link InstanceResolverAnnotation} and creates an instance resolver from it if any.
175 * Otherwise null.
176 */
177 public static <T> InstanceResolver<T> createFromInstanceResolverAnnotation(@NotNull Class<T> clazz) {
178 for( Annotation a : clazz.getAnnotations() ) {
179 InstanceResolverAnnotation ira = a.annotationType().getAnnotation(InstanceResolverAnnotation.class);
180 if(ira==null) continue;
181 Class<? extends InstanceResolver> ir = ira.value();
182 try {
183 return ir.getConstructor(Class.class).newInstance(clazz);
184 } catch (InstantiationException e) {
185 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
186 ir.getName(),a.annotationType(),clazz.getName()));
187 } catch (IllegalAccessException e) {
188 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
189 ir.getName(),a.annotationType(),clazz.getName()));
190 } catch (InvocationTargetException e) {
191 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
192 ir.getName(),a.annotationType(),clazz.getName()));
193 } catch (NoSuchMethodException e) {
194 throw new WebServiceException(ServerMessages.FAILED_TO_INSTANTIATE_INSTANCE_RESOLVER(
195 ir.getName(),a.annotationType(),clazz.getName()));
196 }
197 }
198
199 return null;
200 }
201
202 protected static <T> T createNewInstance(Class<T> cl) {
203 try {
204 return cl.newInstance();
205 } catch (InstantiationException e) {
206 logger.log(Level.SEVERE, e.getMessage(), e);
207 throw new ServerRtException(
208 WsservletMessages.ERROR_IMPLEMENTOR_FACTORY_NEW_INSTANCE_FAILED(cl));
209 } catch (IllegalAccessException e) {
210 logger.log(Level.SEVERE, e.getMessage(), e);
211 throw new ServerRtException(
212 WsservletMessages.ERROR_IMPLEMENTOR_FACTORY_NEW_INSTANCE_FAILED(cl));
213 }
214 }
215
216 /**
217 * Wraps this {@link InstanceResolver} into an {@link Invoker}.
218 */
219 public @NotNull Invoker createInvoker() {
220 return new Invoker() {
221 @Override
222 public void start(@NotNull WSWebServiceContext wsc, @NotNull WSEndpoint endpoint) {
223 InstanceResolver.this.start(wsc,endpoint);
224 }
225
226 @Override
227 public void dispose() {
228 InstanceResolver.this.dispose();
229 }
230
231 @Override
232 public Object invoke(Packet p, Method m, Object... args) throws InvocationTargetException, IllegalAccessException {
233 T t = resolve(p);
234 try {
235 return MethodUtil.invoke(t, m, args );
236 } finally {
237 postInvoke(p,t);
238 }
239 }
240
241 @Override
242 public <U> U invokeProvider(@NotNull Packet p, U arg) {
243 T t = resolve(p);
244 try {
245 return ((Provider<U>) t).invoke(arg);
246 } finally {
247 postInvoke(p,t);
248 }
249 }
250
251 public String toString() {
252 return "Default Invoker over "+InstanceResolver.this.toString();
253 }
254 };
255 }
256
257 private static final Logger logger =
258 Logger.getLogger(
259 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
260 }

mercurial