View Javadoc

1   /*
2    * $Id: ObjectToHttpClientMethodRequest.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.providers.http.transformers;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.MuleProperties;
15  import org.mule.providers.NullPayload;
16  import org.mule.providers.http.HttpConnector;
17  import org.mule.providers.http.HttpConstants;
18  import org.mule.providers.http.i18n.HttpMessages;
19  import org.mule.transformers.AbstractEventAwareTransformer;
20  import org.mule.transformers.simple.SerializableToByteArray;
21  import org.mule.umo.UMOEventContext;
22  import org.mule.umo.UMOMessage;
23  import org.mule.umo.transformer.TransformerException;
24  import org.mule.util.StringUtils;
25  
26  import java.io.InputStream;
27  import java.net.URI;
28  import java.util.Iterator;
29  
30  import org.apache.commons.httpclient.HttpMethod;
31  import org.apache.commons.httpclient.HttpVersion;
32  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
33  import org.apache.commons.httpclient.methods.GetMethod;
34  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
35  import org.apache.commons.httpclient.methods.PostMethod;
36  import org.apache.commons.httpclient.methods.StringRequestEntity;
37  import org.apache.commons.httpclient.params.HttpMethodParams;
38  
39  /**
40   * <code>ObjectToHttpClientMethodRequest</code> transforms a UMOMessage into a
41   * HttpClient HttpMethod that represents an HttpRequest.
42   */
43  
44  public class ObjectToHttpClientMethodRequest extends AbstractEventAwareTransformer
45  {
46      private final SerializableToByteArray serializableToByteArray;
47  
48      public ObjectToHttpClientMethodRequest()
49      {
50          setReturnClass(HttpMethod.class);
51          serializableToByteArray = new SerializableToByteArray();
52      }
53  
54      private int addParameters(String queryString, PostMethod postMethod)
55      {
56          // Parse the HTTP argument list and convert to a NameValuePair
57          // collection
58  
59          if (StringUtils.isEmpty(queryString))
60          {
61              return 0;
62          }
63  
64          String currentParam;
65          int equals;
66          equals = queryString.indexOf("&");
67          if (equals > -1)
68          {
69              currentParam = queryString.substring(0, equals);
70              queryString = queryString.substring(equals + 1);
71          }
72          else
73          {
74              currentParam = queryString;
75              queryString = StringUtils.EMPTY;
76          }
77          int parameterIndex = -1;
78          while (StringUtils.isNotBlank(currentParam))
79          {
80              String paramName, paramValue;
81              equals = currentParam.indexOf("=");
82              if (equals > -1)
83              {
84                  paramName = currentParam.substring(0, equals);
85                  paramValue = currentParam.substring(equals + 1);
86                  parameterIndex++;
87                  postMethod.addParameter(paramName, paramValue);
88              }
89              equals = queryString.indexOf("&");
90              if (equals > -1)
91              {
92                  currentParam = queryString.substring(0, equals);
93                  queryString = queryString.substring(equals + 1);
94              }
95              else
96              {
97                  currentParam = queryString;
98                  queryString = StringUtils.EMPTY;
99              }
100         }
101         return parameterIndex + 1;
102     }
103 
104     public Object transform(Object src, String encoding, UMOEventContext context) throws TransformerException
105     {
106         UMOMessage msg = context.getMessage();
107 
108         String endpoint = msg.getStringProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, null);
109         if (endpoint == null)
110         {
111             throw new TransformerException(
112                 HttpMessages.eventPropertyNotSetCannotProcessRequest(
113                     MuleProperties.MULE_ENDPOINT_PROPERTY), this);
114         }
115 
116         String method = msg.getStringProperty(HttpConnector.HTTP_METHOD_PROPERTY, "POST");
117         try
118         {
119             URI uri = new URI(endpoint);
120             HttpMethod httpMethod = null;
121 
122             if (HttpConstants.METHOD_GET.equals(method))
123             {
124                 httpMethod = new GetMethod(uri.toString());
125                 setHeaders(httpMethod, context);
126                 String paramName = msg.getStringProperty(HttpConnector.HTTP_GET_BODY_PARAM_PROPERTY,
127                     HttpConnector.DEFAULT_HTTP_GET_BODY_PARAM_PROPERTY);
128                 String query = uri.getQuery();
129                 if (!(src instanceof NullPayload) && !StringUtils.EMPTY.equals(src))
130                 {
131                     if (query == null)
132                     {
133                         query = paramName + "=" + src.toString();
134                     }
135                     else
136                     {
137                         query += "&" + paramName + "=" + src.toString();
138                     }
139                 }
140                 httpMethod.setQueryString(query);
141 
142             }
143             else
144             {
145                 PostMethod postMethod = new PostMethod(uri.toString());
146                 setHeaders(postMethod, context);
147                 String paramName = msg.getStringProperty(HttpConnector.HTTP_POST_BODY_PARAM_PROPERTY, null);
148                 // postMethod.setRequestContentLength(PostMethod.CONTENT_LENGTH_AUTO);
149                 if (paramName == null)
150                 {
151                     // Call method to manage the parameter array
152                     addParameters(uri.getQuery(), postMethod);
153                     // Dont set a POST payload if the body is a Null Payload.
154                     // This way client calls
155                     // can control if a POST body is posted explicitly
156                     if (!(context.getMessage().getPayload() instanceof NullPayload))
157                     {
158                         // See if we have a MIME type set
159                         String mimeType = msg.getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, null);
160 
161                         if (src instanceof String)
162                         {
163                             // Ensure that we strip the encoding information from the
164                             // encoding type
165                             if (mimeType != null)
166                             {
167                                 int parameterIndex = mimeType.indexOf(";");
168                                 if (parameterIndex > 0)
169                                 {
170                                     mimeType = mimeType.substring(0, parameterIndex);
171                                 }
172                             }
173                             if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
174                             if (encoding == null) encoding = MuleManager.getConfiguration().getEncoding();
175                             postMethod.setRequestEntity(new StringRequestEntity(src.toString(), mimeType,
176                                 encoding));
177                         }
178                         else if (src instanceof InputStream)
179                         {
180                             // TODO Danger here! We don't know if the content is
181                             // really text or not
182                             if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
183                             postMethod.setRequestEntity(new InputStreamRequestEntity((InputStream)src,
184                                 mimeType));
185                         }
186                         else
187                         {
188                             // TODO Danger here! We don't know if the content is
189                             // really text or not
190                             if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
191                             byte[] buffer = (byte[])serializableToByteArray.doTransform(src, encoding);
192                             postMethod.setRequestEntity(new ByteArrayRequestEntity(buffer, mimeType));
193                         }
194                     }
195                 }
196                 else
197                 {
198                     postMethod.addParameter(paramName, src.toString());
199                 }
200 
201                 httpMethod = postMethod;
202             }
203 
204             //Allow the user to set HttpMethodParams as an object on the message
205             HttpMethodParams params = (HttpMethodParams)msg.removeProperty(HttpConnector.HTTP_PARAMS_PROPERTY);
206             if(params!=null)
207             {
208                 httpMethod.setParams(params);
209             }
210             else
211             {
212                 //TODO we should propbably set other propserties here
213                 String httpVersion = msg.getStringProperty(HttpConnector.HTTP_VERSION_PROPERTY, HttpConstants.HTTP11);
214                 if(HttpConstants.HTTP10.equals(httpVersion))
215                 {
216                     httpMethod.getParams().setVersion(HttpVersion.HTTP_1_0);
217                 }
218                 else
219                 {
220                     httpMethod.getParams().setVersion(HttpVersion.HTTP_1_1);
221                 }                
222             }
223             return httpMethod;
224         }
225         catch (Exception e)
226         {
227             throw new TransformerException(this, e);
228         }
229     }
230 
231     protected void setHeaders(HttpMethod httpMethod, UMOEventContext context)
232     {
233         // Standard requestHeaders
234         String headerValue;
235         String headerName;
236         UMOMessage msg = context.getMessage();
237         for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
238         {
239             headerName = (String)iterator.next();
240             headerValue = msg.getStringProperty(headerName, null);
241             if (HttpConstants.REQUEST_HEADER_NAMES.get(headerName) == null)
242             {
243                 if (headerName.startsWith(MuleProperties.PROPERTY_PREFIX))
244                 {
245                     headerName = new StringBuffer(30).append("X-").append(headerName).toString();
246                 }
247                 // Make sure we have a valid header name otherwise we will
248                 // corrupt the request
249                 // If it is Content-Length we should check the Response Headers
250                 // before setting it
251                 if (headerName.startsWith(HttpConstants.HEADER_CONTENT_LENGTH))
252                 {
253                     if (httpMethod.getResponseHeader(HttpConstants.HEADER_CONTENT_LENGTH) == null)
254                     {
255                         httpMethod.addRequestHeader(headerName, headerValue);
256                     }
257                 }
258                 else
259                 {
260                     httpMethod.addRequestHeader(headerName, headerValue);
261                 }
262             }
263         }
264 
265         if (context.getMessage().getPayload() instanceof InputStream)
266         {
267             // must set this for receiver to properly parse attachments
268             httpMethod.addRequestHeader(HttpConstants.HEADER_CONTENT_TYPE, "multipart/related");
269         }
270     }
271 }