Thu, 31 Aug 2017 15:18:52 +0800
merge
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 */
26 package com.sun.xml.internal.ws.api;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.Nullable;
30 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
31 import com.sun.xml.internal.ws.api.server.Container;
32 import com.sun.xml.internal.ws.api.server.ContainerResolver;
33 import com.sun.xml.internal.ws.api.server.WSEndpoint;
34 import com.sun.xml.internal.ws.client.WSServiceDelegate;
36 import javax.xml.bind.JAXBContext;
37 import javax.xml.namespace.QName;
38 import javax.xml.ws.Dispatch;
39 import javax.xml.ws.EndpointReference;
40 import javax.xml.ws.Service;
41 import javax.xml.ws.Service.Mode;
42 import javax.xml.ws.WebServiceException;
43 import javax.xml.ws.WebServiceFeature;
44 import javax.xml.ws.spi.ServiceDelegate;
45 import java.lang.reflect.Field;
46 import java.net.URL;
47 import java.security.AccessController;
48 import java.security.PrivilegedAction;
49 import java.util.HashSet;
50 import java.util.Set;
51 import java.util.concurrent.CopyOnWriteArraySet;
53 /**
54 * JAX-WS implementation of {@link ServiceDelegate}.
55 *
56 * <p>
57 * This abstract class is used only to improve the static type safety
58 * of the JAX-WS internal API.
59 *
60 * <p>
61 * The class name intentionally doesn't include "Delegate",
62 * because the fact that it's a delegate is a detail of
63 * the JSR-224 API, and for the layers above us this object
64 * nevertheless represents {@link Service}. We want them
65 * to think of this as an internal representation of a service.
66 *
67 * <p>
68 * Only JAX-WS internal code may downcast this to {@link WSServiceDelegate}.
69 *
70 * @author Kohsuke Kawaguchi
71 */
72 public abstract class WSService extends ServiceDelegate implements ComponentRegistry {
73 private final Set<Component> components = new CopyOnWriteArraySet<Component>();
75 protected WSService() {
76 }
78 /**
79 * Works like {@link #getPort(EndpointReference, Class, WebServiceFeature...)}
80 * but takes {@link WSEndpointReference}.
81 */
82 public abstract <T> T getPort(WSEndpointReference epr, Class<T> portInterface, WebServiceFeature... features);
84 /**
85 * Works like {@link #createDispatch(javax.xml.ws.EndpointReference, java.lang.Class, javax.xml.ws.Service.Mode, javax.xml.ws.WebServiceFeature[])}
86 * but it takes the port name separately, so that EPR without embedded metadata can be used.
87 */
88 public abstract <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeature... features);
90 /**
91 * Works like {@link #createDispatch(javax.xml.ws.EndpointReference, javax.xml.bind.JAXBContext, javax.xml.ws.Service.Mode, javax.xml.ws.WebServiceFeature[])}
92 * but it takes the port name separately, so that EPR without embedded metadata can be used.
93 */
94 public abstract Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... features);
96 /**
97 * Gets the {@link Container} object.
98 *
99 * <p>
100 * The components inside {@link WSEndpoint} uses this reference
101 * to communicate with the hosting environment.
102 *
103 * @return
104 * always same object. If no "real" {@link Container} instance
105 * is given, {@link Container#NONE} will be returned.
106 */
107 public abstract @NotNull Container getContainer();
109 public @Nullable <S> S getSPI(@NotNull Class<S> spiType) {
110 for (Component c : components) {
111 S s = c.getSPI(spiType);
112 if (s != null)
113 return s;
114 }
116 return getContainer().getSPI(spiType);
117 }
119 public @NotNull Set<Component> getComponents() {
120 return components;
121 }
123 /**
124 * Create a <code>Service</code> instance.
125 *
126 * The specified WSDL document location and service qualified name MUST
127 * uniquely identify a <code>wsdl:service</code> element.
128 *
129 * @param wsdlDocumentLocation URL for the WSDL document location
130 * for the service
131 * @param serviceName QName for the service
132 * @throws WebServiceException If any error in creation of the
133 * specified service.
134 **/
135 public static WSService create( URL wsdlDocumentLocation, QName serviceName) {
136 return new WSServiceDelegate(wsdlDocumentLocation,serviceName,Service.class);
137 }
139 /**
140 * Create a <code>Service</code> instance.
141 *
142 * @param serviceName QName for the service
143 * @throws WebServiceException If any error in creation of the
144 * specified service
145 */
146 public static WSService create(QName serviceName) {
147 return create(null,serviceName);
148 }
150 /**
151 * Creates a service with a dummy service name.
152 */
153 public static WSService create() {
154 return create(null,new QName(WSService.class.getName(),"dummy"));
155 }
157 /**
158 * Typed parameter bag used by {@link WSService#create(URL, QName, InitParams)}
159 *
160 * @since 2.1.3
161 */
162 public static final class InitParams {
163 private Container container;
164 /**
165 * Sets the {@link Container} object used by the created service.
166 * This allows the client to use a specific {@link Container} instance
167 * as opposed to the one obtained by {@link ContainerResolver}.
168 */
169 public void setContainer(Container c) {
170 this.container = c;
171 }
172 public Container getContainer() {
173 return container;
174 }
175 }
177 /**
178 * To create a {@link Service}, we need to go through the API that doesn't let us
179 * pass parameters, so as a hack we use thread local.
180 */
181 protected static final ThreadLocal<InitParams> INIT_PARAMS = new ThreadLocal<InitParams>();
183 /**
184 * Used as a immutable constant so that we can avoid null check.
185 */
186 protected static final InitParams EMPTY_PARAMS = new InitParams();
188 /**
189 * Creates a {@link Service} instance.
190 *
191 * <p>
192 * This method works really like {@link Service#create(URL, QName)}
193 * except it takes one more RI specific parameter.
194 *
195 * @param wsdlDocumentLocation
196 * {@code URL} for the WSDL document location for the service.
197 * Can be null, in which case WSDL is not loaded.
198 * @param serviceName
199 * {@code QName} for the service.
200 * @param properties
201 * Additional RI specific initialization parameters. Can be null.
202 * @throws WebServiceException
203 * If any error in creation of the specified service.
204 **/
205 public static Service create( URL wsdlDocumentLocation, QName serviceName, InitParams properties) {
206 if(INIT_PARAMS.get()!=null)
207 throw new IllegalStateException("someone left non-null InitParams");
208 INIT_PARAMS.set(properties);
209 try {
210 Service svc = Service.create(wsdlDocumentLocation, serviceName);
211 if(INIT_PARAMS.get()!=null)
212 throw new IllegalStateException("Service "+svc+" didn't recognize InitParams");
213 return svc;
214 } finally {
215 // even in case of an exception still reset INIT_PARAMS
216 INIT_PARAMS.set(null);
217 }
218 }
220 /**
221 * Obtains the {@link WSService} that's encapsulated inside a {@link Service}.
222 *
223 * @throws IllegalArgumentException
224 * if the given service object is not from the JAX-WS RI.
225 */
226 public static WSService unwrap(final Service svc) {
227 return AccessController.doPrivileged(new PrivilegedAction<WSService>() {
228 public WSService run() {
229 try {
230 Field f = svc.getClass().getField("delegate");
231 f.setAccessible(true);
232 Object delegate = f.get(svc);
233 if(!(delegate instanceof WSService))
234 throw new IllegalArgumentException();
235 return (WSService) delegate;
236 } catch (NoSuchFieldException e) {
237 AssertionError x = new AssertionError("Unexpected service API implementation");
238 x.initCause(e);
239 throw x;
240 } catch (IllegalAccessException e) {
241 IllegalAccessError x = new IllegalAccessError(e.getMessage());
242 x.initCause(e);
243 throw x;
244 }
245 }
246 });
247 }
248 }