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.client.sei;
038:
039: //import com.sun.tools.ws.wsdl.document.soap.SOAPBinding;
040:
041: import com.sun.istack.NotNull;
042: import com.sun.istack.Nullable;
043: import com.sun.xml.ws.api.message.Message;
044: import com.sun.xml.ws.api.message.Packet;
045: import com.sun.xml.ws.api.pipe.Fiber;
046: import com.sun.xml.ws.client.AsyncInvoker;
047: import com.sun.xml.ws.client.AsyncResponseImpl;
048: import com.sun.xml.ws.client.RequestContext;
049: import com.sun.xml.ws.client.ResponseContext;
050: import com.sun.xml.ws.fault.SOAPFaultBuilder;
051: import com.sun.xml.ws.model.JavaMethodImpl;
052: import com.sun.xml.ws.model.ParameterImpl;
053: import com.sun.xml.ws.model.WrapperParameter;
054:
055: import javax.jws.soap.SOAPBinding.Style;
056: import javax.xml.ws.AsyncHandler;
057: import javax.xml.ws.Response;
058: import javax.xml.ws.WebServiceException;
059: import java.util.List;
060:
061: /**
062: * Common part between {@link CallbackMethodHandler} and {@link PollingMethodHandler}.
063: *
064: * @author Kohsuke Kawaguchi
065: * @author Jitendra Kotamraju
066: */
067: abstract class AsyncMethodHandler extends SEIMethodHandler {
068:
069: private final ResponseBuilder responseBuilder;
070: /**
071: * Async bean class that has setters for all out parameters
072: */
073: private final @Nullable
074: Class asyncBeanClass;
075:
076: AsyncMethodHandler(SEIStub owner, JavaMethodImpl jm,
077: JavaMethodImpl sync) {
078: super (owner, sync);
079:
080: List<ParameterImpl> rp = sync.getResponseParameters();
081: int size = 0;
082: for (ParameterImpl param : rp) {
083: if (param.isWrapperStyle()) {
084: WrapperParameter wrapParam = (WrapperParameter) param;
085: size += wrapParam.getWrapperChildren().size();
086: if (sync.getBinding().getStyle() == Style.DOCUMENT) {
087: // doc/asyncBeanClass - asyncBeanClass bean is in async signature
088: // Add 2 or more so that it is considered as async bean case
089: size += 2;
090: }
091: } else {
092: ++size;
093: }
094: }
095:
096: Class tempWrap = null;
097: if (size > 1) {
098: rp = jm.getResponseParameters();
099: for (ParameterImpl param : rp) {
100: if (param.isWrapperStyle()) {
101: WrapperParameter wrapParam = (WrapperParameter) param;
102: if (sync.getBinding().getStyle() == Style.DOCUMENT) {
103: // doc/asyncBeanClass style
104: tempWrap = (Class) wrapParam.getTypeReference().type;
105: break;
106: }
107: for (ParameterImpl p : wrapParam
108: .getWrapperChildren()) {
109: if (p.getIndex() == -1) {
110: tempWrap = (Class) p.getTypeReference().type;
111: break;
112: }
113: }
114: if (tempWrap != null) {
115: break;
116: }
117: } else {
118: if (param.getIndex() == -1) {
119: tempWrap = (Class) param.getTypeReference().type;
120: break;
121: }
122: }
123: }
124: }
125: asyncBeanClass = tempWrap;
126:
127: switch (size) {
128: case 0:
129: responseBuilder = buildResponseBuilder(sync,
130: ValueSetterFactory.NONE);
131: break;
132: case 1:
133: responseBuilder = buildResponseBuilder(sync,
134: ValueSetterFactory.SINGLE);
135: break;
136: default:
137: responseBuilder = buildResponseBuilder(sync,
138: new ValueSetterFactory.AsyncBeanValueSetterFactory(
139: asyncBeanClass));
140: }
141:
142: }
143:
144: protected final Response<Object> doInvoke(Object proxy,
145: Object[] args, AsyncHandler handler) {
146:
147: AsyncInvoker invoker = new SEIAsyncInvoker(proxy, args);
148: AsyncResponseImpl<Object> ft = new AsyncResponseImpl<Object>(
149: invoker, handler);
150: invoker.setReceiver(ft);
151: // TODO: Do we set this executor on Engine and run the AsyncInvoker in this thread ?
152: owner.getExecutor().execute(ft);
153: return ft;
154: }
155:
156: private class SEIAsyncInvoker extends AsyncInvoker {
157: // snapshot the context now. this is necessary to avoid concurrency issue,
158: // and is required by the spec
159: private final RequestContext rc = owner.requestContext.copy();
160: private final Object[] args;
161:
162: SEIAsyncInvoker(Object proxy, Object[] args) {
163: this .args = args;
164: }
165:
166: public void do_run() {
167: Packet req = new Packet(createRequestMessage(args));
168: req.soapAction = soapAction;
169: req.expectReply = !isOneWay;
170: req.getMessage().assertOneWay(isOneWay);
171:
172: Fiber.CompletionCallback callback = new Fiber.CompletionCallback() {
173:
174: public void onCompletion(@NotNull
175: Packet response) {
176: responseImpl
177: .setResponseContext(new ResponseContext(
178: response));
179: Message msg = response.getMessage();
180: if (msg == null) {
181: return;
182: }
183: try {
184: if (msg.isFault()) {
185: SOAPFaultBuilder faultBuilder = SOAPFaultBuilder
186: .create(msg);
187: throw faultBuilder
188: .createException(checkedExceptions);
189: } else {
190: Object[] rargs = new Object[1];
191: if (asyncBeanClass != null) {
192: rargs[0] = asyncBeanClass.newInstance();
193: }
194: responseBuilder.readResponse(msg, rargs);
195: responseImpl.set(rargs[0], null);
196: }
197: } catch (Throwable t) {
198: if (t instanceof RuntimeException) {
199: if (t instanceof WebServiceException) {
200: responseImpl.set(null, t);
201: }
202: } else if (t instanceof Exception) {
203: responseImpl.set(null, t);
204: }
205: //its RuntimeException or some other exception resulting from user error, wrap it in
206: // WebServiceException
207: responseImpl.set(null, new WebServiceException(
208: t));
209: }
210: }
211:
212: public void onCompletion(@NotNull
213: Throwable error) {
214: if (error instanceof WebServiceException) {
215: responseImpl.set(null, error);
216:
217: } else {
218: //its RuntimeException or some other exception resulting from user error, wrap it in
219: // WebServiceException
220: responseImpl.set(null, new WebServiceException(
221: error));
222: }
223: }
224: };
225: owner.doProcessAsync(req, rc, callback);
226: }
227: }
228:
229: ValueGetterFactory getValueGetterFactory() {
230: return ValueGetterFactory.ASYNC;
231: }
232:
233: }
|