View Javadoc

1   /*
2    * $Id: JerseyResourcesComponent.java 19270 2010-09-01 10:37:41Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.module.jersey;
12  
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.component.JavaComponent;
16  import org.mule.api.endpoint.EndpointURI;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.api.processor.MessageProcessor;
19  import org.mule.api.transformer.TransformerException;
20  import org.mule.component.AbstractComponent;
21  import org.mule.transport.http.HttpConnector;
22  
23  import com.sun.jersey.api.core.DefaultResourceConfig;
24  import com.sun.jersey.core.header.InBoundHeaders;
25  import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory;
26  import com.sun.jersey.spi.container.ContainerRequest;
27  import com.sun.jersey.spi.container.ContainerResponse;
28  import com.sun.jersey.spi.container.WebApplication;
29  import com.sun.jersey.spi.container.WebApplicationFactory;
30  
31  import java.io.InputStream;
32  import java.net.URI;
33  import java.net.URISyntaxException;
34  import java.util.ArrayList;
35  import java.util.HashSet;
36  import java.util.List;
37  import java.util.Set;
38  
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  
42  /**
43   * Wraps a set of components which can get invoked by Jersey. This component
44   * will maps the MuleMessage format to the internal Jersey format. Jersey will then select
45   * the appropriate component to invoke based on the request parameters/URI.
46   */
47  public class JerseyResourcesComponent extends AbstractComponent
48  {
49      public static String JERSEY_RESPONSE = "jersey_response";
50  
51      protected final Log logger = LogFactory.getLog(this.getClass());
52  
53      private List<JavaComponent> components;
54  
55      private WebApplication application;
56  
57      @Override
58      protected void doInitialise() throws InitialisationException
59      {
60          super.doInitialise();
61          
62          final Set<Class<?>> resources = new HashSet<Class<?>>();
63  
64          if (components == null) 
65          {
66              throw new IllegalStateException("There must be at least one component in the Jersey resources.");
67          }
68          
69          // Initialize the Jersey resources using the components
70          for (JavaComponent component : components)
71          {
72              Class<?> c;
73              try
74              {
75                  c = component.getObjectType();
76                  resources.add(c);
77              }
78              catch (Exception e)
79              {
80                  throw new InitialisationException(e, this);
81              }
82          }
83  
84          DefaultResourceConfig resourceConfig = createConfiguration(resources);
85  
86          application = WebApplicationFactory.createWebApplication();
87          application.initiate(resourceConfig, getComponentProvider());
88      }
89  
90      protected DefaultResourceConfig createConfiguration(final Set<Class<?>> resources)
91      {
92          return new DefaultResourceConfig(resources);
93      }
94  
95      @Override
96      protected Object doInvoke(MuleEvent event) throws Exception
97      {
98          MuleMessage message = event.getMessage();
99  
100         String path = (String) message.getInboundProperty(HttpConnector.HTTP_REQUEST_PROPERTY);
101         String contextPath = (String) message.getInboundProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY);
102         String query = null;
103         int queryIdx = path.indexOf('?');
104         if (queryIdx != -1)
105         {
106             query = path.substring(queryIdx + 1);
107             path = path.substring(0, queryIdx);
108         }
109 
110         EndpointURI endpointUri = event.getEndpoint().getEndpointURI();
111         String host = message.getInboundProperty("Host", endpointUri.getHost());
112         String method = message.getInboundProperty(HttpConnector.HTTP_METHOD_PROPERTY);
113         InBoundHeaders headers = new InBoundHeaders();
114         for (Object prop : message.getInboundPropertyNames())
115         {
116             Object property = message.getInboundProperty(prop.toString());
117             if (property != null) 
118             {
119                 headers.add(prop.toString(), property.toString());
120             }
121         }
122 
123         String scheme;
124         if ("servlet".equals(endpointUri.getScheme()))
125         {
126             scheme = "http";
127         }
128         else
129         {
130             scheme = endpointUri.getScheme();
131         }
132 
133         URI baseUri = getBaseUri(endpointUri, scheme, host, contextPath);
134         URI completeUri = getCompleteUri(endpointUri, scheme, host, path, query);
135         ContainerRequest req = new ContainerRequest(application, method, baseUri, completeUri, headers,
136             getInputStream(message));
137         if (logger.isDebugEnabled())
138         {
139             logger.debug("Base URI: " + baseUri);
140             logger.debug("Complete URI: " + completeUri);
141         }
142 
143         MuleResponseWriter writer = new MuleResponseWriter(message);
144         ContainerResponse res = new ContainerResponse(application, req, writer);
145 
146         application.handleRequest(req, res);
147         
148         return writer.getResponse();
149     }
150 
151     protected static InputStream getInputStream(MuleMessage message) throws TransformerException
152     {
153         return message.getPayload(InputStream.class);
154     }
155 
156     protected IoCComponentProviderFactory getComponentProvider()
157     {
158         return new MuleComponentProviderFactory(muleContext, components);
159     }
160 
161     protected static URI getCompleteUri(EndpointURI endpointUri,
162                                         String scheme,
163                                         String host,
164                                         String path,
165                                         String query) throws URISyntaxException
166     {
167         String uri = scheme + "://" + host + path;
168         if (query != null)
169         {
170             uri += "?" + query;
171         }
172 
173         return new URI(uri);
174     }
175 
176     protected static URI getBaseUri(EndpointURI endpointUri, String scheme, String host, String contextPath)
177         throws URISyntaxException
178     {
179         if (!contextPath.endsWith("/"))
180         {
181             contextPath += "/";
182         }
183 
184         return new URI(scheme + "://" + host + contextPath);
185     }
186 
187     public List<JavaComponent> getComponents()
188     {
189         return components;
190     }
191 
192     public void setComponents(List<JavaComponent> components)
193     {
194         this.components = components;
195     }
196     
197     public void setMessageProcessors(List<MessageProcessor> messageProcessors) 
198     {
199         List<JavaComponent> components = new ArrayList<JavaComponent>();
200         for (MessageProcessor mp : messageProcessors) 
201         {
202             if (mp instanceof JavaComponent) 
203             {
204                 components.add((JavaComponent)mp);
205             }
206             else
207             {
208                 throw new IllegalStateException("Only JavaComponents are allowed as MessageProcessors. Type " + mp.getClass().getName() + " is not allowed.");
209             }
210         }
211         setComponents(components);
212     }
213 }