View Javadoc

1   /*
2    * $Id: ObjectToHttpClientMethodRequest.java 11728 2008-05-13 07:31:11Z 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.io.UnsupportedEncodingException;
28  import java.net.URI;
29  import java.net.URLEncoder;
30  import java.util.Iterator;
31  
32  import org.apache.commons.httpclient.HttpMethod;
33  import org.apache.commons.httpclient.HttpVersion;
34  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
35  import org.apache.commons.httpclient.methods.DeleteMethod;
36  import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
37  import org.apache.commons.httpclient.methods.GetMethod;
38  import org.apache.commons.httpclient.methods.HeadMethod;
39  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
40  import org.apache.commons.httpclient.methods.OptionsMethod;
41  import org.apache.commons.httpclient.methods.PostMethod;
42  import org.apache.commons.httpclient.methods.PutMethod;
43  import org.apache.commons.httpclient.methods.StringRequestEntity;
44  import org.apache.commons.httpclient.methods.TraceMethod;
45  import org.apache.commons.httpclient.params.HttpMethodParams;
46  
47  /**
48   * <code>ObjectToHttpClientMethodRequest</code> transforms a UMOMessage into a
49   * HttpClient HttpMethod that represents an HttpRequest.
50   */
51  
52  public class ObjectToHttpClientMethodRequest extends AbstractEventAwareTransformer
53  {
54      private final SerializableToByteArray serializableToByteArray;
55  
56      public ObjectToHttpClientMethodRequest()
57      {
58          setReturnClass(HttpMethod.class);
59          serializableToByteArray = new SerializableToByteArray();
60      }
61  
62      private int addParameters(String queryString, PostMethod postMethod)
63      {
64          // Parse the HTTP argument list and convert to a NameValuePair
65          // collection
66  
67          if (StringUtils.isEmpty(queryString))
68          {
69              return 0;
70          }
71  
72          String currentParam;
73          int equals;
74          equals = queryString.indexOf("&");
75          if (equals > -1)
76          {
77              currentParam = queryString.substring(0, equals);
78              queryString = queryString.substring(equals + 1);
79          }
80          else
81          {
82              currentParam = queryString;
83              queryString = StringUtils.EMPTY;
84          }
85          int parameterIndex = -1;
86          while (StringUtils.isNotBlank(currentParam))
87          {
88              String paramName, paramValue;
89              equals = currentParam.indexOf("=");
90              if (equals > -1)
91              {
92                  paramName = currentParam.substring(0, equals);
93                  paramValue = currentParam.substring(equals + 1);
94                  parameterIndex++;
95                  postMethod.addParameter(paramName, paramValue);
96              }
97              equals = queryString.indexOf("&");
98              if (equals > -1)
99              {
100                 currentParam = queryString.substring(0, equals);
101                 queryString = queryString.substring(equals + 1);
102             }
103             else
104             {
105                 currentParam = queryString;
106                 queryString = StringUtils.EMPTY;
107             }
108         }
109         return parameterIndex + 1;
110     }
111 
112     public Object transform(Object src, String encoding, UMOEventContext context) throws TransformerException
113     {
114         UMOMessage msg = context.getMessage();
115 
116         String endpoint = msg.getStringProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, null);
117         if (endpoint == null)
118         {
119             throw new TransformerException(
120                 HttpMessages.eventPropertyNotSetCannotProcessRequest(MuleProperties.MULE_ENDPOINT_PROPERTY),
121                 this);
122         }
123 
124         String method = msg.getStringProperty(HttpConnector.HTTP_METHOD_PROPERTY, "POST");
125         try
126         {
127             URI uri = new URI(endpoint);
128             HttpMethod httpMethod = null;
129 
130             if (HttpConstants.METHOD_GET.equals(method))
131             {
132                 httpMethod = new GetMethod(uri.toString());
133 
134                 String paramName = URLEncoder.encode(msg.getStringProperty(
135                     HttpConnector.HTTP_GET_BODY_PARAM_PROPERTY,
136                     HttpConnector.DEFAULT_HTTP_GET_BODY_PARAM_PROPERTY), encoding);
137                 String paramValue = URLEncoder.encode(src.toString(), encoding);
138 
139                 // MULE-3236: use the raw query here so that properly encoded parameters from the 
140                 // config file stay intact
141                 String query = uri.getRawQuery();
142                 if (!(src instanceof NullPayload) && !StringUtils.EMPTY.equals(src))
143                 {
144                     if (query == null)
145                     {
146                         query = paramName + "=" + paramValue;
147                     }
148                     else
149                     {
150                         query += "&" + paramName + "=" + paramValue;
151                     }
152                 }
153                 httpMethod.setQueryString(query);
154             }
155             else if (HttpConstants.METHOD_POST.equalsIgnoreCase(method))
156             {
157                 PostMethod postMethod = new PostMethod(uri.toString());
158 
159                 String paramName = msg.getStringProperty(HttpConnector.HTTP_POST_BODY_PARAM_PROPERTY, null);
160 
161                 if (paramName == null)
162                 {
163                     // Call method to manage the parameter array
164                     addParameters(uri.getQuery(), postMethod);
165                     setupEntityMethod(src, encoding, context, msg, uri, postMethod);
166                 }
167                 else
168                 {
169                     postMethod.addParameter(paramName, src.toString());
170                 }
171 
172                 httpMethod = postMethod;
173             }
174             else if (HttpConstants.METHOD_PUT.equalsIgnoreCase(method))
175             {
176                 PutMethod putMethod = new PutMethod(uri.toString());
177 
178                 setupEntityMethod(src, encoding, context, msg, uri, putMethod);
179 
180                 httpMethod = putMethod;
181             }
182             else if (HttpConstants.METHOD_DELETE.equalsIgnoreCase(method))
183             {
184                 httpMethod = new DeleteMethod(uri.toString());
185             }
186             else if (HttpConstants.METHOD_HEAD.equalsIgnoreCase(method))
187             {
188                 httpMethod = new HeadMethod(uri.toString());
189             }
190             else if (HttpConstants.METHOD_OPTIONS.equalsIgnoreCase(method))
191             {
192                 httpMethod = new OptionsMethod(uri.toString());
193             }
194             else if (HttpConstants.METHOD_TRACE.equalsIgnoreCase(method))
195             {
196                 httpMethod = new TraceMethod(uri.toString());
197             }
198             else
199             {
200                 throw new TransformerException(HttpMessages.unsupportedMethod(method));
201             }
202 
203             // Allow the user to set HttpMethodParams as an object on the message
204             HttpMethodParams params = (HttpMethodParams) msg.removeProperty(HttpConnector.HTTP_PARAMS_PROPERTY);
205             if (params != null)
206             {
207                 httpMethod.setParams(params);
208             }
209             else
210             {
211                 // TODO we should propbably set other propserties here
212                 String httpVersion = msg.getStringProperty(HttpConnector.HTTP_VERSION_PROPERTY,
213                     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             setHeaders(httpMethod, context);
224 
225             return httpMethod;
226         }
227         catch (Exception e)
228         {
229             throw new TransformerException(this, e);
230         }
231     }
232 
233     private void setupEntityMethod(Object src,
234                                    String encoding,
235                                    UMOEventContext context,
236                                    UMOMessage msg,
237                                    URI uri,
238                                    EntityEnclosingMethod postMethod)
239         throws UnsupportedEncodingException, TransformerException
240     {
241         // Dont set a POST payload if the body is a Null Payload.
242         // This way client calls
243         // can control if a POST body is posted explicitly
244         if (!(context.getMessage().getPayload() instanceof NullPayload))
245         {
246             // See if we have a MIME type set
247             String mimeType = msg.getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, null);
248 
249             if (src instanceof String)
250             {
251                 // Ensure that we strip the encoding information from the
252                 // encoding type
253                 if (mimeType != null)
254                 {
255                     int parameterIndex = mimeType.indexOf(";");
256                     if (parameterIndex > 0)
257                     {
258                         mimeType = mimeType.substring(0, parameterIndex);
259                     }
260                 }
261                 if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
262                 if (encoding == null) encoding = MuleManager.getConfiguration().getEncoding();
263                 postMethod.setRequestEntity(new StringRequestEntity(src.toString(), mimeType, encoding));
264             }
265             else if (src instanceof InputStream)
266             {
267                 // TODO Danger here! We don't know if the content is
268                 // really text or not
269                 if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
270                 postMethod.setRequestEntity(new InputStreamRequestEntity((InputStream) src, mimeType));
271             }
272             else
273             {
274                 // TODO Danger here! We don't know if the content is
275                 // really text or not
276                 if (mimeType == null) mimeType = HttpConstants.DEFAULT_CONTENT_TYPE;
277                 byte[] buffer = (byte[]) serializableToByteArray.doTransform(src, encoding);
278                 postMethod.setRequestEntity(new ByteArrayRequestEntity(buffer, mimeType));
279             }
280         }
281     }
282 
283     protected void setHeaders(HttpMethod httpMethod, UMOEventContext context)
284     {
285         // Standard requestHeaders
286         String headerValue;
287         String headerName;
288         UMOMessage msg = context.getMessage();
289         for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
290         {
291             headerName = (String) iterator.next();
292 
293             headerValue = msg.getStringProperty(headerName, null);
294             if (HttpConstants.REQUEST_HEADER_NAMES.get(headerName) == null)
295             {
296                 if (headerName.startsWith(MuleProperties.PROPERTY_PREFIX))
297                 {
298                     headerName = new StringBuffer(30).append("X-").append(headerName).toString();
299                 }
300 
301                 httpMethod.addRequestHeader(headerName, headerValue);
302             }
303         }
304 
305         if (context.getMessage().getPayload() instanceof InputStream)
306         {
307             // must set this for receiver to properly parse attachments
308             httpMethod.addRequestHeader(HttpConstants.HEADER_CONTENT_TYPE, "multipart/related");
309         }
310     }
311 }