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:
020: package org.apache.axis2.transport.http;
021:
022: import org.apache.axiom.om.OMElement;
023: import org.apache.axiom.om.OMException;
024: import org.apache.axiom.om.OMNamespace;
025: import org.apache.axiom.soap.SOAP11Constants;
026: import org.apache.axiom.soap.SOAP12Constants;
027: import org.apache.axiom.soap.SOAPEnvelope;
028: import org.apache.axiom.soap.SOAPFactory;
029: import org.apache.axiom.soap.SOAPProcessingException;
030: import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
031: import org.apache.axiom.soap.impl.llom.soap12.SOAP12Factory;
032: import org.apache.axis2.AxisFault;
033: import org.apache.axis2.Constants;
034: import org.apache.axis2.addressing.EndpointReference;
035: import org.apache.axis2.builder.BuilderUtil;
036: import org.apache.axis2.context.ConfigurationContext;
037: import org.apache.axis2.context.MessageContext;
038: import org.apache.axis2.context.OperationContext;
039: import org.apache.axis2.description.AxisService;
040: import org.apache.axis2.description.Parameter;
041: import org.apache.axis2.engine.AxisEngine;
042: import org.apache.axis2.engine.Handler.InvocationResponse;
043: import org.apache.axis2.transport.TransportUtils;
044: import org.apache.axis2.util.JavaUtils;
045: import org.apache.axis2.util.Utils;
046:
047: import javax.xml.parsers.FactoryConfigurationError;
048: import javax.xml.stream.XMLStreamException;
049: import java.io.IOException;
050: import java.io.InputStream;
051: import java.io.OutputStream;
052: import java.util.Iterator;
053: import java.util.Map;
054: import java.util.zip.GZIPInputStream;
055:
056: public class HTTPTransportUtils {
057:
058: /**
059: * @deprecated This was used only by the now deprecated processHTTPGetRequest() method.
060: */
061: public static SOAPEnvelope createEnvelopeFromGetRequest(
062: String requestUrl, Map map, ConfigurationContext configCtx)
063: throws AxisFault {
064: String[] values = Utils.parseRequestURLForServiceAndOperation(
065: requestUrl, configCtx.getServiceContextPath());
066: if (values == null) {
067: return new SOAP11Factory().getDefaultEnvelope();
068: }
069:
070: if ((values[1] != null) && (values[0] != null)) {
071: String srvice = values[0];
072: AxisService service = configCtx.getAxisConfiguration()
073: .getService(srvice);
074: if (service == null) {
075: throw new AxisFault("service not found: " + srvice);
076: }
077: String operation = values[1];
078: SOAPFactory soapFactory = new SOAP11Factory();
079: SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
080: OMNamespace omNs = soapFactory.createOMNamespace(service
081: .getSchematargetNamespace(), service
082: .getSchemaTargetNamespacePrefix());
083: soapFactory.createOMNamespace(service
084: .getSchematargetNamespace(), service
085: .getSchemaTargetNamespacePrefix());
086: OMElement opElement = soapFactory.createOMElement(
087: operation, omNs);
088: Iterator it = map.keySet().iterator();
089:
090: while (it.hasNext()) {
091: String name = (String) it.next();
092: String value = (String) map.get(name);
093: OMElement omEle = soapFactory.createOMElement(name,
094: omNs);
095:
096: omEle.setText(value);
097: opElement.addChild(omEle);
098: }
099:
100: envelope.getBody().addChild(opElement);
101:
102: return envelope;
103: } else {
104: return null;
105: }
106: }
107:
108: /**
109: * <p>
110: * Checks whether MTOM needs to be enabled for the message represented by
111: * the msgContext. We check value assigned to the "enableMTOM" property
112: * either using the config files (axis2.xml, services.xml) or
113: * programatically. Programatic configuration is given priority. If the
114: * given value is "optional", MTOM will be enabled only if the incoming
115: * message was an MTOM message.
116: * </p>
117: *
118: * @param msgContext
119: * @return true if SwA needs to be enabled
120: */
121: public static boolean doWriteMTOM(MessageContext msgContext) {
122: boolean enableMTOM;
123: Object enableMTOMObject = null;
124: // First check the whether MTOM is enabled by the configuration
125: // (Eg:Axis2.xml, services.xml)
126: Parameter parameter = msgContext
127: .getParameter(Constants.Configuration.ENABLE_MTOM);
128: if (parameter != null) {
129: enableMTOMObject = parameter.getValue();
130: }
131: // Check whether the configuration is overridden programatically..
132: // Priority given to programatically setting of the value
133: Object property = msgContext
134: .getProperty(Constants.Configuration.ENABLE_MTOM);
135: if (property != null) {
136: enableMTOMObject = property;
137: }
138: enableMTOM = JavaUtils.isTrueExplicitly(enableMTOMObject);
139: // Handle the optional value for enableMTOM
140: // If the value for 'enableMTOM' is given as optional and if the request
141: // message was a MTOM message we sent out MTOM
142: if (!enableMTOM && msgContext.isDoingMTOM()
143: && (enableMTOMObject instanceof String)) {
144: if (((String) enableMTOMObject)
145: .equalsIgnoreCase(Constants.VALUE_OPTIONAL)) {
146: enableMTOM = true;
147: }
148: }
149: return enableMTOM;
150: }
151:
152: /**
153: * <p>
154: * Checks whether SOAP With Attachments (SwA) needs to be enabled for the
155: * message represented by the msgContext. We check value assigned to the
156: * "enableSwA" property either using the config files (axis2.xml,
157: * services.xml) or programatically. Programatic configuration is given
158: * priority. If the given value is "optional", SwA will be enabled only if
159: * the incoming message was SwA type.
160: * </p>
161: *
162: * @param msgContext
163: * @return true if SwA needs to be enabled
164: */
165: public static boolean doWriteSwA(MessageContext msgContext) {
166: boolean enableSwA;
167: Object enableSwAObject = null;
168: // First check the whether SwA is enabled by the configuration
169: // (Eg:Axis2.xml, services.xml)
170: Parameter parameter = msgContext
171: .getParameter(Constants.Configuration.ENABLE_SWA);
172: if (parameter != null) {
173: enableSwAObject = parameter.getValue();
174: }
175: // Check whether the configuration is overridden programatically..
176: // Priority given to programatically setting of the value
177: Object property = msgContext
178: .getProperty(Constants.Configuration.ENABLE_SWA);
179: if (property != null) {
180: enableSwAObject = property;
181: }
182: enableSwA = JavaUtils.isTrueExplicitly(enableSwAObject);
183: // Handle the optional value for enableSwA
184: // If the value for 'enableSwA' is given as optional and if the request
185: // message was a SwA message we sent out SwA
186: if (!enableSwA && msgContext.isDoingSwA()
187: && (enableSwAObject instanceof String)) {
188: if (((String) enableSwAObject)
189: .equalsIgnoreCase(Constants.VALUE_OPTIONAL)) {
190: enableSwA = true;
191: }
192: }
193: return enableSwA;
194: }
195:
196: /**
197: * Utility method to query CharSetEncoding. First look in the
198: * MessageContext. If it's not there look in the OpContext. Use the defualt,
199: * if it's not given in either contexts.
200: *
201: * @param msgContext
202: * @return CharSetEncoding
203: */
204: public static String getCharSetEncoding(MessageContext msgContext) {
205: String charSetEnc = (String) msgContext
206: .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
207:
208: if (charSetEnc == null) {
209: OperationContext opctx = msgContext.getOperationContext();
210: if (opctx != null) {
211: charSetEnc = (String) opctx
212: .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
213: }
214: /**
215: * If the char set enc is still not found use the default
216: */
217: if (charSetEnc == null) {
218: charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
219: }
220: }
221: return charSetEnc;
222: }
223:
224: /**
225: * @param msgContext - The MessageContext of the Request Message
226: * @param out - The output stream of the response
227: * @param soapAction - SoapAction of the request
228: * @param requestURI - The URL that the request came to
229: * @param configurationContext - The Axis Configuration Context
230: * @param requestParameters - The parameters of the request message
231: * @return - boolean indication whether the operation was succesfull
232: * @throws AxisFault - Thrown in case a fault occurs
233: * @deprecated use RESTUtil.processURLRequest(MessageContext msgContext, OutputStream out, String contentType) instead
234: */
235:
236: public static boolean processHTTPGetRequest(
237: MessageContext msgContext, OutputStream out,
238: String soapAction, String requestURI,
239: ConfigurationContext configurationContext,
240: Map requestParameters) throws AxisFault {
241: if ((soapAction != null) && soapAction.startsWith("\"")
242: && soapAction.endsWith("\"")) {
243: soapAction = soapAction.substring(1,
244: soapAction.length() - 1);
245: }
246:
247: msgContext.setSoapAction(soapAction);
248: msgContext.setTo(new EndpointReference(requestURI));
249: msgContext.setProperty(MessageContext.TRANSPORT_OUT, out);
250: msgContext.setServerSide(true);
251: SOAPEnvelope envelope = HTTPTransportUtils
252: .createEnvelopeFromGetRequest(requestURI,
253: requestParameters, configurationContext);
254:
255: if (envelope == null) {
256: return false;
257: } else {
258: msgContext.setDoingREST(true);
259: msgContext.setEnvelope(envelope);
260: AxisEngine.receive(msgContext);
261: return true;
262: }
263: }
264:
265: private static final int VERSION_UNKNOWN = 0;
266: private static final int VERSION_SOAP11 = 1;
267: private static final int VERSION_SOAP12 = 2;
268:
269: public static InvocationResponse processHTTPPostRequest(
270: MessageContext msgContext, InputStream in,
271: OutputStream out, String contentType,
272: String soapActionHeader, String requestURI)
273: throws AxisFault {
274: int soapVersion = VERSION_UNKNOWN;
275: try {
276: soapVersion = initializeMessageContext(msgContext,
277: soapActionHeader, requestURI, contentType);
278: msgContext.setProperty(MessageContext.TRANSPORT_OUT, out);
279:
280: msgContext.setEnvelope(TransportUtils
281: .createSOAPMessage(msgContext, handleGZip(
282: msgContext, in), contentType));
283: return AxisEngine.receive(msgContext);
284: } catch (SOAPProcessingException e) {
285: throw AxisFault.makeFault(e);
286: } catch (AxisFault e) {
287: throw e;
288: } catch (IOException e) {
289: throw AxisFault.makeFault(e);
290: } catch (OMException e) {
291: throw AxisFault.makeFault(e);
292: } catch (XMLStreamException e) {
293: throw AxisFault.makeFault(e);
294: } catch (FactoryConfigurationError e) {
295: throw AxisFault.makeFault(e);
296: } finally {
297: if ((msgContext.getEnvelope() == null)
298: && soapVersion != VERSION_SOAP11) {
299: msgContext.setEnvelope(new SOAP12Factory()
300: .getDefaultEnvelope());
301: }
302: }
303: }
304:
305: public static int initializeMessageContext(
306: MessageContext msgContext, String soapActionHeader,
307: String requestURI, String contentType) {
308: int soapVersion = VERSION_UNKNOWN;
309: // remove the starting and trailing " from the SOAP Action
310: if ((soapActionHeader != null) && soapActionHeader.length() > 0
311: && soapActionHeader.charAt(0) == '\"'
312: && soapActionHeader.endsWith("\"")) {
313: soapActionHeader = soapActionHeader.substring(1,
314: soapActionHeader.length() - 1);
315: }
316:
317: // fill up the Message Contexts
318: msgContext.setSoapAction(soapActionHeader);
319: msgContext.setTo(new EndpointReference(requestURI));
320: msgContext.setServerSide(true);
321:
322: // get the type of char encoding
323: String charSetEnc = BuilderUtil.getCharSetEncoding(contentType);
324: if (charSetEnc == null) {
325: charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
326: }
327: msgContext.setProperty(
328: Constants.Configuration.CHARACTER_SET_ENCODING,
329: charSetEnc);
330:
331: if (contentType != null) {
332: if (contentType
333: .indexOf(SOAP12Constants.SOAP_12_CONTENT_TYPE) > -1) {
334: soapVersion = VERSION_SOAP12;
335: TransportUtils.processContentTypeForAction(contentType,
336: msgContext);
337: } else if (contentType
338: .indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) > -1) {
339: soapVersion = VERSION_SOAP11;
340: } else if (isRESTRequest(contentType)) {
341: // If REST, construct a SOAP11 envelope to hold the rest message and
342: // indicate that this is a REST message.
343: soapVersion = VERSION_SOAP11;
344: msgContext.setDoingREST(true);
345: }
346: if (soapVersion == VERSION_SOAP11) {
347: // TODO Keith : Do we need this anymore
348: // Deployment configuration parameter
349: Parameter enableREST = msgContext
350: .getParameter(Constants.Configuration.ENABLE_REST);
351: if ((soapActionHeader == null) && (enableREST != null)) {
352: if (Constants.VALUE_TRUE.equals(enableREST
353: .getValue())) {
354: // If the content Type is text/xml (BTW which is the
355: // SOAP 1.1 Content type ) and the SOAP Action is
356: // absent it is rest !!
357: msgContext.setDoingREST(true);
358: }
359: }
360: }
361: }
362: return soapVersion;
363: }
364:
365: public static InputStream handleGZip(MessageContext msgContext,
366: InputStream in) throws IOException {
367: Map headers = (Map) msgContext
368: .getProperty(MessageContext.TRANSPORT_HEADERS);
369:
370: if (headers != null) {
371: if (HTTPConstants.COMPRESSION_GZIP.equals(headers
372: .get(HTTPConstants.HEADER_CONTENT_ENCODING))
373: || HTTPConstants.COMPRESSION_GZIP
374: .equals(headers
375: .get(HTTPConstants.HEADER_CONTENT_ENCODING_LOWERCASE))) {
376: in = new GZIPInputStream(in);
377: }
378: }
379: return in;
380: }
381:
382: public static boolean isDoingREST(MessageContext msgContext) {
383: boolean enableREST = false;
384:
385: // check whether isDoingRest is already true in the message context
386: if (msgContext.isDoingREST()) {
387: return true;
388: }
389:
390: Object enableRESTProperty = msgContext
391: .getProperty(Constants.Configuration.ENABLE_REST);
392: if (enableRESTProperty != null) {
393: enableREST = JavaUtils.isTrueExplicitly(enableRESTProperty);
394: }
395:
396: msgContext.setDoingREST(enableREST);
397:
398: return enableREST;
399: }
400:
401: /**
402: * This will match for content types that will be regarded as REST in WSDL2.0.
403: * This contains,
404: * 1. application/xml
405: * 2. application/x-www-form-urlencoded
406: * 3. multipart/form-data
407: * <p/>
408: * If the request doesnot contain a content type; this will return true.
409: *
410: * @param contentType
411: * @return Boolean
412: */
413: public static boolean isRESTRequest(String contentType) {
414: if (contentType == null) {
415: return false;
416: }
417: return (contentType
418: .indexOf(HTTPConstants.MEDIA_TYPE_APPLICATION_XML) > -1
419: || contentType
420: .indexOf(HTTPConstants.MEDIA_TYPE_X_WWW_FORM) > -1 || contentType
421: .indexOf(HTTPConstants.MEDIA_TYPE_MULTIPART_FORM_DATA) > -1);
422: }
423: }
|