Save This Page
Home » axis2-1.5-src » org.apache » axis2 » transport » http » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements. See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership. The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License. You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied. See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   
   20   package org.apache.axis2.transport.http;
   21   
   22   import org.apache.axiom.om.OMOutputFormat;
   23   import org.apache.axis2.AxisFault;
   24   import org.apache.axis2.Constants;
   25   import org.apache.axis2.addressing.EndpointReference;
   26   import org.apache.axis2.context.ConfigurationContext;
   27   import org.apache.axis2.context.MessageContext;
   28   import org.apache.axis2.description.Parameter;
   29   import org.apache.axis2.description.TransportOutDescription;
   30   import org.apache.axis2.handlers.AbstractHandler;
   31   import org.apache.axis2.transport.MessageFormatter;
   32   import org.apache.axis2.transport.OutTransportInfo;
   33   import org.apache.axis2.transport.TransportSender;
   34   import org.apache.axis2.transport.TransportUtils;
   35   import org.apache.axis2.transport.http.server.AxisHttpResponseImpl;
   36   import org.apache.axis2.util.JavaUtils;
   37   import org.apache.commons.httpclient.Header;
   38   import org.apache.commons.httpclient.HttpException;
   39   import org.apache.commons.httpclient.HttpMethod;
   40   import org.apache.commons.logging.Log;
   41   import org.apache.commons.logging.LogFactory;
   42   
   43   import javax.xml.stream.FactoryConfigurationError;
   44   import javax.servlet.http.HttpServletResponse;
   45   import java.io.IOException;
   46   import java.io.OutputStream;
   47   import java.net.MalformedURLException;
   48   import java.net.URL;
   49   import java.util.Iterator;
   50   import java.util.List;
   51   import java.util.Map;
   52   import java.util.zip.GZIPOutputStream;
   53   
   54   public class CommonsHTTPTransportSender extends AbstractHandler implements
   55           TransportSender {
   56   
   57       protected static final String PROXY_HOST_NAME = "proxy_host";
   58   
   59       protected static final String PROXY_PORT = "proxy_port";
   60   
   61       int soTimeout = HTTPConstants.DEFAULT_SO_TIMEOUT;
   62   
   63       /**
   64        * proxydiscription
   65        */
   66       protected TransportOutDescription proxyOutSetting = null;
   67   
   68       private static final Log log = LogFactory
   69               .getLog(CommonsHTTPTransportSender.class);
   70   
   71       protected String httpVersion = HTTPConstants.HEADER_PROTOCOL_11;
   72   
   73       private boolean chunked = false;
   74   
   75       int connectionTimeout = HTTPConstants.DEFAULT_CONNECTION_TIMEOUT;
   76   
   77       public void cleanup(MessageContext msgContext) throws AxisFault {
   78           HttpMethod httpMethod = (HttpMethod) msgContext
   79                   .getProperty(HTTPConstants.HTTP_METHOD);
   80   
   81           if (httpMethod != null) {
   82               httpMethod.releaseConnection();
   83           }
   84       }
   85   
   86       public void init(ConfigurationContext confContext,
   87                        TransportOutDescription transportOut) throws AxisFault {
   88   
   89           // <parameter name="PROTOCOL">HTTP/1.0</parameter> or
   90           // <parameter name="PROTOCOL">HTTP/1.1</parameter> is
   91           // checked
   92           Parameter version = transportOut
   93                   .getParameter(HTTPConstants.PROTOCOL_VERSION);
   94           if (version != null) {
   95               if (HTTPConstants.HEADER_PROTOCOL_11.equals(version.getValue())) {
   96                   httpVersion = HTTPConstants.HEADER_PROTOCOL_11;
   97   
   98                   Parameter transferEncoding = transportOut
   99                           .getParameter(HTTPConstants.HEADER_TRANSFER_ENCODING);
  100   
  101                   if ((transferEncoding != null)
  102                           && HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED
  103                           .equals(transferEncoding.getValue())) {
  104                       chunked = true;
  105                   }
  106               } else if (HTTPConstants.HEADER_PROTOCOL_10.equals(version
  107                       .getValue())) {
  108                   httpVersion = HTTPConstants.HEADER_PROTOCOL_10;
  109               } else {
  110                   throw new AxisFault("Parameter "
  111                           + HTTPConstants.PROTOCOL_VERSION
  112                           + " Can have values only HTTP/1.0 or HTTP/1.1");
  113               }
  114           }
  115   
  116           // Get the timeout values from the configuration
  117           try {
  118               Parameter tempSoTimeoutParam = transportOut
  119                       .getParameter(HTTPConstants.SO_TIMEOUT);
  120               Parameter tempConnTimeoutParam = transportOut
  121                       .getParameter(HTTPConstants.CONNECTION_TIMEOUT);
  122   
  123               if (tempSoTimeoutParam != null) {
  124                   soTimeout = Integer.parseInt((String) tempSoTimeoutParam
  125                           .getValue());
  126               }
  127   
  128               if (tempConnTimeoutParam != null) {
  129                   connectionTimeout = Integer
  130                           .parseInt((String) tempConnTimeoutParam.getValue());
  131               }
  132           } catch (NumberFormatException nfe) {
  133   
  134               // If there's a problem log it and use the default values
  135               log.error("Invalid timeout value format: not a number", nfe);
  136           }
  137       }
  138   
  139       public void stop() {
  140           // Any code that , need to invoke when sender stop
  141       }
  142   
  143       public InvocationResponse invoke(MessageContext msgContext)
  144               throws AxisFault {
  145           try {
  146               OMOutputFormat format = new OMOutputFormat();
  147               // if (!msgContext.isDoingMTOM())
  148               msgContext.setDoingMTOM(TransportUtils.doWriteMTOM(msgContext));
  149               msgContext.setDoingSwA(TransportUtils.doWriteSwA(msgContext));
  150               msgContext.setDoingREST(TransportUtils.isDoingREST(msgContext));
  151               format.setSOAP11(msgContext.isSOAP11());
  152               format.setDoOptimize(msgContext.isDoingMTOM());
  153               format.setDoingSWA(msgContext.isDoingSwA());
  154               format.setCharSetEncoding(TransportUtils.getCharSetEncoding(msgContext));
  155   
  156               Object mimeBoundaryProperty = msgContext
  157                       .getProperty(Constants.Configuration.MIME_BOUNDARY);
  158               if (mimeBoundaryProperty != null) {
  159                   format.setMimeBoundary((String) mimeBoundaryProperty);
  160               }
  161   
  162               TransportOutDescription transportOut = msgContext.getConfigurationContext().
  163                       getAxisConfiguration().getTransportOut(Constants.TRANSPORT_HTTP);
  164   
  165                // set the timeout properteies
  166   
  167               Parameter soTimeoutParam = transportOut.getParameter(HTTPConstants.SO_TIMEOUT);
  168               Parameter connTimeoutParam = transportOut.getParameter(HTTPConstants.CONNECTION_TIMEOUT);
  169   
  170               // set the property valuse only if they are not set by the user explicitly
  171               if ((soTimeoutParam != null) && (msgContext.getProperty(HTTPConstants.SO_TIMEOUT) == null)) {
  172                   msgContext.setProperty(HTTPConstants.SO_TIMEOUT, new Integer((String)soTimeoutParam.getValue()));
  173               }
  174   
  175               if ((connTimeoutParam != null) && (msgContext.getProperty(HTTPConstants.CONNECTION_TIMEOUT) == null)) {
  176                   msgContext.setProperty(HTTPConstants.CONNECTION_TIMEOUT, new Integer((String)connTimeoutParam.getValue()));
  177               }
  178   
  179               //if a parameter has set been set, we will omit the SOAP action for SOAP 1.2
  180               if (transportOut != null) {
  181                   if (!msgContext.isSOAP11()) {
  182                       Parameter param = transportOut.getParameter(HTTPConstants.OMIT_SOAP_12_ACTION);
  183                       Object parameterValue = null;
  184                       if (param != null) {
  185                           parameterValue = param.getValue();
  186                       }
  187   
  188                       if (parameterValue != null && JavaUtils.isTrueExplicitly(parameterValue)) {
  189                           //Check whether user has already overridden this.
  190                           Object propertyValue = msgContext.getProperty(Constants.Configuration.DISABLE_SOAP_ACTION);
  191                           if (propertyValue == null || !JavaUtils.isFalseExplicitly(propertyValue)) {
  192                               msgContext.setProperty(Constants.Configuration.DISABLE_SOAP_ACTION,
  193                                       Boolean.TRUE);
  194                           }
  195                       }
  196                   }
  197               }
  198   
  199               // Transport URL can be different from the WSA-To. So processing
  200               // that now.
  201               EndpointReference epr = null;
  202               String transportURL = (String) msgContext
  203                       .getProperty(Constants.Configuration.TRANSPORT_URL);
  204   
  205               if (transportURL != null) {
  206                   epr = new EndpointReference(transportURL);
  207               } else if (msgContext.getTo() != null
  208                       && !msgContext.getTo().hasAnonymousAddress()) {
  209                   epr = msgContext.getTo();
  210               }
  211   
  212               // Check for the REST behavior, if you desire rest behavior
  213               // put a <parameter name="doREST" value="true"/> at the
  214               // server.xml/client.xml file
  215               // ######################################################
  216               // Change this place to change the wsa:toepr
  217               // epr = something
  218               // ######################################################
  219   
  220               if (epr != null) {
  221                   if (!epr.hasNoneAddress()) {
  222                       writeMessageWithCommons(msgContext, epr, format);
  223                   }else{
  224                   	if(msgContext.isFault()){
  225                   		if(log.isDebugEnabled()){
  226                   			log.debug("Fault sent to WS-A None URI: "+msgContext.getEnvelope().getBody().getFault());
  227                   		}
  228                   	}
  229                   }
  230               } else {
  231                   if (msgContext.getProperty(MessageContext.TRANSPORT_OUT) != null) {
  232                       sendUsingOutputStream(msgContext, format);
  233                       TransportUtils.setResponseWritten(msgContext, true);
  234                   } else {
  235                       throw new AxisFault("Both the TO and MessageContext.TRANSPORT_OUT property " +
  236                               "are null, so nowhere to send");
  237                   }
  238               }
  239           } catch (FactoryConfigurationError e) {
  240               log.debug(e);
  241               throw AxisFault.makeFault(e);
  242           } catch (IOException e) {
  243               log.debug(e);
  244               throw AxisFault.makeFault(e);
  245           }
  246           return InvocationResponse.CONTINUE;
  247       }
  248   
  249       /**
  250        * Send a message (which must be a response) via the OutputStream sitting in the
  251        * MessageContext TRANSPORT_OUT property.  Since this class is used for both requests and
  252        * responses, we split the logic - this method always gets called when we're
  253        * writing to the HTTP response stream, and sendUsingCommons() is used for requests.
  254        *
  255        * @param msgContext the active MessageContext
  256        * @param format output formatter for our message
  257        * @throws AxisFault if a general problem arises
  258        */
  259       private void sendUsingOutputStream(MessageContext msgContext,
  260                                          OMOutputFormat format) throws AxisFault {
  261           OutputStream out = (OutputStream) msgContext.getProperty(MessageContext.TRANSPORT_OUT);
  262   
  263           // I Don't think we need this check.. Content type needs to be set in
  264           // any case. (thilina)
  265           // if (msgContext.isServerSide()) {
  266           OutTransportInfo transportInfo = (OutTransportInfo) msgContext
  267                   .getProperty(Constants.OUT_TRANSPORT_INFO);
  268   
  269           if (transportInfo == null) throw new AxisFault("No transport info in MessageContext");
  270   
  271           ServletBasedOutTransportInfo servletBasedOutTransportInfo = null;
  272           if (transportInfo instanceof ServletBasedOutTransportInfo) {
  273               servletBasedOutTransportInfo =
  274                       (ServletBasedOutTransportInfo) transportInfo;
  275   
  276               // if sending a fault, set HTTP status code to 500
  277               if (msgContext.isFault()) {
  278                   servletBasedOutTransportInfo.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  279               }
  280   
  281               Object customHeaders = msgContext.getProperty(HTTPConstants.HTTP_HEADERS);
  282               if (customHeaders != null) {
  283                   if (customHeaders instanceof List) {
  284                       Iterator iter = ((List) customHeaders).iterator();
  285                       while (iter.hasNext()) {
  286                           Header header = (Header) iter.next();
  287                           if (header != null) {
  288                               servletBasedOutTransportInfo
  289                                       .addHeader(header.getName(), header.getValue());
  290                           }
  291                       }
  292                   } else if (customHeaders instanceof Map) {
  293                       Iterator iter = ((Map) customHeaders).entrySet().iterator();
  294                       while (iter.hasNext()) {
  295                           Map.Entry header = (Map.Entry) iter.next();
  296                           if (header != null) {
  297                               servletBasedOutTransportInfo
  298                                       .addHeader((String) header.getKey(), (String) header.getValue());
  299                           }
  300                       }
  301                   }
  302               }
  303           } else if (transportInfo instanceof AxisHttpResponseImpl) {
  304               Object customHeaders = msgContext.getProperty(HTTPConstants.HTTP_HEADERS);
  305               if (customHeaders != null) {
  306                   if (customHeaders instanceof List) {
  307                       Iterator iter = ((List) customHeaders).iterator();
  308                       while (iter.hasNext()) {
  309                           Header header = (Header) iter.next();
  310                           if (header != null) {
  311                               ((AxisHttpResponseImpl) transportInfo)
  312                                       .addHeader(header.getName(), header.getValue());
  313                           }
  314                       }
  315                   } else if (customHeaders instanceof Map) {
  316                       Iterator iter = ((Map) customHeaders).entrySet().iterator();
  317                       while (iter.hasNext()) {
  318                           Map.Entry header = (Map.Entry) iter.next();
  319                           if (header != null) {
  320                               ((AxisHttpResponseImpl) transportInfo)
  321                                       .addHeader((String) header.getKey(), (String) header.getValue());
  322                           }
  323                       }
  324                   }
  325               }
  326           }
  327   
  328           format.setAutoCloseWriter(true);
  329   
  330           MessageFormatter messageFormatter = TransportUtils.getMessageFormatter(msgContext);
  331           if (messageFormatter == null) throw new AxisFault("No MessageFormatter in MessageContext");
  332   
  333           // Once we get to this point, exceptions should NOT be turned into faults and sent,
  334           // because we're already sending!  So catch everything and log it, but don't pass
  335           // upwards.
  336   
  337           try {
  338               transportInfo.setContentType(
  339                   messageFormatter.getContentType(msgContext, format, findSOAPAction(msgContext)));
  340   
  341               Object gzip = msgContext.getOptions().getProperty(HTTPConstants.MC_GZIP_RESPONSE);
  342               if (gzip != null && JavaUtils.isTrueExplicitly(gzip)) {
  343                   if (servletBasedOutTransportInfo != null)
  344                       servletBasedOutTransportInfo.addHeader(HTTPConstants.HEADER_CONTENT_ENCODING,
  345                                                              HTTPConstants.COMPRESSION_GZIP);
  346                   try {
  347                       out = new GZIPOutputStream(out);
  348                       out.write(messageFormatter.getBytes(msgContext, format));
  349                       ((GZIPOutputStream) out).finish();
  350                       out.flush();
  351                   } catch (IOException e) {
  352                       throw new AxisFault("Could not compress response");
  353                   }
  354               } else {
  355                   messageFormatter.writeTo(msgContext, format, out, false);
  356               }
  357           } catch (AxisFault axisFault) {
  358               log.error(axisFault.getMessage(), axisFault);
  359               throw axisFault;
  360           }
  361       }
  362   
  363       private void writeMessageWithCommons(MessageContext messageContext,
  364                                            EndpointReference toEPR, OMOutputFormat format)
  365               throws AxisFault {
  366           try {
  367               URL url = new URL(toEPR.getAddress());
  368   
  369               // select the Message Sender depending on the REST status
  370               AbstractHTTPSender sender;
  371   
  372               sender = new HTTPSender();
  373   
  374               if (messageContext.getProperty(HTTPConstants.CHUNKED) != null) {
  375                   chunked = JavaUtils.isTrueExplicitly(messageContext
  376                           .getProperty(HTTPConstants.CHUNKED));
  377               }
  378   
  379               if (messageContext.getProperty(HTTPConstants.HTTP_PROTOCOL_VERSION) != null) {
  380                   httpVersion = (String) messageContext
  381                           .getProperty(HTTPConstants.HTTP_PROTOCOL_VERSION);
  382               }
  383               // Following order needed to be preserved because,
  384               // HTTP/1.0 does not support chunk encoding
  385               sender.setChunked(chunked);
  386               sender.setHttpVersion(httpVersion);
  387               sender.setFormat(format);
  388   
  389               sender.send(messageContext, url, findSOAPAction(messageContext));
  390           } catch (MalformedURLException e) {
  391               log.debug(e);
  392               throw AxisFault.makeFault(e);
  393           } catch (HttpException e) {
  394               log.debug(e);
  395               throw AxisFault.makeFault(e);
  396           } catch (IOException e) {
  397               log.debug(e);
  398               throw AxisFault.makeFault(e);
  399           }
  400       }
  401   
  402       private static String findSOAPAction(MessageContext messageContext) {
  403           String soapActionString = null;
  404   
  405           Parameter parameter =
  406                   messageContext.getTransportOut().getParameter(HTTPConstants.OMIT_SOAP_12_ACTION);
  407           if (parameter != null && JavaUtils.isTrueExplicitly(parameter.getValue()) &&
  408               !messageContext.isSOAP11()) {
  409               return "\"\"";
  410           }
  411   
  412           Object disableSoapAction = messageContext.getOptions().getProperty(
  413                   Constants.Configuration.DISABLE_SOAP_ACTION);
  414   
  415           if (!JavaUtils.isTrueExplicitly(disableSoapAction)) {
  416               // first try to get the SOAP action from message context
  417               soapActionString = messageContext.getSoapAction();
  418               if ((soapActionString == null) || (soapActionString.length() == 0)) {
  419                   // now let's try to get WSA action
  420                   soapActionString = messageContext.getWSAAction();
  421                   if (messageContext.getAxisOperation() != null
  422                           && ((soapActionString == null) || (soapActionString
  423                           .length() == 0))) {
  424                       // last option is to get it from the axis operation
  425                       soapActionString = messageContext.getAxisOperation()
  426                               .getSoapAction();
  427                   }
  428               }
  429           }
  430   
  431           //Since action is optional for SOAP 1.2 we can return null here.
  432           if (soapActionString == null && messageContext.isSOAP11()) {
  433               soapActionString = "\"\"";
  434           }
  435   
  436           return soapActionString;
  437       }
  438   }

Save This Page
Home » axis2-1.5-src » org.apache » axis2 » transport » http » [javadoc | source]