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.server;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.SOAPVersion;
042: import com.sun.xml.ws.api.WSBinding;
043: import com.sun.xml.ws.api.addressing.AddressingVersion;
044: import com.sun.xml.ws.api.addressing.WSEndpointReference;
045: import com.sun.xml.ws.api.message.Message;
046: import com.sun.xml.ws.api.message.Packet;
047: import com.sun.xml.ws.api.model.SEIModel;
048: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
049: import com.sun.xml.ws.api.pipe.Codec;
050: import com.sun.xml.ws.api.pipe.Engine;
051: import com.sun.xml.ws.api.pipe.Fiber;
052: import com.sun.xml.ws.api.pipe.FiberContextSwitchInterceptor;
053: import com.sun.xml.ws.api.pipe.ServerPipeAssemblerContext;
054: import com.sun.xml.ws.api.pipe.ServerTubeAssemblerContext;
055: import com.sun.xml.ws.api.pipe.Tube;
056: import com.sun.xml.ws.api.pipe.TubeCloner;
057: import com.sun.xml.ws.api.pipe.TubelineAssembler;
058: import com.sun.xml.ws.api.pipe.TubelineAssemblerFactory;
059: import com.sun.xml.ws.api.server.Container;
060: import com.sun.xml.ws.api.server.EndpointAwareCodec;
061: import com.sun.xml.ws.api.server.EndpointComponent;
062: import com.sun.xml.ws.api.server.TransportBackChannel;
063: import com.sun.xml.ws.api.server.WSEndpoint;
064: import com.sun.xml.ws.api.server.WebServiceContextDelegate;
065: import com.sun.xml.ws.fault.SOAPFaultBuilder;
066: import com.sun.xml.ws.model.wsdl.WSDLProperties;
067: import com.sun.xml.ws.resources.HandlerMessages;
068: import com.sun.xml.ws.util.Pool;
069: import com.sun.xml.ws.util.Pool.TubePool;
070: import org.w3c.dom.Element;
071:
072: import javax.annotation.PreDestroy;
073: import javax.xml.namespace.QName;
074: import javax.xml.ws.EndpointReference;
075: import javax.xml.ws.handler.Handler;
076: import java.lang.reflect.Method;
077: import java.util.Arrays;
078: import java.util.LinkedHashSet;
079: import java.util.List;
080: import java.util.Set;
081: import java.util.concurrent.Executor;
082: import java.util.logging.Level;
083: import java.util.logging.Logger;
084:
085: /**
086: * {@link WSEndpoint} implementation.
087: *
088: * @author Kohsuke Kawaguchi
089: * @author Jitendra Kotamraju
090: */
091: public final class WSEndpointImpl<T> extends WSEndpoint<T> {
092: // Register JAX-WS JMX MBeans
093: static {
094: try {
095: JMXAgent.getDefault();
096: } catch (Throwable t) {
097: // Ignore for now by logging the stack trace
098: t.printStackTrace();
099: }
100: }
101:
102: private final @NotNull
103: QName serviceName;
104: private final @NotNull
105: QName portName;
106: private final WSBinding binding;
107: private final SEIModel seiModel;
108: private final @NotNull
109: Container container;
110: private final WSDLPort port;
111:
112: private final Tube masterTubeline;
113: private final ServiceDefinitionImpl serviceDef;
114: private final SOAPVersion soapVersion;
115: private final Engine engine;
116: private final @NotNull
117: Codec masterCodec;
118:
119: private final Pool<Tube> tubePool;
120:
121: /**
122: * Set to true once we start shutting down this endpoint.
123: * Used to avoid running the clean up processing twice.
124: *
125: * @see #dispose()
126: */
127: private boolean disposed;
128:
129: private final Class<T> implementationClass;
130: private final @Nullable
131: WSDLProperties wsdlProperties;
132: private final Set<EndpointComponent> componentRegistry = new LinkedHashSet<EndpointComponent>();
133:
134: WSEndpointImpl(@NotNull
135: QName serviceName, @NotNull
136: QName portName, WSBinding binding, Container container,
137: SEIModel seiModel, WSDLPort port,
138: Class<T> implementationClass, @Nullable
139: ServiceDefinitionImpl serviceDef, InvokerTube terminalTube,
140: boolean isSynchronous) {
141: this .serviceName = serviceName;
142: this .portName = portName;
143: this .binding = binding;
144: this .soapVersion = binding.getSOAPVersion();
145: this .container = container;
146: this .port = port;
147: this .implementationClass = implementationClass;
148: this .serviceDef = serviceDef;
149: this .seiModel = seiModel;
150: if (serviceDef != null) {
151: serviceDef.setOwner(this );
152: }
153:
154: TubelineAssembler assembler = TubelineAssemblerFactory.create(
155: Thread.currentThread().getContextClassLoader(), binding
156: .getBindingId(), container);
157: assert assembler != null;
158:
159: ServerTubeAssemblerContext context = new ServerPipeAssemblerContext(
160: seiModel, port, this , terminalTube, isSynchronous);
161: this .masterTubeline = assembler.createServer(context);
162:
163: Codec c = context.getCodec();
164: if (c instanceof EndpointAwareCodec) {
165: // create a copy to avoid sharing the codec between multiple endpoints
166: c = c.copy();
167: ((EndpointAwareCodec) c).setEndpoint(this );
168: }
169: this .masterCodec = c;
170:
171: tubePool = new TubePool(masterTubeline);
172: terminalTube.setEndpoint(this );
173: engine = new Engine(toString());
174: wsdlProperties = (port == null) ? null : new WSDLProperties(
175: port);
176: }
177:
178: public @NotNull
179: Class<T> getImplementationClass() {
180: return implementationClass;
181: }
182:
183: public @NotNull
184: WSBinding getBinding() {
185: return binding;
186: }
187:
188: public @NotNull
189: Container getContainer() {
190: return container;
191: }
192:
193: public WSDLPort getPort() {
194: return port;
195: }
196:
197: @Override
198: public @Nullable
199: SEIModel getSEIModel() {
200: return seiModel;
201: }
202:
203: public void setExecutor(Executor exec) {
204: engine.setExecutor(exec);
205: }
206:
207: public void schedule(final Packet request,
208: final CompletionCallback callback,
209: FiberContextSwitchInterceptor interceptor) {
210: request.endpoint = WSEndpointImpl.this ;
211: if (wsdlProperties != null) {
212: request.addSatellite(wsdlProperties);
213: }
214: Fiber fiber = engine.createFiber();
215: if (interceptor != null) {
216: fiber.addInterceptor(interceptor);
217: }
218: final Tube tube = tubePool.take();
219: fiber.start(tube, request, new Fiber.CompletionCallback() {
220: public void onCompletion(@NotNull
221: Packet response) {
222: tubePool.recycle(tube);
223: if (callback != null) {
224: callback.onCompletion(response);
225: }
226: }
227:
228: public void onCompletion(@NotNull
229: Throwable error) {
230: // let's not reuse tubes as they might be in a wrong state, so not
231: // calling tubePool.recycle()
232: error.printStackTrace();
233: // Convert all runtime exceptions to Packet so that transport doesn't
234: // have to worry about converting to wire message
235: // TODO XML/HTTP binding
236: Message faultMsg = SOAPFaultBuilder
237: .createSOAPFaultMessage(soapVersion, null,
238: error);
239: Packet response = request.createServerResponse(
240: faultMsg, request.endpoint.getPort(), null,
241: request.endpoint.getBinding());
242: if (callback != null) {
243: callback.onCompletion(response);
244: }
245: }
246: });
247: }
248:
249: public @NotNull
250: PipeHead createPipeHead() {
251: return new PipeHead() {
252: private final Tube tube = TubeCloner.clone(masterTubeline);
253:
254: public @NotNull
255: Packet process(Packet request,
256: WebServiceContextDelegate wscd,
257: TransportBackChannel tbc) {
258: request.webServiceContextDelegate = wscd;
259: request.transportBackChannel = tbc;
260: request.endpoint = WSEndpointImpl.this ;
261: if (wsdlProperties != null) {
262: request.addSatellite(wsdlProperties);
263: }
264: Fiber fiber = engine.createFiber();
265: Packet response;
266: try {
267: response = fiber.runSync(tube, request);
268: } catch (RuntimeException re) {
269: // Catch all runtime exceptions so that transport doesn't
270: // have to worry about converting to wire message
271: // TODO XML/HTTP binding
272: re.printStackTrace();
273: Message faultMsg = SOAPFaultBuilder
274: .createSOAPFaultMessage(soapVersion, null,
275: re);
276: response = request.createServerResponse(faultMsg,
277: request.endpoint.getPort(), null,
278: request.endpoint.getBinding());
279: }
280: return response;
281: }
282: };
283: }
284:
285: public synchronized void dispose() {
286: if (disposed)
287: return;
288: disposed = true;
289:
290: masterTubeline.preDestroy();
291:
292: for (Handler handler : binding.getHandlerChain()) {
293: for (Method method : handler.getClass().getMethods()) {
294: if (method.getAnnotation(PreDestroy.class) == null) {
295: continue;
296: }
297: try {
298: method.invoke(handler);
299: } catch (Exception e) {
300: logger.log(Level.WARNING, HandlerMessages
301: .HANDLER_PREDESTROY_IGNORE(e.getMessage()),
302: e);
303: }
304: break;
305: }
306: }
307: }
308:
309: public ServiceDefinitionImpl getServiceDefinition() {
310: return serviceDef;
311: }
312:
313: public Set<EndpointComponent> getComponentRegistry() {
314: return componentRegistry;
315: }
316:
317: private static final Logger logger = Logger
318: .getLogger(com.sun.xml.ws.util.Constants.LoggingDomain
319: + ".server.endpoint");
320:
321: public <T extends EndpointReference> T getEndpointReference(
322: Class<T> clazz, String address, String wsdlAddress,
323: Element... referenceParameters) {
324: QName portType = null;
325: if (port != null) {
326: portType = port.getBinding().getPortTypeName();
327: }
328: List<Element> refParams = null;
329: if (referenceParameters != null) {
330: refParams = Arrays.asList(referenceParameters);
331: }
332: AddressingVersion av = AddressingVersion.fromSpecClass(clazz);
333: if (av == AddressingVersion.W3C) {
334: // Supress writing ServiceName and EndpointName in W3C EPR,
335: // Until the ns for those metadata elements is resolved.
336: return new WSEndpointReference(AddressingVersion.W3C,
337: address, null /*serviceName*/, null /*portName*/,
338: null /*portType*/, null, null /*wsdlAddress*/,
339: refParams).toSpec(clazz);
340: } else {
341: return new WSEndpointReference(AddressingVersion.MEMBER,
342: address, serviceName, portName, portType, null,
343: wsdlAddress, refParams).toSpec(clazz);
344: }
345: }
346:
347: public @NotNull
348: QName getPortName() {
349: return portName;
350: }
351:
352: public @NotNull
353: Codec createCodec() {
354: return masterCodec.copy();
355: }
356:
357: public @NotNull
358: QName getServiceName() {
359: return serviceName;
360: }
361: }
|