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