Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2010, 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 */
26 package com.sun.xml.internal.ws.api.server;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.Nullable;
30 import com.sun.xml.internal.ws.api.BindingID;
31 import com.sun.xml.internal.ws.api.Component;
32 import com.sun.xml.internal.ws.api.ComponentRegistry;
33 import com.sun.xml.internal.ws.api.WSBinding;
34 import com.sun.xml.internal.ws.api.config.management.EndpointCreationAttributes;
35 import com.sun.xml.internal.ws.api.config.management.ManagedEndpointFactory;
36 import com.sun.xml.internal.ws.api.message.Message;
37 import com.sun.xml.internal.ws.api.message.Packet;
38 import com.sun.xml.internal.ws.api.model.SEIModel;
39 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
40 import com.sun.xml.internal.ws.api.pipe.Codec;
41 import com.sun.xml.internal.ws.api.pipe.Engine;
42 import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptor;
43 import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext;
44 import com.sun.xml.internal.ws.api.pipe.Tube;
45 import com.sun.xml.internal.ws.policy.PolicyMap;
46 import com.sun.xml.internal.ws.server.EndpointFactory;
47 import com.sun.xml.internal.ws.util.ServiceFinder;
48 import com.sun.xml.internal.ws.util.xml.XmlUtil;
49 import com.sun.org.glassfish.gmbal.ManagedObjectManager;
50 import org.xml.sax.EntityResolver;
52 import javax.xml.namespace.QName;
53 import javax.xml.ws.Binding;
54 import javax.xml.ws.WebServiceContext;
55 import javax.xml.ws.WebServiceException;
56 import java.net.URL;
57 import java.util.Collection;
58 import java.util.Collections;
59 import java.util.Iterator;
60 import java.util.List;
61 import java.util.Set;
62 import java.util.concurrent.Executor;
64 /**
65 * Root object that hosts the {@link Packet} processing code
66 * at the server.
67 *
68 * <p>
69 * One instance of {@link WSEndpoint} is created for each deployed service
70 * endpoint. A hosted service usually handles multiple concurrent
71 * requests. To do this efficiently, an endpoint handles incoming
72 * {@link Packet} through {@link PipeHead}s, where many copies can be created
73 * for each endpoint.
74 *
75 * <p>
76 * Each {@link PipeHead} is thread-unsafe, and request needs to be
77 * serialized. A {@link PipeHead} represents a sizable resource
78 * (in particular a whole pipeline), so the caller is expected to
79 * reuse them and avoid excessive allocations as much as possible.
80 * Making {@link PipeHead}s thread-unsafe allow the JAX-WS RI internal to
81 * tie thread-local resources to {@link PipeHead}, and reduce the total
82 * resource management overhead.
83 *
84 * <p>
85 * To abbreviate this resource management (and for a few other reasons),
86 * JAX-WS RI provides {@link Adapter} class. If you are hosting a JAX-WS
87 * service, you'll most likely want to send requests to {@link WSEndpoint}
88 * through {@link Adapter}.
89 *
90 * <p>
91 * {@link WSEndpoint} is ready to handle {@link Packet}s as soon as
92 * it's created. No separate post-initialization step is necessary.
93 * However, to comply with the JAX-WS spec requirement, the caller
94 * is expected to call the {@link #dispose()} method to allow an
95 * orderly shut-down of a hosted service.
96 *
97 *
98 *
99 * <h3>Objects Exposed From Endpoint</h3>
100 * <p>
101 * {@link WSEndpoint} exposes a series of information that represents
102 * how an endpoint is configured to host a service. See the getXXX methods
103 * for more details.
104 *
105 *
106 *
107 * <h3>Implementation Notes</h3>
108 * <p>
109 * {@link WSEndpoint} owns a {@link WSWebServiceContext} implementation.
110 * But a bulk of the work is delegated to {@link WebServiceContextDelegate},
111 * which is passed in as a parameter to {@link PipeHead#process(Packet, WebServiceContextDelegate, TransportBackChannel)}.
112 *
113 * @author Kohsuke Kawaguchi
114 */
115 public abstract class WSEndpoint<T> implements ComponentRegistry {
117 /**
118 * Gets the Endpoint's codec that is used to encode/decode {@link Message}s. This is a
119 * copy of the master codec and it shouldn't be shared across two requests running
120 * concurrently(unless it is stateless).
121 *
122 * @return codec to encode/decode
123 */
124 public abstract @NotNull Codec createCodec();
126 /**
127 * Gets the application endpoint's serviceName. It could be got from DD or annotations
128 *
129 * @return same as wsdl:service QName if WSDL exists or generated
130 */
131 public abstract @NotNull QName getServiceName();
133 /**
134 * Gets the application endpoint's portName. It could be got from DD or annotations
135 *
136 * @return same as wsdl:port QName if WSDL exists or generated
137 */
138 public abstract @NotNull QName getPortName();
140 /**
141 * Gets the application endpoint {@link Class} that eventually serves the request.
142 *
143 * <p>
144 * This is the same value given to the {@link #create} method.
145 */
146 public abstract @NotNull Class<T> getImplementationClass();
148 /**
149 * Represents the binding for which this {@link WSEndpoint}
150 * is created for.
151 *
152 * @return
153 * always same object.
154 */
155 public abstract @NotNull WSBinding getBinding();
157 /**
158 * Gets the {@link Container} object.
159 *
160 * <p>
161 * The components inside {@link WSEndpoint} uses this reference
162 * to communicate with the hosting environment.
163 *
164 * @return
165 * always same object. If no "real" {@link Container} instance
166 * is given, {@link Container#NONE} will be returned.
167 */
168 public abstract @NotNull Container getContainer();
170 /**
171 * Gets the port that this endpoint is serving.
172 *
173 * <p>
174 * A service is not required to have a WSDL, and when it doesn't,
175 * this method returns null. Otherwise it returns an object that
176 * describes the port that this {@link WSEndpoint} is serving.
177 *
178 * @return
179 * Possibly null, but always the same value.
180 */
181 public abstract @Nullable WSDLPort getPort();
183 /**
184 * Set this {@link Executor} to run asynchronous requests using this executor.
185 * This executor is set on {@link Engine} and must be set before
186 * calling {@link #schedule(Packet,CompletionCallback) } and
187 * {@link #schedule(Packet,CompletionCallback,FiberContextSwitchInterceptor)} methods.
188 *
189 * @param exec Executor to run async requests
190 */
191 public abstract void setExecutor(@NotNull Executor exec);
193 /**
194 * This method takes a {@link Packet} that represents
195 * a request, run it through a {@link Tube}line, eventually
196 * pass it to the user implementation code, which produces
197 * a reply, then run that through the tubeline again,
198 * and eventually return it as a return value through {@link CompletionCallback}.
199 *
200 * <p>
201 * This takes care of pooling of {@link Tube}lines and reuses
202 * tubeline for requests. Same instance of tubeline is not used concurrently
203 * for two requests.
204 *
205 * <p>
206 * If the transport is capable of asynchronous execution, use this
207 * instead of using {@link PipeHead#process}.
208 *
209 * <p>
210 * Before calling this method, set the executor using {@link #setExecutor}. The
211 * executor may used multiple times to run this request in a asynchronous fashion.
212 * The calling thread will be returned immediately, and the callback will be
213 * called in a different a thread.
214 *
215 * <p>
216 * {@link Packet#transportBackChannel} should have the correct value, so that
217 * one-way message processing happens correctly. {@link Packet#webServiceContextDelegate}
218 * should have the correct value, so that some {@link WebServiceContext} methods correctly.
219 *
220 * @see {@link Packet#transportBackChannel}
221 * @see {@link Packet#webServiceContextDelegate}
222 *
223 * @param request web service request
224 * @param callback callback to get response packet
225 */
226 public final void schedule(@NotNull Packet request, @NotNull CompletionCallback callback ) {
227 schedule(request,callback,null);
228 }
230 /**
231 * Schedule invocation of web service asynchronously.
232 *
233 * @see {@link #schedule(Packet, CompletionCallback)}
234 *
235 * @param request web service request
236 * @param callback callback to get response packet(exception if there is one)
237 * @param interceptor caller's interceptor to impose a context of execution
238 */
239 public abstract void schedule(@NotNull Packet request, @NotNull CompletionCallback callback, @Nullable FiberContextSwitchInterceptor interceptor );
241 public void process(@NotNull Packet request, @NotNull CompletionCallback callback, @Nullable FiberContextSwitchInterceptor interceptor ) {
242 schedule(request,callback,interceptor);
243 }
245 /**
246 * Returns {@link Engine} for this endpoint
247 * @return Engine
248 */
249 public Engine getEngine() {
250 throw new UnsupportedOperationException();
251 }
253 /**
254 * Callback to notify that jax-ws runtime has finished execution of a request
255 * submitted via schedule().
256 */
257 public interface CompletionCallback {
258 /**
259 * Indicates that the jax-ws runtime has finished execution of a request
260 * submitted via schedule().
261 *
262 * <p>
263 * Since the JAX-WS RI runs asynchronously,
264 * this method maybe invoked by a different thread
265 * than any of the threads that started it or run a part of tubeline.
266 *
267 * @param response {@link Packet}
268 */
269 void onCompletion(@NotNull Packet response);
270 }
272 /**
273 * Creates a new {@link PipeHead} to process
274 * incoming requests.
275 *
276 * <p>
277 * This is not a cheap operation. The caller is expected
278 * to reuse the returned {@link PipeHead}. See
279 * {@link WSEndpoint class javadoc} for details.
280 *
281 * @return
282 * A newly created {@link PipeHead} that's ready to serve.
283 */
284 public abstract @NotNull PipeHead createPipeHead();
286 /**
287 * Represents a resource local to a thread.
288 *
289 * See {@link WSEndpoint} class javadoc for more discussion about
290 * this.
291 */
292 public interface PipeHead {
293 /**
294 * Processes a request and produces a reply.
295 *
296 * <p>
297 * This method takes a {@link Packet} that represents
298 * a request, run it through a {@link Tube}line, eventually
299 * pass it to the user implementation code, which produces
300 * a reply, then run that through the pipeline again,
301 * and eventually return it as a return value.
302 *
303 * @param request
304 * Unconsumed {@link Packet} that represents
305 * a request.
306 * @param wscd
307 * {@link WebServiceContextDelegate} to be set to {@link Packet}.
308 * (we didn't have to take this and instead just ask the caller to
309 * set to {@link Packet#webServiceContextDelegate}, but that felt
310 * too error prone.)
311 * @param tbc
312 * {@link TransportBackChannel} to be set to {@link Packet}.
313 * See the {@code wscd} parameter javadoc for why this is a parameter.
314 * Can be null.
315 * @return
316 * Unconsumed {@link Packet} that represents
317 * a reply to the request.
318 *
319 * @throws WebServiceException
320 * This method <b>does not</b> throw a {@link WebServiceException}.
321 * The {@link WSEndpoint} must always produce a fault {@link Message}
322 * for it.
323 *
324 * @throws RuntimeException
325 * A {@link RuntimeException} thrown from this method, including
326 * {@link WebServiceException}, must be treated as a bug in the
327 * code (including JAX-WS and all the pipe implementations), not
328 * an operator error by the user.
329 *
330 * <p>
331 * Therefore, it should be recorded by the caller in a way that
332 * allows developers to fix a bug.
333 */
334 @NotNull Packet process(
335 @NotNull Packet request, @Nullable WebServiceContextDelegate wscd, @Nullable TransportBackChannel tbc);
336 }
338 /**
339 * Indicates that the {@link WSEndpoint} is about to be turned off,
340 * and will no longer serve any packet anymore.
341 *
342 * <p>
343 * This method needs to be invoked for the JAX-WS RI to correctly
344 * implement some of the spec semantics (TODO: pointer.)
345 * It's the responsibility of the code that hosts a {@link WSEndpoint}
346 * to invoke this method.
347 *
348 * <p>
349 * Once this method is called, the behavior is undefed for
350 * all in-progress {@link PipeHead#process} methods (by other threads)
351 * and future {@link PipeHead#process} method invocations.
352 */
353 public abstract void dispose();
355 /**
356 * Gets the description of the service.
357 *
358 * <p>
359 * A description is a set of WSDL/schema and other documents that together
360 * describes a service.
361 * A service is not required to have a description, and when it doesn't,
362 * this method returns null.
363 *
364 * @return
365 * Possibly null, always the same value under ordinary circumstances but
366 * may change if the endpoint is managed.
367 */
368 public abstract @Nullable ServiceDefinition getServiceDefinition();
370 /**
371 * Gets the list of {@link BoundEndpoint} that are associated
372 * with this endpoint.
373 *
374 * @return
375 * always return the same set.
376 */
377 public List<BoundEndpoint> getBoundEndpoints() {
378 Module m = getContainer().getSPI(Module.class);
379 return m != null ? m.getBoundEndpoints() : null;
380 }
382 /**
383 * Gets the list of {@link EndpointComponent} that are associated
384 * with this endpoint.
385 *
386 * <p>
387 * Components (such as codec, tube, handler, etc) who wish to provide
388 * some service to other components in the endpoint can iterate the
389 * registry and call its {@link EndpointComponent#getSPI(Class)} to
390 * establish a private contract between components.
391 * <p>
392 * Components who wish to subscribe to such a service can add itself
393 * to this set.
394 *
395 * @return
396 * always return the same set.
397 * @deprecated
398 */
399 public abstract @NotNull Set<EndpointComponent> getComponentRegistry();
401 public @NotNull Set<Component> getComponents() {
402 return Collections.emptySet();
403 }
405 public @Nullable <S> S getSPI(@NotNull Class<S> spiType) {
406 Set<Component> componentRegistry = getComponents();
407 if (componentRegistry != null) {
408 for (Component c : componentRegistry) {
409 S s = c.getSPI(spiType);
410 if (s != null)
411 return s;
412 }
413 }
414 return getContainer().getSPI(spiType);
415 }
417 /**
418 * Gets the {@link com.sun.xml.internal.ws.api.model.SEIModel} that represents the relationship
419 * between WSDL and Java SEI.
420 *
421 * <p>
422 * This method returns a non-null value if and only if this
423 * endpoint is ultimately serving an application through an SEI.
424 *
425 * @return
426 * maybe null. See above for more discussion.
427 * Always the same value.
428 */
429 public abstract @Nullable SEIModel getSEIModel();
431 /**
432 * Gives the PolicMap that captures the Policy for the endpoint
433 *
434 * @return PolicyMap
435 *
436 * @deprecated
437 * Do not use this method as the PolicyMap API is not final yet and might change in next few months.
438 */
439 public abstract PolicyMap getPolicyMap();
441 /**
442 * Get the ManagedObjectManager for this endpoint.
443 */
444 public abstract @NotNull ManagedObjectManager getManagedObjectManager();
446 /**
447 * Close the ManagedObjectManager for this endpoint.
448 * This is used by the Web Service Configuration Management system so that it
449 * closes the MOM before it creates a new WSEndpoint. Then it calls dispose
450 * on the existing endpoint and then installs the new endpoint.
451 * The call to dispose also calls closeManagedObjectManager, but is a noop
452 * if that method has already been called.
453 */
454 public abstract void closeManagedObjectManager();
456 /**
457 * This is only needed to expose info for monitoring.
458 */
459 public abstract @NotNull ServerTubeAssemblerContext getAssemblerContext();
461 /**
462 * Creates an endpoint from deployment or programmatic configuration
463 *
464 * <p>
465 * This method works like the following:
466 * <ol>
467 * <li>{@link ServiceDefinition} is modeleed from the given SEI type.
468 * <li>{@link Invoker} that always serves <tt>implementationObject</tt> will be used.
469 * </ol>
470 * @param implType
471 * Endpoint class(not SEI). Enpoint class must have @WebService or @WebServiceProvider
472 * annotation.
473 * @param processHandlerAnnotation
474 * Flag to control processing of @HandlerChain on Impl class
475 * if true, processes @HandlerChain on Impl
476 * if false, DD might have set HandlerChain no need to parse.
477 * @param invoker
478 * Pass an object to invoke the actual endpoint object. If it is null, a default
479 * invoker is created using {@link InstanceResolver#createDefault}. Appservers
480 * could create its own invoker to do additional functions like transactions,
481 * invoking the endpoint through proxy etc.
482 * @param serviceName
483 * Optional service name(may be from DD) to override the one given by the
484 * implementation class. If it is null, it will be derived from annotations.
485 * @param portName
486 * Optional port name(may be from DD) to override the one given by the
487 * implementation class. If it is null, it will be derived from annotations.
488 * @param container
489 * Allows technologies that are built on top of JAX-WS(such as WSIT) needs to
490 * negotiate private contracts between them and the container
491 * @param binding
492 * JAX-WS implementation of {@link Binding}. This object can be created by
493 * {@link BindingID#createBinding()}. Usually the binding can be got from
494 * DD, {@link javax.xml.ws.BindingType}.
495 *
496 *
497 * TODO: DD has a configuration for MTOM threshold.
498 * Maybe we need something more generic so that other technologies
499 * like Tango can get information from DD.
500 *
501 * TODO: does it really make sense for this to take EntityResolver?
502 * Given that all metadata has to be given as a list anyway.
503 *
504 * @param primaryWsdl
505 * The {@link ServiceDefinition#getPrimary() primary} WSDL.
506 * If null, it'll be generated based on the SEI (if this is an SEI)
507 * or no WSDL is associated (if it's a provider.)
508 * TODO: shouldn't the implementation find this from the metadata list?
509 * @param metadata
510 * Other documents that become {@link SDDocument}s. Can be null.
511 * @param resolver
512 * Optional resolver used to de-reference resources referenced from
513 * WSDL. Must be null if the {@code url} is null.
514 * @param isTransportSynchronous
515 * If the caller knows that the returned {@link WSEndpoint} is going to be
516 * used by a synchronous-only transport, then it may pass in <tt>true</tt>
517 * to allow the callee to perform an optimization based on that knowledge
518 * (since often synchronous version is cheaper than an asynchronous version.)
519 * This value is visible from {@link ServerTubeAssemblerContext#isSynchronous()}.
520 *
521 * @return newly constructed {@link WSEndpoint}.
522 * @throws WebServiceException
523 * if the endpoint set up fails.
524 */
525 public static <T> WSEndpoint<T> create(
526 @NotNull Class<T> implType,
527 boolean processHandlerAnnotation,
528 @Nullable Invoker invoker,
529 @Nullable QName serviceName,
530 @Nullable QName portName,
531 @Nullable Container container,
532 @Nullable WSBinding binding,
533 @Nullable SDDocumentSource primaryWsdl,
534 @Nullable Collection<? extends SDDocumentSource> metadata,
535 @Nullable EntityResolver resolver,
536 boolean isTransportSynchronous) {
537 return create(implType, processHandlerAnnotation, invoker, serviceName, portName, container, binding, primaryWsdl, metadata, resolver, isTransportSynchronous, true);
538 }
540 public static <T> WSEndpoint<T> create(
541 @NotNull Class<T> implType,
542 boolean processHandlerAnnotation,
543 @Nullable Invoker invoker,
544 @Nullable QName serviceName,
545 @Nullable QName portName,
546 @Nullable Container container,
547 @Nullable WSBinding binding,
548 @Nullable SDDocumentSource primaryWsdl,
549 @Nullable Collection<? extends SDDocumentSource> metadata,
550 @Nullable EntityResolver resolver,
551 boolean isTransportSynchronous,
552 boolean isStandard)
553 {
554 final WSEndpoint<T> endpoint =
555 EndpointFactory.createEndpoint(
556 implType,processHandlerAnnotation, invoker,serviceName,portName,container,binding,primaryWsdl,metadata,resolver,isTransportSynchronous,isStandard);
558 final Iterator<ManagedEndpointFactory> managementFactories = ServiceFinder.find(ManagedEndpointFactory.class).iterator();
559 if (managementFactories.hasNext()) {
560 final ManagedEndpointFactory managementFactory = managementFactories.next();
561 final EndpointCreationAttributes attributes = new EndpointCreationAttributes(
562 processHandlerAnnotation, invoker, resolver, isTransportSynchronous);
563 return managementFactory.createEndpoint(endpoint, attributes);
564 }
566 return endpoint;
567 }
569 /**
570 * Deprecated version that assumes <tt>isTransportSynchronous==false</tt>
571 */
572 @Deprecated
573 public static <T> WSEndpoint<T> create(
574 @NotNull Class<T> implType,
575 boolean processHandlerAnnotation,
576 @Nullable Invoker invoker,
577 @Nullable QName serviceName,
578 @Nullable QName portName,
579 @Nullable Container container,
580 @Nullable WSBinding binding,
581 @Nullable SDDocumentSource primaryWsdl,
582 @Nullable Collection<? extends SDDocumentSource> metadata,
583 @Nullable EntityResolver resolver) {
584 return create(implType,processHandlerAnnotation,invoker,serviceName,portName,container,binding,primaryWsdl,metadata,resolver,false);
585 }
588 /**
589 * The same as
590 * {@link #create(Class, boolean, Invoker, QName, QName, Container, WSBinding, SDDocumentSource, Collection, EntityResolver)}
591 * except that this version takes an url of the <tt>jax-ws-catalog.xml</tt>.
592 *
593 * @param catalogUrl
594 * if not null, an {@link EntityResolver} is created from it and used.
595 * otherwise no resolution will be performed.
596 */
597 public static <T> WSEndpoint<T> create(
598 @NotNull Class<T> implType,
599 boolean processHandlerAnnotation,
600 @Nullable Invoker invoker,
601 @Nullable QName serviceName,
602 @Nullable QName portName,
603 @Nullable Container container,
604 @Nullable WSBinding binding,
605 @Nullable SDDocumentSource primaryWsdl,
606 @Nullable Collection<? extends SDDocumentSource> metadata,
607 @Nullable URL catalogUrl) {
608 return create(
609 implType,processHandlerAnnotation,invoker,serviceName,portName,container,binding,primaryWsdl,metadata,
610 XmlUtil.createEntityResolver(catalogUrl),false);
611 }
613 /**
614 * Gives the wsdl:service default name computed from the endpoint implementaiton class
615 */
616 public static @NotNull QName getDefaultServiceName(Class endpointClass){
617 return getDefaultServiceName(endpointClass, true);
618 }
620 public static @NotNull QName getDefaultServiceName(Class endpointClass, boolean isStandard){
621 return EndpointFactory.getDefaultServiceName(endpointClass, isStandard);
622 }
624 /**
625 * Gives the wsdl:service/wsdl:port default name computed from the endpoint implementaiton class
626 */
627 public static @NotNull QName getDefaultPortName(@NotNull QName serviceName, Class endpointClass){
628 return getDefaultPortName(serviceName, endpointClass, true);
629 }
631 public static @NotNull QName getDefaultPortName(@NotNull QName serviceName, Class endpointClass, boolean isStandard){
632 return EndpointFactory.getDefaultPortName(serviceName, endpointClass, isStandard);
633 }
635 }