1
2
3
4
5
6
7 package org.mule.module.jersey;
8
9 import org.mule.api.MuleEvent;
10 import org.mule.api.MuleMessage;
11 import org.mule.api.component.JavaComponent;
12 import org.mule.api.endpoint.EndpointURI;
13 import org.mule.api.lifecycle.InitialisationException;
14 import org.mule.api.processor.MessageProcessor;
15 import org.mule.api.transformer.TransformerException;
16 import org.mule.component.AbstractComponent;
17 import org.mule.transport.http.HttpConnector;
18
19 import com.sun.jersey.api.core.DefaultResourceConfig;
20 import com.sun.jersey.core.header.InBoundHeaders;
21 import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory;
22 import com.sun.jersey.spi.container.ContainerRequest;
23 import com.sun.jersey.spi.container.ContainerResponse;
24 import com.sun.jersey.spi.container.WebApplication;
25 import com.sun.jersey.spi.container.WebApplicationFactory;
26
27 import java.io.InputStream;
28 import java.net.URI;
29 import java.net.URISyntaxException;
30 import java.util.ArrayList;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Set;
34
35 import javax.ws.rs.ext.ExceptionMapper;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40
41
42
43
44
45 public class JerseyResourcesComponent extends AbstractComponent
46 {
47 public static String JERSEY_RESPONSE = "jersey_response";
48
49 protected final Log logger = LogFactory.getLog(this.getClass());
50
51 private List<JavaComponent> components;
52
53 private WebApplication application;
54
55 private List<ExceptionMapper<?>> exceptionMappers = new ArrayList<ExceptionMapper<?>>();
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 initializeResources(resources);
70 initializeExceptionMappers(resources);
71
72 DefaultResourceConfig resourceConfig = createConfiguration(resources);
73
74 application = WebApplicationFactory.createWebApplication();
75 application.initiate(resourceConfig, getComponentProvider());
76 }
77
78 protected void initializeResources(Set<Class<?>> resources) throws InitialisationException
79 {
80
81 for (JavaComponent component : components)
82 {
83 Class<?> c;
84 try
85 {
86 c = component.getObjectType();
87 resources.add(c);
88 }
89 catch (Exception e)
90 {
91 throw new InitialisationException(e, this);
92 }
93 }
94 }
95
96 protected void initializeExceptionMappers(final Set<Class<?>> resources)
97 {
98
99 for (ExceptionMapper<?> exceptionMapper : exceptionMappers)
100 {
101 resources.add(exceptionMapper.getClass());
102 }
103 }
104
105 protected DefaultResourceConfig createConfiguration(final Set<Class<?>> resources)
106 {
107 return new DefaultResourceConfig(resources);
108 }
109
110 @Override
111 protected Object doInvoke(MuleEvent event) throws Exception
112 {
113 MuleMessage message = event.getMessage();
114
115 String path = (String) message.getInboundProperty(HttpConnector.HTTP_REQUEST_PROPERTY);
116 String contextPath = (String) message.getInboundProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY);
117 String query = null;
118 int queryIdx = path.indexOf('?');
119 if (queryIdx != -1)
120 {
121 query = path.substring(queryIdx + 1);
122 path = path.substring(0, queryIdx);
123 }
124
125 EndpointURI endpointUri = event.getEndpoint().getEndpointURI();
126 String host = message.getInboundProperty("Host", endpointUri.getHost());
127 String method = message.getInboundProperty(HttpConnector.HTTP_METHOD_PROPERTY);
128 InBoundHeaders headers = new InBoundHeaders();
129 for (Object prop : message.getInboundPropertyNames())
130 {
131 Object property = message.getInboundProperty(prop.toString());
132 if (property != null)
133 {
134 headers.add(prop.toString(), property.toString());
135 }
136 }
137
138 String scheme;
139 if ("servlet".equals(endpointUri.getScheme()))
140 {
141 scheme = "http";
142 }
143 else
144 {
145 scheme = endpointUri.getScheme();
146 }
147
148 URI baseUri = getBaseUri(endpointUri, scheme, host, contextPath);
149 URI completeUri = getCompleteUri(endpointUri, scheme, host, path, query);
150 ContainerRequest req = new ContainerRequest(application, method, baseUri, completeUri, headers,
151 getInputStream(message));
152 if (logger.isDebugEnabled())
153 {
154 logger.debug("Base URI: " + baseUri);
155 logger.debug("Complete URI: " + completeUri);
156 }
157
158 MuleResponseWriter writer = new MuleResponseWriter(message);
159 ContainerResponse res = new ContainerResponse(application, req, writer);
160
161 application.handleRequest(req, res);
162
163 return writer.getResponse();
164 }
165
166 protected static InputStream getInputStream(MuleMessage message) throws TransformerException
167 {
168 return message.getPayload(InputStream.class);
169 }
170
171 protected IoCComponentProviderFactory getComponentProvider()
172 {
173 return new MuleComponentProviderFactory(muleContext, components);
174 }
175
176 protected static URI getCompleteUri(EndpointURI endpointUri,
177 String scheme,
178 String host,
179 String path,
180 String query) throws URISyntaxException
181 {
182 String uri = scheme + "://" + host + path;
183 if (query != null)
184 {
185 uri += "?" + query;
186 }
187
188 return new URI(uri);
189 }
190
191 protected static URI getBaseUri(EndpointURI endpointUri, String scheme, String host, String contextPath)
192 throws URISyntaxException
193 {
194 if (!contextPath.endsWith("/"))
195 {
196 contextPath += "/";
197 }
198
199 return new URI(scheme + "://" + host + contextPath);
200 }
201
202 public List<JavaComponent> getComponents()
203 {
204 return components;
205 }
206
207 public void setComponents(List<JavaComponent> components)
208 {
209 this.components = components;
210 }
211
212 public void setMessageProcessors(List<MessageProcessor> messageProcessors)
213 {
214 List<JavaComponent> javaComponents = new ArrayList<JavaComponent>();
215 for (MessageProcessor mp : messageProcessors)
216 {
217 if (mp instanceof JavaComponent)
218 {
219 javaComponents.add((JavaComponent) mp);
220 }
221 else
222 {
223 throw new IllegalStateException("Only JavaComponents are allowed as MessageProcessors. Type "
224 + mp.getClass().getName() + " is not allowed.");
225 }
226 }
227 setComponents(javaComponents);
228 }
229
230 public void setExceptionMapper(ExceptionMapper<?> exceptionMapper)
231 {
232 exceptionMappers.add(exceptionMapper);
233 }
234 }