001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.transport.nhttp;
020:
021: import org.apache.axis2.context.ConfigurationContext;
022: import org.apache.axis2.context.MessageContext;
023: import org.apache.axis2.description.WSDL2Constants;
024: import org.apache.axis2.AxisFault;
025: import org.apache.axis2.Constants;
026: import org.apache.axis2.builder.BuilderUtil;
027: import org.apache.axis2.wsdl.WSDLConstants;
028: import org.apache.axis2.engine.AxisEngine;
029: import org.apache.axis2.transport.TransportUtils;
030: import org.apache.axiom.soap.SOAPEnvelope;
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.apache.http.HttpResponse;
034: import org.apache.http.Header;
035: import org.apache.http.protocol.HTTP;
036:
037: import javax.xml.stream.XMLStreamException;
038: import java.io.InputStream;
039: import java.io.IOException;
040: import java.util.HashMap;
041: import java.util.Map;
042:
043: /**
044: * Performs processing of the HTTP response received for our outgoing request. An instance of this
045: * class is created to process each unique response.
046: */
047: public class ClientWorker implements Runnable {
048:
049: private static final Log log = LogFactory
050: .getLog(ClientWorker.class);
051:
052: /** the Axis2 configuration context */
053: private ConfigurationContext cfgCtx = null;
054: /** the response message context that would be created */
055: private MessageContext responseMsgCtx = null;
056: /** the InputStream out of which the response body should be read */
057: private InputStream in = null;
058: /** the original request message context */
059: private MessageContext outMsgCtx = null;
060: /** the HttpResponse received */
061: private HttpResponse response = null;
062:
063: /**
064: * Create the thread that would process the response message received for the outgoing message
065: * context sent
066: * @param cfgCtx the Axis2 configuration context
067: * @param in the InputStream to read the body of the response message received
068: * @param outMsgCtx the original outgoing message context (i.e. corresponding request)
069: */
070: public ClientWorker(ConfigurationContext cfgCtx, InputStream in,
071: HttpResponse response, MessageContext outMsgCtx) {
072:
073: this .cfgCtx = cfgCtx;
074: this .in = in;
075: this .outMsgCtx = outMsgCtx;
076: this .response = response;
077:
078: try {
079: responseMsgCtx = outMsgCtx.getOperationContext()
080: .getMessageContext(WSDL2Constants.MESSAGE_LABEL_IN);
081: } catch (AxisFault af) {
082: log
083: .error(
084: "Error getting IN message context from the operation context",
085: af);
086: return;
087: }
088:
089: // this conditional block is to support Sandesha, as it uses an out-in mep, but without
090: // creating the message context to write the response and adding it into the operation
091: // context, as it may get a 202 accepted or 200. So if the operation is complete ignore
092: // this message, else, create a new message context and handle this
093: if (responseMsgCtx == null
094: && outMsgCtx.getOperationContext().isComplete()) {
095: log
096: .debug("Error getting IN message context from the operation context. "
097: + "Possibly an RM terminate sequence message");
098: return;
099:
100: } else {
101: if (responseMsgCtx == null) {
102: responseMsgCtx = new MessageContext();
103: responseMsgCtx.setOperationContext(outMsgCtx
104: .getOperationContext());
105: }
106:
107: responseMsgCtx.setServerSide(true);
108: responseMsgCtx.setDoingREST(outMsgCtx.isDoingREST());
109: responseMsgCtx.setProperty(MessageContext.TRANSPORT_IN,
110: outMsgCtx.getProperty(MessageContext.TRANSPORT_IN));
111: responseMsgCtx.setTransportIn(outMsgCtx.getTransportIn());
112: responseMsgCtx.setTransportOut(outMsgCtx.getTransportOut());
113:
114: // set any transport headers received
115: Header[] headers = response.getAllHeaders();
116: if (headers != null && headers.length > 0) {
117: Map headerMap = new HashMap();
118: for (int i = 0; i < headers.length; i++) {
119: Header header = headers[i];
120: headerMap.put(header.getName(), header.getValue());
121: }
122: responseMsgCtx.setProperty(
123: MessageContext.TRANSPORT_HEADERS, headerMap);
124: }
125:
126: responseMsgCtx.setAxisMessage(outMsgCtx
127: .getOperationContext().getAxisOperation()
128: .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE));
129: responseMsgCtx.setOperationContext(outMsgCtx
130: .getOperationContext());
131: responseMsgCtx.setConfigurationContext(outMsgCtx
132: .getConfigurationContext());
133: responseMsgCtx.setTo(null);
134: }
135: }
136:
137: /**
138: * Process the received response through Axis2
139: */
140: public void run() {
141: // to support Sandesha.. if there isn't a response message context, we cannot read any
142: // response and populate it with the soap envelope
143: if (responseMsgCtx == null) {
144: return;
145: }
146:
147: SOAPEnvelope envelope = null;
148: try {
149: String contentType = response.getFirstHeader(
150: HTTP.CONTENT_TYPE).getValue();
151: String charSetEnc = BuilderUtil
152: .getCharSetEncoding(contentType);
153: if (charSetEnc == null) {
154: charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
155: }
156:
157: if (contentType.indexOf(HTTP.CHARSET_PARAM) > 0) {
158: responseMsgCtx.setProperty(
159: Constants.Configuration.CHARACTER_SET_ENCODING,
160: charSetEnc);
161: } else {
162: responseMsgCtx.setProperty(
163: Constants.Configuration.CHARACTER_SET_ENCODING,
164: MessageContext.DEFAULT_CHAR_SET_ENCODING);
165: }
166: // TODO: FIXME:
167: // workaround for Axis2 TransportUtils.createSOAPMessage() issue, where a response
168: // of content type "text/xml" is thought to be REST if !MC.isServerSide(). This
169: // question is still under debate and due to the timelines, I am commiting this
170: // workaround as Axis2 1.2 is about to be released and Synapse 1.0
171: responseMsgCtx.setServerSide(false);
172: envelope = TransportUtils.createSOAPMessage(responseMsgCtx,
173: in, contentType);
174: responseMsgCtx.setServerSide(true);
175: responseMsgCtx.setEnvelope(envelope);
176:
177: } catch (AxisFault af) {
178: log.error("Fault creating response SOAP envelope", af);
179: return;
180: } catch (XMLStreamException e) {
181: log.error("Error creating response SOAP envelope", e);
182: } catch (IOException e) {
183: log
184: .error(
185: "Error closing input stream from which message was read",
186: e);
187: }
188:
189: AxisEngine engine = new AxisEngine(cfgCtx);
190: try {
191: engine.receive(responseMsgCtx);
192: } catch (AxisFault af) {
193: log.error(
194: "Fault processing response message through Axis2",
195: af);
196: }
197:
198: try {
199: if (in != null) {
200: in.close();
201: }
202: } catch (IOException ignore) {
203: }
204: }
205:
206: // -------------- utility methods -------------
207: private void handleException(String msg, Exception e)
208: throws AxisFault {
209: log.error(msg, e);
210: throw new AxisFault(msg, e);
211: }
212: }
|