1
2
3
4
5
6
7 package org.mule.transport.servlet;
8
9 import org.mule.RequestContext;
10 import org.mule.api.MuleContext;
11 import org.mule.api.MuleMessage;
12 import org.mule.api.config.MuleProperties;
13 import org.mule.api.lifecycle.InitialisationException;
14 import org.mule.api.transformer.TransformerException;
15 import org.mule.api.transport.OutputHandler;
16 import org.mule.config.ExceptionHelper;
17 import org.mule.transport.http.HttpConstants;
18 import org.mule.transport.http.HttpResponse;
19 import org.mule.transport.http.transformers.MuleMessageToHttpResponse;
20
21 import java.io.IOException;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServlet;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.httpclient.Header;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31
32
33
34
35
36 public abstract class AbstractReceiverServlet extends HttpServlet
37 {
38
39
40
41 protected transient Log logger = LogFactory.getLog(getClass());
42
43 public static final String REQUEST_TIMEOUT_PROPERTY = "org.mule.servlet.timeout";
44 public static final String FEEDBACK_PROPERTY = "org.mule.servlet.feedback";
45 public static final String DEFAULT_CONTENT_TYPE_PROPERTY = "org.mule.servlet.default.content.type";
46
47
48
49
50
51 @Deprecated
52 public static final String SERVLET_CONNECTOR_NAME_PROPERTY = "org.mule.servlet.connector.name";
53
54 public static final String PAYLOAD_PARAMETER_NAME = "org.mule.servlet.payload.param";
55 public static final String DEFAULT_PAYLOAD_PARAMETER_NAME = "payload";
56
57 public static final long DEFAULT_GET_TIMEOUT = 10000L;
58
59 protected String payloadParameterName;
60 protected long timeout = DEFAULT_GET_TIMEOUT;
61 protected boolean feedback = true;
62 protected String defaultContentType = HttpConstants.DEFAULT_CONTENT_TYPE;
63 protected MuleContext muleContext;
64
65 private MuleMessageToHttpResponse responseTransformer = new MuleMessageToHttpResponse();
66
67 @Override
68 public final void init() throws ServletException
69 {
70 String timeoutString = getServletConfig().getInitParameter(REQUEST_TIMEOUT_PROPERTY);
71 if (timeoutString != null)
72 {
73 timeout = Long.parseLong(timeoutString);
74 }
75 if (logger.isInfoEnabled())
76 {
77 logger.info("Default request timeout for GET methods is: " + timeout);
78 }
79
80 String feedbackString = getServletConfig().getInitParameter(FEEDBACK_PROPERTY);
81 if (feedbackString != null)
82 {
83 feedback = Boolean.valueOf(feedbackString);
84 }
85 if (logger.isInfoEnabled())
86 {
87 logger.info("feedback is set to: " + feedback);
88 }
89
90 String ct = getServletConfig().getInitParameter(DEFAULT_CONTENT_TYPE_PROPERTY);
91 if (ct != null)
92 {
93 if (logger.isDebugEnabled())
94 {
95 logger.debug("Using default content type configured on the servlet (" + DEFAULT_CONTENT_TYPE_PROPERTY + ") = " + ct);
96 }
97 defaultContentType = ct;
98 }
99 if (logger.isInfoEnabled())
100 {
101 logger.info("Default content type is: " + defaultContentType);
102 }
103
104 payloadParameterName = getServletConfig().getInitParameter(PAYLOAD_PARAMETER_NAME);
105 if (payloadParameterName == null)
106 {
107 payloadParameterName = DEFAULT_PAYLOAD_PARAMETER_NAME;
108 }
109 if (logger.isInfoEnabled())
110 {
111 logger.info("Using payload param name: " + payloadParameterName);
112 }
113
114 muleContext = setupMuleContext();
115 setupResponseTransformer();
116 doInit();
117 }
118
119 protected MuleContext setupMuleContext() throws ServletException
120 {
121 MuleContext context = (MuleContext) getServletContext().getAttribute(MuleProperties.MULE_CONTEXT_PROPERTY);
122 if (context == null)
123 {
124 throw new ServletException("Property " + MuleProperties.MULE_CONTEXT_PROPERTY + " not set on ServletContext");
125 }
126 return context;
127 }
128
129 protected void setupResponseTransformer() throws ServletException
130 {
131 responseTransformer.setMuleContext(muleContext);
132
133 try
134 {
135 responseTransformer.initialise();
136 }
137 catch (InitialisationException e)
138 {
139 throw new ServletException(e);
140 }
141 }
142
143 protected void doInit() throws ServletException
144 {
145
146 }
147
148 protected void writeResponse(HttpServletResponse servletResponse, MuleMessage message) throws Exception
149 {
150 if (message == null)
151 {
152 writeEmptyResponse(servletResponse);
153 }
154 else
155 {
156 writeResponseFromMessage(servletResponse, message);
157 }
158 servletResponse.flushBuffer();
159 }
160
161 protected void writeEmptyResponse(HttpServletResponse servletResponse) throws IOException
162 {
163 servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
164 if (feedback)
165 {
166 servletResponse.setStatus(HttpServletResponse.SC_OK);
167 servletResponse.getWriter().write("Action was processed successfully. There was no result");
168 }
169 }
170
171 protected void writeResponseFromMessage(HttpServletResponse servletResponse, MuleMessage message) throws Exception
172 {
173 HttpResponse httpResponse = convertToHttpResponse(message);
174 setHttpHeadersOnServletResponse(httpResponse, servletResponse);
175
176 if (!servletResponse.isCommitted())
177 {
178 servletResponse.setStatus(httpResponse.getStatusCode());
179 }
180
181 if (httpResponse.hasBody())
182 {
183 OutputHandler outputHandler = httpResponse.getBody();
184 outputHandler.write(RequestContext.getEvent(), servletResponse.getOutputStream());
185 }
186 }
187
188 protected HttpResponse convertToHttpResponse(MuleMessage message) throws TransformerException
189 {
190 if (message.getPayload() instanceof HttpResponse)
191 {
192 return (HttpResponse) message.getPayload();
193
194 }
195 else
196 {
197 return (HttpResponse) responseTransformer.transform(message);
198 }
199 }
200
201 protected HttpServletResponse setHttpHeadersOnServletResponse(HttpResponse httpResponse, HttpServletResponse servletResponse)
202 {
203
204
205
206
207
208 httpResponse.removeHeaders(HttpConstants.HEADER_TRANSFER_ENCODING);
209
210 Header[] headers = httpResponse.getHeaders();
211 for (Header header : headers)
212 {
213 servletResponse.addHeader(header.getName(), header.getValue());
214 }
215
216 ensureContentTypeHeaderIsSet(servletResponse, httpResponse);
217
218 return servletResponse;
219 }
220
221 protected void ensureContentTypeHeaderIsSet(HttpServletResponse servletResponse, HttpResponse httpResponse)
222 {
223 Header contentTypeHeader = httpResponse.getFirstHeader(HttpConstants.HEADER_CONTENT_TYPE);
224 String contentType = defaultContentType;
225 if (contentTypeHeaderIsValid(contentTypeHeader))
226 {
227 if (logger.isDebugEnabled())
228 {
229 logger.debug("Using Content-Type from message header = " + contentTypeHeader.getValue());
230 }
231 contentType = contentTypeHeader.getValue();
232 }
233 servletResponse.setContentType(contentType);
234 }
235
236 protected boolean contentTypeHeaderIsValid(Header header)
237 {
238 return (header != null) && (header.getValue() != null);
239 }
240
241 protected void handleException(Throwable exception, String message, HttpServletResponse response)
242 {
243 logger.error("message: " + exception.getMessage(), exception);
244 int code = Integer.valueOf(ExceptionHelper.getErrorMapping("http", exception.getClass()));
245 response.setStatus(code);
246 try
247 {
248 response.sendError(code, message + ": " + exception.getMessage());
249 }
250 catch (IOException e)
251 {
252 logger.error("Failed to sendError on response: " + e.getMessage(), e);
253 }
254 }
255 }