0001: /*
0002: * Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025: package com.sun.xml.internal.ws.protocol.xml.client;
0026:
0027: import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException;
0028: import com.sun.xml.internal.ws.binding.BindingImpl;
0029: import com.sun.xml.internal.ws.client.*;
0030: import static com.sun.xml.internal.ws.client.BindingProviderProperties.*;
0031: import com.sun.xml.internal.ws.client.dispatch.DispatchContext;
0032: import com.sun.xml.internal.ws.client.dispatch.ResponseImpl;
0033: import com.sun.xml.internal.ws.encoding.soap.SOAPEncoder;
0034: import com.sun.xml.internal.ws.encoding.soap.client.SOAP12XMLEncoder;
0035: import com.sun.xml.internal.ws.encoding.soap.client.SOAPXMLEncoder;
0036: import com.sun.xml.internal.ws.encoding.soap.internal.MessageInfoBase;
0037: import com.sun.xml.internal.ws.encoding.xml.XMLEncoder;
0038: import com.sun.xml.internal.ws.encoding.xml.XMLMessage;
0039: import com.sun.xml.internal.ws.handler.HandlerChainCaller;
0040: import com.sun.xml.internal.ws.handler.HandlerChainCaller.Direction;
0041: import com.sun.xml.internal.ws.handler.HandlerChainCaller.RequestOrResponse;
0042: import com.sun.xml.internal.ws.handler.MessageContextUtil;
0043: import com.sun.xml.internal.ws.handler.XMLHandlerContext;
0044: import com.sun.xml.internal.ws.handler.HandlerContext;
0045: import com.sun.xml.internal.ws.model.JavaMethod;
0046: import com.sun.xml.internal.ws.pept.ept.EPTFactory;
0047: import com.sun.xml.internal.ws.pept.ept.MessageInfo;
0048: import com.sun.xml.internal.ws.pept.presentation.MessageStruct;
0049: import com.sun.xml.internal.ws.pept.protocol.MessageDispatcher;
0050: import com.sun.xml.internal.ws.server.RuntimeContext;
0051: import com.sun.xml.internal.ws.spi.runtime.ClientTransportFactory;
0052: import com.sun.xml.internal.ws.spi.runtime.WSConnection;
0053: import com.sun.xml.internal.ws.transport.http.client.HttpClientTransportFactory;
0054: import com.sun.xml.internal.ws.util.Base64Util;
0055: import com.sun.xml.internal.ws.util.XMLConnectionUtil;
0056: import com.sun.xml.internal.ws.util.xml.XmlUtil;
0057:
0058: import javax.activation.DataSource;
0059: import javax.activation.DataHandler;
0060: import javax.xml.bind.JAXBContext;
0061: import javax.xml.soap.MimeHeader;
0062: import javax.xml.soap.MimeHeaders;
0063: import javax.xml.transform.Source;
0064: import javax.xml.transform.Transformer;
0065: import javax.xml.transform.TransformerException;
0066: import javax.xml.transform.stream.StreamResult;
0067: import javax.xml.transform.stream.StreamSource;
0068: import javax.xml.ws.*;
0069: import static javax.xml.ws.BindingProvider.PASSWORD_PROPERTY;
0070: import static javax.xml.ws.BindingProvider.USERNAME_PROPERTY;
0071: import javax.xml.ws.handler.MessageContext;
0072: import javax.xml.ws.http.HTTPBinding;
0073: import javax.xml.ws.http.HTTPException;
0074: import javax.xml.ws.soap.SOAPBinding;
0075: import java.io.*;
0076: import java.net.HttpURLConnection;
0077: import java.net.URI;
0078: import java.net.URISyntaxException;
0079: import java.util.*;
0080: import java.util.concurrent.*;
0081:
0082: /**
0083: * Client-side XML-based message dispatcher {@link com.sun.xml.internal.ws.pept.protocol.MessageDispatcher}
0084: *
0085: * @author WS Development Team
0086: */
0087: public class XMLMessageDispatcher implements MessageDispatcher {
0088:
0089: protected static final int MAX_THREAD_POOL_SIZE = 3;
0090: protected static final long AWAIT_TERMINATION_TIME = 10L;
0091:
0092: protected ExecutorService executorService = null;
0093:
0094: /**
0095: * Default constructor
0096: */
0097:
0098: public XMLMessageDispatcher() {
0099: }
0100:
0101: /*
0102: * Invokes doSendAsync method if the message exchange pattern is asynchronous, otherwise
0103: * invokes doSend method.
0104: *
0105: * @see com.sun.pept.protocol.MessageDispatcher#send(com.sun.pept.ept.MessageInfo)
0106: */
0107: public void send(MessageInfo messageInfo) {
0108: if (isAsync(messageInfo)) {
0109: doSendAsync(messageInfo);
0110: } else {
0111: doSend(messageInfo);
0112: }
0113: }
0114:
0115: /**
0116: * Orchestrates the sending of a synchronous request
0117: */
0118: protected XMLMessage doSend(MessageInfo messageInfo) {
0119: //change from LogicalEPTFactory to ContactInfoBase - should be changed back when we have things working
0120: EPTFactory contactInfo = messageInfo.getEPTFactory();
0121: XMLEncoder encoder = (XMLEncoder) contactInfo
0122: .getEncoder(messageInfo);
0123:
0124: boolean handlerResult = true;
0125: boolean isRequestResponse = (messageInfo.getMEP() == MessageStruct.REQUEST_RESPONSE_MEP);
0126:
0127: DispatchContext dispatchContext = (DispatchContext) messageInfo
0128: .getMetaData(BindingProviderProperties.DISPATCH_CONTEXT);
0129:
0130: if (!isHTTPMessageType(dispatchContext)) {
0131: throw new WebServiceException(
0132: "Mode not allowed with HTTP Binding. Must use other Service.mode");
0133: }
0134:
0135: XMLMessage xm = makeXMLMessage(messageInfo);
0136:
0137: try {
0138: HandlerChainCaller caller = getHandlerChainCaller(messageInfo);
0139: if (caller.hasHandlers()) {
0140: XMLHandlerContext handlerContext = new XMLHandlerContext(
0141: messageInfo, null, xm);
0142: updateMessageContext(messageInfo, handlerContext);
0143: handlerResult = callHandlersOnRequest(handlerContext);
0144: updateXMLMessage(handlerContext);
0145: xm = handlerContext.getXMLMessage();
0146: if (xm == null) {
0147: xm = encoder.toXMLMessage(handlerContext
0148: .getInternalMessage(), messageInfo);
0149: }
0150:
0151: // the only case where no message is sent
0152: if (isRequestResponse && !handlerResult) {
0153: return xm;
0154: }
0155: }
0156:
0157: // Setting encoder here is necessary for calls to getBindingId()
0158: // messageInfo.setEncoder(encoder);
0159: Map<String, Object> context = processMetadata(messageInfo,
0160: xm);
0161:
0162: // set the MIME headers on connection headers
0163: Map<String, List<String>> ch = new HashMap<String, List<String>>();
0164: for (Iterator iter = xm.getMimeHeaders().getAllHeaders(); iter
0165: .hasNext();) {
0166: List<String> h = new ArrayList<String>();
0167: MimeHeader mh = (MimeHeader) iter.next();
0168:
0169: h.clear();
0170: h.add(mh.getValue());
0171: ch.put(mh.getName(), h);
0172: }
0173:
0174: setConnection(messageInfo, context);
0175: ((WSConnection) messageInfo.getConnection()).setHeaders(ch);
0176:
0177: if (!isAsync(messageInfo)) {
0178: WSConnection connection = (WSConnection) messageInfo
0179: .getConnection();
0180: //logRequestMessage(xm, messageInfo);
0181: XMLConnectionUtil.sendResponse(connection, xm);
0182: }
0183:
0184: // if handlerResult is false, the receive has already happened
0185: if (isRequestResponse && handlerResult) {
0186: receive(messageInfo);
0187: postReceiveHook(messageInfo);
0188: }
0189: } catch (Throwable e) {
0190: setResponseType(e, messageInfo);
0191: messageInfo.setResponse(e);
0192: }
0193: return xm;
0194: }
0195:
0196: /**
0197: * Process and classify the metadata in MIME headers or message context. <String,String> data
0198: * is copied into MIME headers and the remaining metadata is passed in message context to the
0199: * transport layer.
0200: *
0201: * @param messageInfo
0202: * @param xm
0203: */
0204: protected Map<String, Object> processMetadata(
0205: MessageInfo messageInfo, XMLMessage xm) {
0206: Map<String, Object> messageContext = new HashMap<String, Object>();
0207: List<String> header = new ArrayList<String>();
0208:
0209: ContextMap properties = (ContextMap) messageInfo
0210: .getMetaData(JAXWS_CONTEXT_PROPERTY);
0211: DispatchContext dcontext = (DispatchContext) messageInfo
0212: .getMetaData(BindingProviderProperties.DISPATCH_CONTEXT);
0213: if (isHTTPMessageType(dcontext)) {
0214: setHTTPContext(messageContext, dcontext, properties);
0215: }
0216:
0217: if (messageInfo.getMEP() == MessageStruct.ONE_WAY_MEP)
0218: messageContext.put(ONE_WAY_OPERATION, "true");
0219:
0220: // process the properties
0221: if (properties != null) {
0222: for (Iterator names = properties.getPropertyNames(); names
0223: .hasNext();) {
0224: String propName = (String) names.next();
0225:
0226: // consume PEPT-specific properties
0227: if (propName.equals(ClientTransportFactory.class
0228: .getName())) {
0229: messageContext.put(CLIENT_TRANSPORT_FACTORY,
0230: (ClientTransportFactory) properties
0231: .get(propName));
0232: } else if (propName.equals(USERNAME_PROPERTY)) {
0233: String credentials = (String) properties
0234: .get(USERNAME_PROPERTY);
0235: if (credentials != null) {
0236: credentials += ":";
0237: String password = (String) properties
0238: .get(PASSWORD_PROPERTY);
0239: if (password != null)
0240: credentials += password;
0241:
0242: try {
0243: credentials = Base64Util.encode(credentials
0244: .getBytes());
0245: } catch (Exception ex) {
0246: throw new WebServiceException(ex);
0247: }
0248: xm.getMimeHeaders().addHeader("Authorization",
0249: "Basic " + credentials);
0250: }
0251: } else if (propName
0252: .equals(BindingProvider.SESSION_MAINTAIN_PROPERTY)) {
0253: Object maintainSession = properties
0254: .get(BindingProvider.SESSION_MAINTAIN_PROPERTY);
0255: if (maintainSession != null
0256: && maintainSession.equals(Boolean.TRUE)) {
0257: Object cookieJar = properties
0258: .get(HTTP_COOKIE_JAR);
0259: if (cookieJar != null)
0260: messageContext.put(HTTP_COOKIE_JAR,
0261: cookieJar);
0262: }
0263: } else {
0264: messageContext.put(propName, properties
0265: .get(propName));
0266: }
0267: }
0268: }
0269:
0270: // Set accept header depending on content negotiation property
0271: String contentNegotiation = (String) messageInfo
0272: .getMetaData(CONTENT_NEGOTIATION_PROPERTY);
0273:
0274: String bindingId = getBindingId(messageInfo);
0275:
0276: if (bindingId.equals(SOAPBinding.SOAP12HTTP_BINDING)) {
0277: xm
0278: .getMimeHeaders()
0279: .addHeader(
0280: ACCEPT_PROPERTY,
0281: contentNegotiation != "none" ? SOAP12_XML_FI_ACCEPT_VALUE
0282: : SOAP12_XML_ACCEPT_VALUE);
0283: } else {
0284: xm.getMimeHeaders().addHeader(
0285: ACCEPT_PROPERTY,
0286: contentNegotiation != "none" ? XML_FI_ACCEPT_VALUE
0287: : XML_ACCEPT_VALUE);
0288: }
0289:
0290: //setRequestHeaders
0291: Map<String, List<String>> requestHeaders = (Map) properties
0292: .get(MessageContext.HTTP_REQUEST_HEADERS);
0293: //requestHeaders.
0294: setMimeHeaders(requestHeaders, xm);
0295:
0296: messageContext.put(BINDING_ID_PROPERTY, bindingId);
0297:
0298: // SOAPAction: MIME header
0299: RuntimeContext runtimeContext = (RuntimeContext) messageInfo
0300: .getMetaData(JAXWS_RUNTIME_CONTEXT);
0301: if (runtimeContext != null) {
0302: JavaMethod javaMethod = runtimeContext.getModel()
0303: .getJavaMethod(messageInfo.getMethod());
0304: if (javaMethod != null) {
0305: String soapAction = ((com.sun.xml.internal.ws.model.soap.SOAPBinding) javaMethod
0306: .getBinding()).getSOAPAction();
0307: header.clear();
0308: if (soapAction == null) {
0309: xm.getMimeHeaders().addHeader("SOAPAction", "\"\"");
0310: } else {
0311: xm.getMimeHeaders().addHeader("SOAPAction",
0312: soapAction);
0313: }
0314: }
0315: }
0316:
0317: return messageContext;
0318: }
0319:
0320: protected void setConnection(MessageInfo messageInfo,
0321: Map<String, Object> context) {
0322: ClientTransportFactory clientTransportFactory = (ClientTransportFactory) context
0323: .get(CLIENT_TRANSPORT_FACTORY);
0324: WSConnection connection = null;
0325: if (clientTransportFactory == null) {
0326: clientTransportFactory = new HttpClientTransportFactory();
0327: }
0328: connection = clientTransportFactory.create(context);
0329: messageInfo.setConnection(connection);
0330: }
0331:
0332: protected void setResponseType(Throwable e, MessageInfo messageInfo) {
0333: //e.printStackTrace();
0334: if (e instanceof RuntimeException) {
0335: messageInfo
0336: .setResponseType(MessageStruct.UNCHECKED_EXCEPTION_RESPONSE);
0337: if (e instanceof ClientTransportException) {
0338: Throwable temp = e;
0339: e = new WebServiceException(temp.getMessage(), temp);
0340: }
0341: } else {
0342: messageInfo
0343: .setResponseType(MessageStruct.CHECKED_EXCEPTION_RESPONSE);
0344: }
0345: messageInfo.setResponse(e);
0346: }
0347:
0348: /*
0349: * Orchestrates the receiving of a synchronous response
0350: *
0351: * @see com.sun.pept.protocol.MessageDispatcher#receive(com.sun.pept.ept.MessageInfo)
0352: *
0353: * todo: exception handling with possible saaj error below
0354: */
0355: public void receive(MessageInfo messageInfo) {
0356: // change from LogicalEPTFactory to ContactInfoBase - should be changed back when we have things working
0357: EPTFactory contactInfo = messageInfo.getEPTFactory();
0358:
0359: XMLMessage xm = getXMLMessage(messageInfo);
0360:
0361: // Content negotiation logic
0362: String contentNegotiation = (String) messageInfo
0363: .getMetaData(CONTENT_NEGOTIATION_PROPERTY);
0364: // If XML request
0365: if (contentNegotiation == "pessimistic") {
0366: try {
0367: if (xm.isFastInfoset()) {
0368: Map requestContext = (Map) messageInfo
0369: .getMetaData(JAXWS_CONTEXT_PROPERTY);
0370: // Further requests will be send using FI
0371: requestContext.put(CONTENT_NEGOTIATION_PROPERTY,
0372: "optimistic");
0373: }
0374: } catch (ClassCastException e) {
0375: // Content negotiation fails
0376: }
0377: }
0378:
0379: try {
0380: //logResponseMessage(xm, messageInfo);
0381: } catch (Exception ex) {
0382: throw new WebServiceException(ex);
0383: }
0384:
0385: XMLHandlerContext handlerContext = getInboundHandlerContext(
0386: messageInfo, xm);
0387:
0388: HandlerChainCaller caller = getHandlerChainCaller(messageInfo);
0389: if (caller.hasHandlers()) {
0390: callHandlersOnResponse(handlerContext);
0391: xm = handlerContext.getXMLMessage();
0392: }
0393:
0394: //set messageInfo response with appropriate result
0395: //at same time sets ResponseContext
0396: setResponse(messageInfo, xm, handlerContext);
0397: }
0398:
0399: private void setResponse(MessageInfo messageInfo, XMLMessage xm,
0400: HandlerContext handlerContext) {
0401:
0402: Map<String, DataHandler> attachments = getAttachments(
0403: handlerContext, xm);
0404:
0405: updateResponseContext(messageInfo,
0406: (XMLHandlerContext) handlerContext, attachments);
0407:
0408: DispatchContext dispatchContext = (DispatchContext) messageInfo
0409: .getMetaData(BindingProviderProperties.DISPATCH_CONTEXT);
0410: DispatchContext.MessageType msgtype = (DispatchContext.MessageType) dispatchContext
0411: .getProperty(DispatchContext.DISPATCH_MESSAGE);
0412: if (msgtype != null) {
0413: switch ((DispatchContext.MessageType) msgtype) {
0414: case HTTP_SOURCE_MESSAGE:
0415: messageInfo.setResponse(xm.getSource());
0416: break;
0417: case HTTP_SOURCE_PAYLOAD:
0418: messageInfo.setResponse(xm.getSource());
0419: break;
0420: case HTTP_JAXB_PAYLOAD:
0421: messageInfo.setResponse(xm
0422: .getPayload(getJAXBContext(messageInfo)));
0423: break;
0424: case HTTP_DATASOURCE_MESSAGE:
0425: if (xm.getDataSource() != null)
0426: messageInfo.setResponse(xm.getDataSource());
0427: break;
0428: default:
0429: throw new WebServiceException(
0430: "Unknown invocation return object ");
0431: }
0432: } else {
0433: //tbd just assume source for now
0434: throw new WebServiceException(
0435: "Unknown invocation return object");
0436: }
0437:
0438: }
0439:
0440: private Map<String, DataHandler> getAttachments(
0441: HandlerContext handlerContext, XMLMessage xm) {
0442: //are there attachments on the MessageContext properties ? Handlers
0443: Map<String, DataHandler> attmc = (Map<String, DataHandler>) handlerContext
0444: .getMessageContext().get(
0445: MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
0446: //can we get it from XMLMessage as well?
0447: Map<String, DataHandler> attxm = xm.getAttachments();
0448:
0449: Map<String, DataHandler> attachments = new HashMap<String, DataHandler>();
0450: if (attxm != null && attmc != null) {
0451: attachments.putAll(attxm);
0452: attachments.putAll(attmc);
0453: } else if (attxm != null) {
0454: attachments.putAll(attxm);
0455: } else if (attmc != null)
0456: attachments.putAll(attmc);
0457: else {
0458: attachments = null; //gc it
0459: return null;
0460: }
0461: return attachments;
0462: }
0463:
0464: private XMLHandlerContext getInboundHandlerContext(
0465: MessageInfo messageInfo, XMLMessage xm) {
0466: XMLHandlerContext handlerContext = (XMLHandlerContext) messageInfo
0467: .getMetaData(BindingProviderProperties.JAXWS_HANDLER_CONTEXT_PROPERTY);
0468: if (handlerContext != null) {
0469: handlerContext.setXMLMessage(xm);
0470: handlerContext.setInternalMessage(null);
0471: } else {
0472: handlerContext = new XMLHandlerContext(messageInfo, null,
0473: xm);
0474: }
0475: return handlerContext;
0476: }
0477:
0478: /**
0479: * Orchestrates the sending of an asynchronous request
0480: */
0481: protected void doSendAsync(final MessageInfo messageInfo) {
0482: try { // should have already been caught
0483: preSendHook(messageInfo);
0484: XMLMessage xm = doSend(messageInfo);
0485: postSendHook(messageInfo);
0486:
0487: //pass a copy of MessageInfo to the future task,so that no conflicts
0488: //due to threading happens
0489: Response r = sendAsyncReceive(MessageInfoBase
0490: .copy(messageInfo), xm);
0491: if (executorService == null) {
0492: executorService = Executors
0493: .newFixedThreadPool(MAX_THREAD_POOL_SIZE,
0494: new DaemonThreadFactory());
0495: }
0496:
0497: AsyncHandlerService service = (AsyncHandlerService) messageInfo
0498: .getMetaData(BindingProviderProperties.JAXWS_CLIENT_ASYNC_HANDLER);
0499: WSFuture wsfuture = null;
0500: if (service != null) {
0501: wsfuture = service.setupAsyncCallback(r);
0502: ((ResponseImpl) r).setUID(service.getUID());
0503: ((ResponseImpl) r).setHandlerService(service);
0504: }
0505: executorService.execute((FutureTask) r);
0506: if (service == null)
0507: messageInfo.setResponse(r);
0508: else
0509: messageInfo.setResponse(wsfuture);
0510:
0511: } catch (Throwable e) {
0512: messageInfo.setResponse(e);
0513: }
0514: }
0515:
0516: /**
0517: * Orchestrates the receiving of an asynchronous response
0518: */
0519: protected Response<Object> sendAsyncReceive(
0520: final MessageInfo messageInfo, final XMLMessage xm) {
0521:
0522: final AsyncHandlerService handler = (AsyncHandlerService) messageInfo
0523: .getMetaData(BindingProviderProperties.JAXWS_CLIENT_ASYNC_HANDLER);
0524: final boolean callback = (messageInfo.getMEP() == MessageStruct.ASYNC_CALLBACK_MEP) ? true
0525: : false;
0526: if (callback && (handler == null))
0527: throw new WebServiceException(
0528: "Asynchronous callback invocation, but no handler - AsyncHandler required");
0529:
0530: final Response r = new ResponseImpl<Object>(
0531: new Callable<Object>() {
0532:
0533: public Object call() throws Exception {
0534: // get connection and do http.invoke()
0535: try {
0536: final WSConnection connection = (WSConnection) messageInfo
0537: .getConnection();
0538: //logRequestMessage(xm, messageInfo);
0539: XMLConnectionUtil.sendResponse(connection,
0540: xm);
0541: } catch (Throwable t) {
0542: messageInfo.setResponse(t);
0543: messageInfo
0544: .setResponseType(MessageStruct.UNCHECKED_EXCEPTION_RESPONSE);
0545: }
0546: // receive response
0547: preReceiveHook(messageInfo);
0548: try {
0549: receive(messageInfo);
0550: } catch (Exception ex) {
0551: messageInfo.setResponse(ex);
0552: }
0553: postReceiveHook(messageInfo);
0554:
0555: if (messageInfo.getResponse() instanceof Exception)
0556: throw (Exception) messageInfo.getResponse();
0557: return messageInfo.getResponse();
0558: }
0559: });
0560: messageInfo.setMetaData(JAXWS_CLIENT_ASYNC_RESPONSE_CONTEXT, r);
0561: return r;
0562: }
0563:
0564: protected boolean callHandlersOnRequest(
0565: XMLHandlerContext handlerContext) {
0566:
0567: HandlerChainCaller caller = getHandlerChainCaller(handlerContext
0568: .getMessageInfo());
0569: boolean responseExpected = (handlerContext.getMessageInfo()
0570: .getMEP() != MessageStruct.ONE_WAY_MEP);
0571: try {
0572: return caller.callHandlers(Direction.OUTBOUND,
0573: RequestOrResponse.REQUEST, handlerContext,
0574: responseExpected);
0575: } catch (ProtocolException pe) {
0576: if (MessageContextUtil.ignoreFaultInMessage(handlerContext
0577: .getMessageContext())) {
0578: // Ignore fault in this case and use exception.
0579: throw pe;
0580: } else
0581: return false;
0582: } catch (WebServiceException wse) {
0583: throw wse;
0584: } catch (RuntimeException re) {
0585: // handlers are expected to be able to throw RE
0586: throw new WebServiceException(re);
0587: }
0588: }
0589:
0590: /*
0591: * User's handler can throw a RuntimeExceptions
0592: * (e.g., a ProtocolException).
0593: * Need to wrap any RuntimeException (other than WebServiceException) in
0594: * WebServiceException.
0595: */
0596: protected boolean callHandlersOnResponse(
0597: XMLHandlerContext handlerContext) {
0598: HandlerChainCaller caller = getHandlerChainCaller(handlerContext
0599: .getMessageInfo());
0600: try {
0601: return caller.callHandlers(Direction.INBOUND,
0602: RequestOrResponse.RESPONSE, handlerContext, false);
0603: } catch (WebServiceException wse) {
0604: throw wse;
0605: } catch (RuntimeException re) {
0606: // handlers are expected to be able to throw RE
0607: throw new WebServiceException(re);
0608: }
0609: }
0610:
0611: protected Binding getBinding(MessageInfo messageInfo) {
0612: ContextMap context = (ContextMap) ((MessageInfoBase) messageInfo)
0613: .getMetaData(BindingProviderProperties.JAXWS_CONTEXT_PROPERTY);
0614: BindingProvider provider = (BindingProvider) context
0615: .get(BindingProviderProperties.JAXWS_CLIENT_HANDLE_PROPERTY);
0616: return provider.getBinding();
0617: }
0618:
0619: protected HandlerChainCaller getHandlerChainCaller(
0620: MessageInfo messageInfo) {
0621: BindingImpl binding = (BindingImpl) getBinding(messageInfo);
0622: return binding.getHandlerChainCaller();
0623: }
0624:
0625: protected void updateMessageContext(MessageInfo messageInfo,
0626: XMLHandlerContext context) {
0627:
0628: MessageContext messageContext = context.getMessageContext();
0629: messageInfo
0630: .setMetaData(
0631: BindingProviderProperties.JAXWS_HANDLER_CONTEXT_PROPERTY,
0632: context);
0633: RequestContext ctxt = (RequestContext) messageInfo
0634: .getMetaData(BindingProviderProperties.JAXWS_CONTEXT_PROPERTY);
0635: Iterator i = ctxt.copy().getPropertyNames();
0636: while (i.hasNext()) {
0637: String name = (String) i.next();
0638: Object value = ctxt.get(name);
0639: messageContext.put(name, value);
0640: }
0641: }
0642:
0643: protected void updateResponseContext(MessageInfo messageInfo,
0644: XMLHandlerContext context,
0645: Map<String, DataHandler> attachments) {
0646:
0647: MessageContext messageContext = context.getMessageContext();
0648: BindingProvider provider = (BindingProvider) messageContext
0649: .get(JAXWS_CLIENT_HANDLE_PROPERTY);
0650: ResponseContext responseContext = new ResponseContext(provider);
0651: for (String name : messageContext.keySet()) {
0652: MessageContext.Scope scope = messageContext.getScope(name);
0653: if (MessageContext.Scope.APPLICATION == scope) {
0654: Object value = messageContext.get(name);
0655: responseContext.put(name, value);
0656: }
0657: }
0658:
0659: //let's update status code
0660: MessageContext mc = context.getMessageContext();
0661: WSConnection con = messageInfo.getConnection();
0662: Map<String, List<String>> headers = con.getHeaders();
0663:
0664: responseContext.put(MessageContext.HTTP_RESPONSE_HEADERS,
0665: headers);
0666: responseContext.put(MessageContext.HTTP_RESPONSE_CODE, con
0667: .getStatus());
0668:
0669: //attachments for ResponseContext
0670: if (attachments != null)
0671: responseContext.put(
0672: MessageContext.INBOUND_MESSAGE_ATTACHMENTS,
0673: attachments);
0674:
0675: ResponseImpl asyncResponse = (ResponseImpl) messageInfo
0676: .getMetaData(JAXWS_CLIENT_ASYNC_RESPONSE_CONTEXT);
0677: if (asyncResponse != null) {
0678: asyncResponse.setResponseContext(responseContext.copy());
0679: } else {
0680: messageInfo.setMetaData(JAXWS_RESPONSE_CONTEXT_PROPERTY,
0681: responseContext.copy());
0682: }
0683: }
0684:
0685: /**
0686: * @return true if message exchange pattern indicates asynchronous, otherwise returns false
0687: */
0688: protected boolean isAsync(MessageInfo messageInfo) {
0689: if ((messageInfo.getMEP() == MessageStruct.ASYNC_POLL_MEP)
0690: || (messageInfo.getMEP() == MessageStruct.ASYNC_CALLBACK_MEP)) {
0691: return true;
0692: }
0693: return false;
0694: }
0695:
0696: private void preSendHook(MessageInfo messageInfo) {
0697: }
0698:
0699: private void preReceiveHook(MessageInfo messageInfo) {
0700: }
0701:
0702: private void postSendHook(MessageInfo messageInfo) {
0703: if (messageInfo.getResponseType() != MessageStruct.NORMAL_RESPONSE) {
0704: postReceiveHook(messageInfo);
0705: throw (WebServiceException) messageInfo.getResponse();
0706: }
0707: }
0708:
0709: private void postReceiveAndDecodeHook(MessageInfo messageInfo) {
0710: }
0711:
0712: private void postReceiveHook(MessageInfo messageInfo) {
0713:
0714: if (messageInfo.getMEP() == MessageStruct.ONE_WAY_MEP)
0715: return;
0716: Object response = messageInfo.getResponse();
0717: if (response instanceof StreamSource) {
0718: InputStream is = ((StreamSource) response).getInputStream();
0719:
0720: Transformer transformer = XmlUtil.newTransformer();
0721: try {
0722: ByteArrayOutputStream out = new ByteArrayOutputStream(
0723: is.available());
0724: if (out.size() > 0) {
0725: transformer.transform((StreamSource) response,
0726: new StreamResult(out));
0727: byte[] bytes = out.toByteArray();
0728: //could do to string
0729: if (new String(bytes).indexOf("HTTPException") > -1)
0730: throw new HTTPException(
0731: HttpURLConnection.HTTP_INTERNAL_ERROR);
0732: else {
0733: InputStream bis = new ByteArrayInputStream(
0734: bytes);
0735: messageInfo.setResponse(new StreamSource(bis));
0736: }
0737: }
0738: } catch (TransformerException e) {
0739: throw new WebServiceException(e);
0740: } catch (IOException e) {
0741: throw new WebServiceException(e);
0742: }
0743: }
0744: switch (messageInfo.getResponseType()) {
0745: case MessageStruct.NORMAL_RESPONSE:
0746: // not sure where this belongs yet - but for now-
0747: return;
0748: case MessageStruct.CHECKED_EXCEPTION_RESPONSE:
0749: if (response instanceof Exception) {
0750: throw new HTTPException(
0751: HttpURLConnection.HTTP_INTERNAL_ERROR);
0752: }
0753: return;
0754: case MessageStruct.UNCHECKED_EXCEPTION_RESPONSE:
0755: if (response instanceof ProtocolException) {
0756: throw new HTTPException(
0757: HttpURLConnection.HTTP_INTERNAL_ERROR);
0758: } else {
0759: WebServiceException jex = null;
0760: if (response instanceof Exception) {
0761: throw new WebServiceException((Exception) response);
0762: }
0763: messageInfo.setResponse(response);
0764: }
0765: return;
0766: default:
0767: messageInfo.setResponse(response);
0768: }
0769: }
0770:
0771: private void closeAllHandlers(XMLHandlerContext context) {
0772: HandlerChainCaller caller = getHandlerChainCaller(context
0773: .getMessageInfo());
0774: if (caller != null && caller.hasHandlers()) {
0775: caller.forceCloseHandlersOnClient(context);
0776: }
0777: }
0778:
0779: /**
0780: * This method is used to create the appropriate SOAPMessage (1.1 or 1.2 using SAAJ api).
0781: *
0782: * @return the BindingId associated with messageInfo
0783: */
0784: protected String getBindingId(MessageInfo messageInfo) {
0785: SOAPEncoder encoder = (SOAPEncoder) messageInfo.getEncoder();
0786: if (encoder instanceof SOAPXMLEncoder)
0787: return SOAPBinding.SOAP11HTTP_BINDING;
0788: else if (encoder instanceof SOAP12XMLEncoder)
0789: return SOAPBinding.SOAP12HTTP_BINDING;
0790: else
0791: return HTTPBinding.HTTP_BINDING;
0792: }
0793:
0794: /**
0795: * Logs the SOAP request message
0796: */
0797: protected void logRequestMessage(XMLMessage request,
0798: MessageInfo messageInfo) throws IOException,
0799: MessagingException, TransformerException {
0800:
0801: OutputStream out = ((WSConnection) messageInfo.getConnection())
0802: .getDebug();
0803:
0804: if (out != null) {
0805: String s = "******************\nRequest\n";
0806: out.write(s.getBytes());
0807: for (Iterator iter = request.getMimeHeaders()
0808: .getAllHeaders(); iter.hasNext();) {
0809: MimeHeader header = (MimeHeader) iter.next();
0810: s = header.getName() + ": " + header.getValue() + "\n";
0811: out.write(s.getBytes());
0812: }
0813: out.flush();
0814: request.writeTo(out);
0815: s = "\n";
0816: out.write(s.getBytes());
0817: out.flush();
0818: }
0819: }
0820:
0821: /**
0822: * Logs the SOAP response message
0823: */
0824: protected void logResponseMessage(XMLMessage response,
0825: MessageInfo messageInfo) throws IOException,
0826: MessagingException, TransformerException {
0827:
0828: OutputStream out = ((WSConnection) messageInfo.getConnection())
0829: .getDebug();
0830:
0831: if (out != null) {
0832: String s = "Response\n";
0833: out.write(s.getBytes());
0834: s = "Http Status Code: "
0835: + ((WSConnection) messageInfo.getConnection())
0836: .getStatus() + "\n\n";
0837: out.write(s.getBytes());
0838: for (Iterator iter = response.getMimeHeaders()
0839: .getAllHeaders(); iter.hasNext();) {
0840: MimeHeader header = (MimeHeader) iter.next();
0841: s = header.getName() + ": " + header.getValue() + "\n";
0842: out.write(s.getBytes());
0843: }
0844: out.flush();
0845: response.writeTo(out);
0846: s = "******************\n\n";
0847: out.write(s.getBytes());
0848: }
0849: }
0850:
0851: /*
0852: * Gets XMLMessage from the connection
0853: */
0854: private XMLMessage getXMLMessage(MessageInfo messageInfo) {
0855: WSConnection con = (WSConnection) messageInfo.getConnection();
0856: return XMLConnectionUtil.getXMLMessage(con, messageInfo);
0857: }
0858:
0859: protected JAXBContext getJAXBContext(MessageInfo messageInfo) {
0860: JAXBContext jc = null;
0861: RequestContext context = (RequestContext) messageInfo
0862: .getMetaData(BindingProviderProperties.JAXWS_CONTEXT_PROPERTY);
0863: if (context != null)
0864: jc = (JAXBContext) context
0865: .get(BindingProviderProperties.JAXB_CONTEXT_PROPERTY);
0866:
0867: return jc;
0868: }
0869:
0870: public void setHTTPContext(Map<String, Object> messageContext,
0871: DispatchContext dispatchContext, Map requestContext) {
0872:
0873: if (requestContext.get(MessageContext.HTTP_REQUEST_METHOD) != null)
0874: messageContext.put(MessageContext.HTTP_REQUEST_METHOD,
0875: requestContext
0876: .get(MessageContext.HTTP_REQUEST_METHOD));
0877: if (requestContext.get(MessageContext.HTTP_REQUEST_HEADERS) != null)
0878: messageContext.put(MessageContext.HTTP_REQUEST_HEADERS,
0879: requestContext
0880: .get(MessageContext.HTTP_REQUEST_HEADERS));
0881:
0882: //resolve endpoint look for query parameters, pathInfo
0883: String origEndpoint = (String) requestContext
0884: .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
0885:
0886: String pathInfo = null;
0887: String queryString = null;
0888: if (requestContext.get(MessageContext.PATH_INFO) != null) {
0889: pathInfo = (String) requestContext
0890: .get(MessageContext.PATH_INFO);
0891: }
0892: if (requestContext.get(MessageContext.QUERY_STRING) != null) {
0893: queryString = (String) requestContext
0894: .get(MessageContext.QUERY_STRING);
0895: }
0896:
0897: String resolvedEndpoint = null;
0898: if (pathInfo != null || queryString != null) {
0899: pathInfo = checkPath(pathInfo);
0900: queryString = checkQuery(queryString);
0901: if (origEndpoint != null) {
0902: try {
0903: URI endpointURI = new URI(origEndpoint);
0904: resolvedEndpoint = resolveURI(endpointURI,
0905: pathInfo, queryString);
0906: } catch (URISyntaxException e) {
0907: resolvedEndpoint = origEndpoint;
0908: }
0909: }
0910:
0911: requestContext.put(
0912: BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
0913: resolvedEndpoint);
0914: messageContext.put(
0915: BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
0916: resolvedEndpoint);
0917: }
0918: }
0919:
0920: protected String resolveURI(URI endpointURI, String pathInfo,
0921: String queryString) {
0922: String query = null;
0923: String fragment = null;
0924: if (queryString != null) {
0925: URI result = endpointURI.resolve(queryString);
0926: query = result.getQuery();
0927: fragment = result.getFragment();
0928: }
0929: //String path = (pathInfo != null) ? endpointURI.getPath() + pathInfo : endpointURI.getPath();
0930: String path = (pathInfo != null) ? pathInfo : endpointURI
0931: .getPath();
0932: try {
0933: URI temp = new URI(null, null, path, query, fragment);
0934: return endpointURI.resolve(temp).toString();
0935: } catch (URISyntaxException e) {
0936: e.printStackTrace();
0937: }
0938: return endpointURI.toString();
0939: }
0940:
0941: private String checkPath(String path) {
0942: //does it begin with /
0943: return (path == null || path.startsWith("/")) ? path : "/"
0944: + path;
0945: }
0946:
0947: private String checkQuery(String query) {
0948: //does it begin with ?
0949: return (query == null || query.startsWith("?")) ? query : "?"
0950: + query;
0951: }
0952:
0953: protected boolean isHTTPMessageType(DispatchContext dispatchContext) {
0954:
0955: DispatchContext.MessageType type = (DispatchContext.MessageType) dispatchContext
0956: .getProperty(DispatchContext.DISPATCH_MESSAGE);
0957:
0958: if ((type == DispatchContext.MessageType.HTTP_DATASOURCE_MESSAGE)
0959: ||
0960: //(type == DispatchContext.MessageType.HTTP_DATASOURCE_PAYLOAD) ||
0961: (type == DispatchContext.MessageType.HTTP_SOURCE_MESSAGE)
0962: || (type == DispatchContext.MessageType.HTTP_SOURCE_PAYLOAD)
0963: ||
0964: //(type == DispatchContext.MessageType.HTTP_JAXB_MESSAGE) ||
0965: (type == DispatchContext.MessageType.HTTP_JAXB_PAYLOAD))
0966: return true;
0967:
0968: return false;
0969: }
0970:
0971: protected XMLMessage makeXMLMessage(MessageInfo messageInfo) {
0972:
0973: XMLMessage xm = null;
0974:
0975: Class clazz = (Class) messageInfo
0976: .getMetaData(DispatchContext.DISPATCH_MESSAGE_CLASS);
0977:
0978: Map<String, Object> context = (Map<String, Object>) messageInfo
0979: .getMetaData(BindingProviderProperties.JAXWS_CONTEXT_PROPERTY);
0980: Map<String, DataHandler> attachments = (context != null) ? (Map<String, DataHandler>) context
0981: .get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS)
0982: : null;
0983:
0984: // Determine if Fast Infoset is to be used
0985: boolean useFastInfoset = (messageInfo
0986: .getMetaData(CONTENT_NEGOTIATION_PROPERTY) == "optimistic");
0987:
0988: Object object = messageInfo.getData()[0];
0989:
0990: if (clazz != null && clazz.isAssignableFrom(Source.class)) {
0991: //xm = new XMLMessage((Source) object, useFastInfoset);
0992: xm = new XMLMessage((Source) object, attachments,
0993: useFastInfoset);
0994: } else if (clazz != null
0995: && clazz.isAssignableFrom(DataSource.class)) {
0996: xm = new XMLMessage((DataSource) object, useFastInfoset);
0997: } else {
0998: xm = new XMLMessage(object, getJAXBContext(messageInfo),
0999: attachments, useFastInfoset);
1000: //xm = new XMLMessage(object, getJAXBContext(messageInfo), useFastInfoset);
1001: }
1002:
1003: return xm;
1004: }
1005:
1006: private void setMimeHeaders(
1007: Map<String, List<String>> requestHeaders, XMLMessage xm) {
1008:
1009: if ((requestHeaders != null) && (!requestHeaders.isEmpty())) {
1010: Set<Map.Entry<String, List<String>>> headerSet = requestHeaders
1011: .entrySet();
1012: Iterator<Map.Entry<String, List<String>>> iter = headerSet
1013: .iterator();
1014: while (iter.hasNext()) {
1015: Map.Entry<String, List<String>> entry = iter.next();
1016: MimeHeaders headers = xm.getMimeHeaders();
1017: String[] values = entry.getValue().toArray(
1018: new String[entry.getValue().size()]);
1019: ;
1020: StringBuffer buf = new StringBuffer(250);
1021: if (values.length > 0)
1022: buf.append(values[0]);
1023: else
1024: break;
1025: for (int i = 1; i < values.length - 1; i++) {
1026: buf.append(values[i]);
1027: }
1028:
1029: headers.addHeader(entry.getKey(), buf.toString());
1030: }
1031: }
1032: }
1033:
1034: private XMLMessage updateXMLMessage(XMLHandlerContext context) {
1035: // Create a new XMLMessage from existing message and OUTBOUND attachments property
1036: MessageContext msgCtxt = context.getMessageContext();
1037: Map<String, DataHandler> atts = (Map<String, DataHandler>) msgCtxt
1038: .get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
1039: if (atts != null) {
1040: XMLMessage xmlMessage = context.getXMLMessage();
1041: if (xmlMessage != null) {
1042: Map<String, DataHandler> allAtts = xmlMessage
1043: .getAttachments();
1044: if (allAtts != null) {
1045: allAtts.putAll(atts);
1046: } else {
1047: allAtts = atts;
1048: }
1049: context.setXMLMessage(new XMLMessage(xmlMessage
1050: .getSource(), allAtts, xmlMessage
1051: .isFastInfoset()));
1052: } else {
1053: //can I make a message w/o src
1054: }
1055:
1056: }
1057: return context.getXMLMessage();
1058: }
1059:
1060: class DaemonThreadFactory implements ThreadFactory {
1061: public Thread newThread(Runnable r) {
1062: Thread daemonThread = new Thread(r);
1063: daemonThread.setDaemon(Boolean.TRUE);
1064: return daemonThread;
1065: }
1066: }
1067:
1068: }
|