001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.api;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.xml.ws.api.addressing.WSEndpointReference;
041: import com.sun.xml.ws.api.server.Container;
042: import com.sun.xml.ws.api.server.ContainerResolver;
043: import com.sun.xml.ws.api.server.WSEndpoint;
044: import com.sun.xml.ws.client.WSServiceDelegate;
045:
046: import javax.xml.bind.JAXBContext;
047: import javax.xml.namespace.QName;
048: import javax.xml.ws.Dispatch;
049: import javax.xml.ws.EndpointReference;
050: import javax.xml.ws.Service;
051: import javax.xml.ws.Service.Mode;
052: import javax.xml.ws.WebServiceException;
053: import javax.xml.ws.WebServiceFeature;
054: import javax.xml.ws.spi.ServiceDelegate;
055: import java.lang.reflect.Field;
056: import java.net.URL;
057: import java.security.AccessController;
058: import java.security.PrivilegedAction;
059:
060: /**
061: * JAX-WS implementation of {@link ServiceDelegate}.
062: *
063: * <p>
064: * This abstract class is used only to improve the static type safety
065: * of the JAX-WS internal API.
066: *
067: * <p>
068: * The class name intentionally doesn't include "Delegate",
069: * because the fact that it's a delegate is a detail of
070: * the JSR-224 API, and for the layers above us this object
071: * nevertheless represents {@link Service}. We want them
072: * to think of this as an internal representation of a service.
073: *
074: * <p>
075: * Only JAX-WS internal code may downcast this to {@link WSServiceDelegate}.
076: *
077: * @author Kohsuke Kawaguchi
078: */
079: public abstract class WSService extends ServiceDelegate {
080: protected WSService() {
081: }
082:
083: /**
084: * Works like {@link #getPort(EndpointReference, Class, WebServiceFeature...)}
085: * but takes {@link WSEndpointReference}.
086: */
087: public abstract <T> T getPort(WSEndpointReference epr,
088: Class<T> portInterface, WebServiceFeature... features);
089:
090: /**
091: * Works like {@link #createDispatch(EndpointReference, Class, Mode, WebServiceFeature[])}
092: * but it takes the port name separately, so that EPR without embedded metadata can be used.
093: */
094: public abstract <T> Dispatch<T> createDispatch(QName portName,
095: WSEndpointReference wsepr, Class<T> aClass,
096: Service.Mode mode, WebServiceFeature... features);
097:
098: /**
099: * Works like {@link #createDispatch(EndpointReference, JAXBContext, Mode, WebServiceFeature[])}
100: * but it takes the port name separately, so that EPR without embedded metadata can be used.
101: */
102: public abstract Dispatch<Object> createDispatch(QName portName,
103: WSEndpointReference wsepr, JAXBContext jaxbContext,
104: Service.Mode mode, WebServiceFeature... features);
105:
106: /**
107: * Gets the {@link Container} object.
108: *
109: * <p>
110: * The components inside {@link WSEndpoint} uses this reference
111: * to communicate with the hosting environment.
112: *
113: * @return
114: * always same object. If no "real" {@link Container} instance
115: * is given, {@link Container#NONE} will be returned.
116: */
117: public abstract @NotNull
118: Container getContainer();
119:
120: /**
121: * Create a <code>Service</code> instance.
122: *
123: * The specified WSDL document location and service qualified name MUST
124: * uniquely identify a <code>wsdl:service</code> element.
125: *
126: * @param wsdlDocumentLocation URL for the WSDL document location
127: * for the service
128: * @param serviceName QName for the service
129: * @throws WebServiceException If any error in creation of the
130: * specified service.
131: **/
132: public static WSService create(URL wsdlDocumentLocation,
133: QName serviceName) {
134: return new WSServiceDelegate(wsdlDocumentLocation, serviceName,
135: Service.class);
136: }
137:
138: /**
139: * Create a <code>Service</code> instance.
140: *
141: * @param serviceName QName for the service
142: * @throws WebServiceException If any error in creation of the
143: * specified service
144: */
145: public static WSService create(QName serviceName) {
146: return create(null, serviceName);
147: }
148:
149: /**
150: * Creates a service with a dummy service name.
151: */
152: public static WSService create() {
153: return create(null, new QName(WSService.class.getName(),
154: "dummy"));
155: }
156:
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: /**
166: * Sets the {@link Container} object used by the created service.
167: * This allows the client to use a specific {@link Container} instance
168: * as opposed to the one obtained by {@link ContainerResolver}.
169: */
170: public void setContainer(Container c) {
171: this .container = c;
172: }
173:
174: public Container getContainer() {
175: return container;
176: }
177: }
178:
179: /**
180: * To create a {@link Service}, we need to go through the API that doesn't let us
181: * pass parameters, so as a hack we use thread local.
182: */
183: protected static final ThreadLocal<InitParams> INIT_PARAMS = new ThreadLocal<InitParams>();
184:
185: /**
186: * Used as a immutable constant so that we can avoid null check.
187: */
188: protected static final InitParams EMPTY_PARAMS = new InitParams();
189:
190: /**
191: * Creates a {@link Service} instance.
192: *
193: * <p>
194: * This method works really like {@link Service#create(URL, QName)}
195: * except it takes one more RI specific parameter.
196: *
197: * @param wsdlDocumentLocation
198: * {@code URL} for the WSDL document location for the service.
199: * Can be null, in which case WSDL is not loaded.
200: * @param serviceName
201: * {@code QName} for the service.
202: * @param properties
203: * Additional RI specific initialization parameters. Can be null.
204: * @throws WebServiceException
205: * If any error in creation of the specified service.
206: **/
207: public static Service create(URL wsdlDocumentLocation,
208: QName serviceName, InitParams properties) {
209: if (INIT_PARAMS.get() != null)
210: throw new IllegalStateException(
211: "someone left non-null InitParams");
212: INIT_PARAMS.set(properties);
213: try {
214: Service svc = Service.create(wsdlDocumentLocation,
215: serviceName);
216: if (INIT_PARAMS.get() != null)
217: throw new IllegalStateException("Service " + svc
218: + " didn't recognize InitParams");
219: return svc;
220: } finally {
221: // even in case of an exception still reset INIT_PARAMS
222: INIT_PARAMS.set(null);
223: }
224: }
225:
226: /**
227: * Obtains the {@link WSService} that's encapsulated inside a {@link Service}.
228: *
229: * @throws IllegalArgumentException
230: * if the given service object is not from the JAX-WS RI.
231: */
232: public static WSService unwrap(final Service svc) {
233: return AccessController
234: .doPrivileged(new PrivilegedAction<WSService>() {
235: public WSService run() {
236: try {
237: Field f = svc.getClass().getField(
238: "delegate");
239: f.setAccessible(true);
240: Object delegate = f.get(svc);
241: if (!(delegate instanceof WSService))
242: throw new IllegalArgumentException();
243: return (WSService) delegate;
244: } catch (NoSuchFieldException e) {
245: AssertionError x = new AssertionError(
246: "Unexpected service API implementation");
247: x.initCause(e);
248: throw x;
249: } catch (IllegalAccessException e) {
250: IllegalAccessError x = new IllegalAccessError(
251: e.getMessage());
252: x.initCause(e);
253: throw x;
254: }
255: }
256: });
257: }
258: }
|