1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20
21 package org.apache.axis2.transport.http;
22
23 import org.apache.axiom.om.OMElement;
24 import org.apache.axiom.om.impl.builder.StAXBuilder;
25 import org.apache.axiom.soap.SOAP12Constants;
26 import org.apache.axiom.soap.SOAPEnvelope;
27 import org.apache.axiom.soap.SOAPFaultCode;
28 import org.apache.axis2.AxisFault;
29 import org.apache.axis2.Constants;
30 import org.apache.axis2.addressing.AddressingHelper;
31 import org.apache.axis2.addressing.EndpointReference;
32 import org.apache.axis2.context.ConfigurationContext;
33 import org.apache.axis2.context.ConfigurationContextFactory;
34 import org.apache.axis2.context.MessageContext;
35 import org.apache.axis2.context.SessionContext;
36 import org.apache.axis2.deployment.WarBasedAxisConfigurator;
37 import org.apache.axis2.description.AxisBindingMessage;
38 import org.apache.axis2.description.AxisBindingOperation;
39 import org.apache.axis2.description.Parameter;
40 import org.apache.axis2.description.TransportInDescription;
41 import org.apache.axis2.description.TransportOutDescription;
42 import org.apache.axis2.description.WSDL2Constants;
43 import org.apache.axis2.engine.AxisConfiguration;
44 import org.apache.axis2.engine.AxisEngine;
45 import org.apache.axis2.engine.Handler.InvocationResponse;
46 import org.apache.axis2.engine.ListenerManager;
47 import org.apache.axis2.transport.RequestResponseTransport;
48 import org.apache.axis2.transport.TransportListener;
49 import org.apache.axis2.transport.TransportUtils;
50 import org.apache.axis2.transport.http.server.HttpUtils;
51 import org.apache.axis2.transport.http.util.QueryStringParser;
52 import org.apache.axis2.transport.http.util.RESTUtil;
53 import org.apache.axis2.util.JavaUtils;
54 import org.apache.axis2.util.MessageContextBuilder;
55 import org.apache.axis2.util.Utils;
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
58
59 import javax.servlet.ServletConfig;
60 import javax.servlet.ServletContext;
61 import javax.servlet.ServletException;
62 import javax.servlet.http.HttpServlet;
63 import javax.servlet.http.HttpServletRequest;
64 import javax.servlet.http.HttpServletResponse;
65 import javax.xml.namespace.QName;
66 import java.io.BufferedInputStream;
67 import java.io.BufferedOutputStream;
68 import java.io.IOException;
69 import java.io.OutputStream;
70 import java.io.PrintWriter;
71 import java.net.SocketException;
72 import java.util.Arrays;
73 import java.util.HashSet;
74 import java.util.Map;
75 import java.util.Set;
76 import java.util.concurrent.CountDownLatch;
77
78 /**
79 * Class AxisServlet
80 */
81 public class AxisServlet extends HttpServlet implements TransportListener {
82
83 private static final Log log = LogFactory.getLog(AxisServlet.class);
84 public static final String CONFIGURATION_CONTEXT = "CONFIGURATION_CONTEXT";
85 public static final String SESSION_ID = "SessionId";
86
87 private static final Set<String> metadataQueryParamNames = new HashSet<String>(
88 Arrays.asList("wsdl2", "wsdl", "xsd", "policy"));
89
90 protected transient ConfigurationContext configContext;
91 protected transient AxisConfiguration axisConfiguration;
92
93 protected transient ServletConfig servletConfig;
94
95 protected transient ListingAgent agent;
96 protected transient String contextRoot = null;
97
98 protected boolean disableREST = false;
99 private static final String LIST_SERVICES_SUFFIX = "/services/listServices";
100 private static final String LIST_FAULTY_SERVICES_SUFFIX = "/services/ListFaultyServices";
101 private boolean closeReader = true;
102
103 private static final int BUFFER_SIZE = 1024 * 8;
104
105 private boolean initCalled = false;
106
107 /**
108 * Implementaion of POST interface
109 *
110 * @param request
111 * @param response
112 * @throws ServletException
113 * @throws IOException
114 */
115 protected void doPost(HttpServletRequest request, HttpServletResponse response)
116 throws ServletException, IOException {
117 //set the initial buffer for a larger value
118 try {
119 response.setBufferSize(BUFFER_SIZE);
120 } catch (Throwable t){
121 log.info("Old Servlet API :" + t);
122 }
123
124 initContextRoot(request);
125
126 MessageContext msgContext;
127 OutputStream out = response.getOutputStream();
128 String contentType = request.getContentType();
129 if (!HTTPTransportUtils.isRESTRequest(contentType)) {
130 msgContext = createMessageContext(request, response);
131 msgContext.setProperty(Constants.Configuration.CONTENT_TYPE, contentType);
132 try {
133 // adding ServletContext into msgContext;
134 String url;
135 try {
136 url = request.getRequestURL().toString();
137 } catch (Throwable t){
138 log.info("Old Servlet API (fallback to HttpServletRequest.getRequestURI) :" + t);
139 url = request.getRequestURI();
140 }
141
142 InvocationResponse pi = HTTPTransportUtils.
143 processHTTPPostRequest(msgContext,
144 new BufferedInputStream(request.getInputStream()),
145 new BufferedOutputStream(out),
146 contentType,
147 request.getHeader(HTTPConstants.HEADER_SOAP_ACTION),
148 url);
149
150 Boolean holdResponse =
151 (Boolean) msgContext.getProperty(RequestResponseTransport.HOLD_RESPONSE);
152
153 if (pi.equals(InvocationResponse.SUSPEND) ||
154 (holdResponse != null && Boolean.TRUE.equals(holdResponse))) {
155 ((RequestResponseTransport) msgContext
156 .getProperty(RequestResponseTransport.TRANSPORT_CONTROL))
157 .awaitResponse();
158 }
159 response.setContentType("text/xml; charset="
160 + msgContext
161 .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING));
162 // if data has not been sent back and this is not a signal response
163 if (!TransportUtils.isResponseWritten(msgContext)
164 && (((RequestResponseTransport)
165 msgContext.getProperty(
166 RequestResponseTransport.TRANSPORT_CONTROL)).
167 getStatus() != RequestResponseTransport.
168 RequestResponseTransportStatus.SIGNALLED)) {
169 response.setStatus(HttpServletResponse.SC_ACCEPTED);
170 }
171
172 } catch (AxisFault e) {
173 setResponseState(msgContext, response);
174 log.debug(e);
175 if (msgContext != null) {
176 processAxisFault(msgContext, response, out, e);
177 } else {
178 throw new ServletException(e);
179 }
180 } catch (Throwable t) {
181 log.error(t.getMessage(), t);
182 try {
183 // If the fault is not going along the back channel we should be 202ing
184 if (AddressingHelper.isFaultRedirected(msgContext)) {
185 response.setStatus(HttpServletResponse.SC_ACCEPTED);
186 } else {
187 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
188
189 AxisBindingOperation axisBindingOperation =
190 (AxisBindingOperation) msgContext
191 .getProperty(Constants.AXIS_BINDING_OPERATION);
192 if (axisBindingOperation != null) {
193 AxisBindingMessage axisBindingMessage = axisBindingOperation.getFault(
194 (String) msgContext.getProperty(Constants.FAULT_NAME));
195 if(axisBindingMessage != null){
196 Integer code = (Integer) axisBindingMessage
197 .getProperty(WSDL2Constants.ATTR_WHTTP_CODE);
198 if (code != null) {
199 response.setStatus(code.intValue());
200 }
201 }
202 }
203 }
204 handleFault(msgContext, out, new AxisFault(t.toString(), t));
205 } catch (AxisFault e2) {
206 log.info(e2);
207 throw new ServletException(e2);
208 }
209 } finally {
210 closeStaxBuilder(msgContext);
211 TransportUtils.deleteAttachments(msgContext);
212 }
213 } else {
214 if (!disableREST) {
215 new RestRequestProcessor(Constants.Configuration.HTTP_METHOD_POST, request, response)
216 .processXMLRequest();
217 } else {
218 showRestDisabledErrorMessage(response);
219 }
220 }
221 }
222
223 /**
224 * Implementation for GET interface
225 *
226 * @param request
227 * @param response
228 * @throws ServletException
229 * @throws IOException
230 */
231
232 protected void doGet(HttpServletRequest request,
233 HttpServletResponse response) throws ServletException, IOException {
234
235 initContextRoot(request);
236
237 // this method is also used to serve for the listServices request.
238
239 String requestURI = request.getRequestURI();
240 String query = request.getQueryString();
241
242 // There can be three different request coming to this.
243 // 1. wsdl, wsdl2 and xsd requests
244 // 2. list services requests
245 // 3. REST requests.
246 if ((query != null) && new QueryStringParser(query).search(metadataQueryParamNames)) {
247 // handling meta data exchange stuff
248 agent.initTransportListener(request);
249 agent.processListService(request, response);
250 } else if (requestURI.endsWith(".xsd") ||
251 requestURI.endsWith(".wsdl")) {
252 agent.processExplicitSchemaAndWSDL(request, response);
253 } else if (requestURI.endsWith(LIST_SERVICES_SUFFIX) ||
254 requestURI.endsWith(LIST_FAULTY_SERVICES_SUFFIX)) {
255 // handling list services request
256 try {
257 agent.handle(request, response);
258 } catch (Exception e) {
259 throw new ServletException(e);
260 }
261 } else if (!disableREST) {
262 new RestRequestProcessor(Constants.Configuration.HTTP_METHOD_GET, request, response)
263 .processURLRequest();
264 } else {
265 showRestDisabledErrorMessage(response);
266 }
267 }
268
269 /**
270 * Implementation of DELETE interface
271 *
272 * @param request
273 * @param response
274 * @throws ServletException
275 * @throws IOException
276 */
277
278 protected void doDelete(HttpServletRequest request,
279 HttpServletResponse response) throws ServletException, IOException {
280
281 initContextRoot(request);
282 // this method is also used to serve for the listServices request.
283 if (!disableREST) {
284 new RestRequestProcessor(Constants.Configuration.HTTP_METHOD_DELETE, request, response)
285 .processURLRequest();
286 } else {
287 showRestDisabledErrorMessage(response);
288 }
289 }
290
291 /**
292 * Implementation of PUT interface
293 *
294 * @param request
295 * @param response
296 * @throws ServletException
297 * @throws IOException
298 */
299 protected void doPut(HttpServletRequest request,
300 HttpServletResponse response) throws ServletException, IOException {
301
302 initContextRoot(request);
303 // this method is also used to serve for the listServices request.
304 if (!disableREST) {
305 new RestRequestProcessor(Constants.Configuration.HTTP_METHOD_PUT, request, response)
306 .processXMLRequest();
307 } else {
308 showRestDisabledErrorMessage(response);
309 }
310 }
311
312 /**
313 * Private method that deals with disabling of REST support.
314 *
315 * @param response
316 * @throws IOException
317 */
318 protected void showRestDisabledErrorMessage(HttpServletResponse response) throws IOException {
319 PrintWriter writer = new PrintWriter(response.getOutputStream());
320 writer.println("<html><body><h2>Please enable REST support in WEB-INF/conf/axis2.xml " +
321 "and WEB-INF/web.xml</h2></body></html>");
322 writer.flush();
323 response.setStatus(HttpServletResponse.SC_ACCEPTED);
324 }
325
326 /**
327 * Close the builders.
328 *
329 * @param messageContext
330 * @throws ServletException
331 */
332 private void closeStaxBuilder(MessageContext messageContext) throws ServletException {
333 if (closeReader && messageContext != null) {
334 try {
335 SOAPEnvelope envelope = messageContext.getEnvelope();
336 if(envelope != null) {
337 StAXBuilder builder = (StAXBuilder) envelope.getBuilder();
338 if (builder != null) {
339 builder.close();
340 }
341 }
342 } catch (Exception e) {
343 log.debug(e.toString(), e);
344 }
345 }
346 }
347
348 /**
349 * Processing for faults
350 *
351 * @param msgContext
352 * @param res
353 * @param out
354 * @param e
355 */
356 private void processAxisFault(MessageContext msgContext, HttpServletResponse res,
357 OutputStream out, AxisFault e) {
358 try {
359 // If the fault is not going along the back channel we should be 202ing
360 if (AddressingHelper.isFaultRedirected(msgContext)) {
361 res.setStatus(HttpServletResponse.SC_ACCEPTED);
362 } else {
363
364 String status =
365 (String) msgContext.getProperty(Constants.HTTP_RESPONSE_STATE);
366 if (status == null) {
367 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
368 } else {
369 res.setStatus(Integer.parseInt(status));
370 }
371
372 AxisBindingOperation axisBindingOperation =
373 (AxisBindingOperation) msgContext
374 .getProperty(Constants.AXIS_BINDING_OPERATION);
375 if (axisBindingOperation != null) {
376 AxisBindingMessage fault = axisBindingOperation
377 .getFault((String) msgContext.getProperty(Constants.FAULT_NAME));
378 if (fault != null) {
379 Integer code = (Integer) fault.getProperty(WSDL2Constants.ATTR_WHTTP_CODE);
380 if (code != null) {
381 res.setStatus(code.intValue());
382 }
383 }
384 }
385 }
386 handleFault(msgContext, out, e);
387 } catch (AxisFault e2) {
388 log.info(e2);
389 }
390 }
391
392 protected void handleFault(MessageContext msgContext, OutputStream out, AxisFault e)
393 throws AxisFault {
394 msgContext.setProperty(MessageContext.TRANSPORT_OUT, out);
395
396 MessageContext faultContext =
397 MessageContextBuilder.createFaultMessageContext(msgContext, e);
398 // SOAP 1.2 specification mentions that we should send HTTP code 400 in a fault if the
399 // fault code Sender
400 HttpServletResponse response =
401 (HttpServletResponse) msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE);
402 if (response != null) {
403
404 //TODO : Check for SOAP 1.2!
405 SOAPFaultCode code = faultContext.getEnvelope().getBody().getFault().getCode();
406
407 OMElement valueElement = null;
408 if (code != null) {
409 valueElement = code.getFirstChildWithName(new QName(
410 SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI,
411 SOAP12Constants.SOAP_FAULT_VALUE_LOCAL_NAME));
412 }
413
414 if (valueElement != null) {
415 if (SOAP12Constants.FAULT_CODE_SENDER.equals(valueElement.getTextAsQName().getLocalPart())
416 && !msgContext.isDoingREST()) {
417 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
418 }
419 }
420 }
421
422
423 AxisEngine.sendFault(faultContext);
424 }
425
426 /**
427 * Main init method
428 *
429 * @param config
430 * @throws ServletException
431 */
432 public void init(ServletConfig config) throws ServletException {
433
434 // prevent this method from being called more than once per instance
435 initCalled = true;
436 super.init(config);
437 try {
438 this.servletConfig = config;
439 ServletContext servletContext = servletConfig.getServletContext();
440 this.configContext =
441 (ConfigurationContext) servletContext.getAttribute(CONFIGURATION_CONTEXT);
442 if(configContext == null){
443 configContext = initConfigContext(config);
444 config.getServletContext().setAttribute(CONFIGURATION_CONTEXT, configContext);
445 }
446 axisConfiguration = configContext.getAxisConfiguration();
447
448 ListenerManager listenerManager = new ListenerManager();
449 listenerManager.init(configContext);
450 TransportInDescription transportInDescription = new TransportInDescription(
451 Constants.TRANSPORT_HTTP);
452 transportInDescription.setReceiver(this);
453 listenerManager.addListener(transportInDescription, true);
454 listenerManager.start();
455 ListenerManager.defaultConfigurationContext = configContext;
456 agent = new ListingAgent(configContext);
457
458 initParams();
459
460 } catch (Exception e) {
461 throw new ServletException(e);
462 }
463 }
464
465 /**
466 * distroy the ConfigurationContext
467 */
468 public void destroy() {
469 //stoping listner manager
470 try {
471 if (configContext != null) {
472 configContext.terminate();
473 }
474 } catch (AxisFault axisFault) {
475 log.info(axisFault.getMessage());
476 }
477 try {
478 super.destroy();
479 } catch (Exception e) {
480 log.info(e.getMessage());
481 }
482 }
483
484 /**
485 * Initializes the Axis2 parameters.
486 */
487 protected void initParams() {
488 Parameter parameter;
489 // do we need to completely disable REST support
490 parameter = axisConfiguration.getParameter(Constants.Configuration.DISABLE_REST);
491 if (parameter != null) {
492 disableREST = !JavaUtils.isFalseExplicitly(parameter.getValue());
493 }
494
495 // Should we close the reader(s)
496 parameter = axisConfiguration.getParameter("axis2.close.reader");
497 if (parameter != null) {
498 closeReader = JavaUtils.isTrueExplicitly(parameter.getValue());
499 }
500
501 }
502
503 /**
504 * Convenient method to re-initialize the ConfigurationContext
505 *
506 * @throws ServletException
507 */
508 public void init() throws ServletException {
509 if (this.servletConfig != null
510 &&
511 !initCalled) {
512 init(this.servletConfig);
513 }
514 }
515
516 /**
517 * Initialize the Axis configuration context
518 *
519 * @param config Servlet configuration
520 * @return ConfigurationContext
521 * @throws ServletException
522 */
523 protected ConfigurationContext initConfigContext(ServletConfig config) throws ServletException {
524 try {
525 ConfigurationContext configContext =
526 ConfigurationContextFactory
527 .createConfigurationContext(new WarBasedAxisConfigurator(config));
528 configContext.setProperty(Constants.CONTAINER_MANAGED, Constants.VALUE_TRUE);
529 return configContext;
530 } catch (Exception e) {
531 log.info(e);
532 throw new ServletException(e);
533 }
534 }
535
536 /**
537 * Set the context root if it is not set already.
538 *
539 * @param req
540 */
541 public void initContextRoot(HttpServletRequest req) {
542 if (contextRoot != null && contextRoot.trim().length() != 0) {
543 return;
544 }
545 String contextPath = null;
546 // Support older servlet API's
547 try {
548 contextPath = req.getContextPath();
549 } catch (Throwable t) {
550 log.info("Old Servlet API (Fallback to HttpServletRequest.getServletPath) :" + t);
551 contextPath = req.getServletPath();
552 }
553 //handling ROOT scenario, for servlets in the default (root) context, this method returns ""
554 if (contextPath != null && contextPath.length() == 0) {
555 contextPath = "/";
556 }
557 this.contextRoot = contextPath;
558
559 configContext.setContextRoot(contextRoot);
560 }
561
562 /**
563 * Get all transport headers.
564 *
565 * @param req
566 * @return Map
567 */
568 protected Map getTransportHeaders(HttpServletRequest req) {
569 return new TransportHeaders(req);
570 }
571
572
573 public EndpointReference getEPRForService(String serviceName, String ip) throws AxisFault {
574 return getEPRsForService(serviceName, ip)[0];
575 }
576
577 public EndpointReference[] getEPRsForService(String serviceName, String ip) throws AxisFault {
578 //RUNNING_PORT
579 String port = (String) configContext.getProperty(ListingAgent.RUNNING_PORT);
580 if (port == null) {
581 port = "8080";
582 }
583 if (ip == null) {
584 try {
585 ip = Utils.getIpAddress(axisConfiguration);
586 if (ip == null) {
587 ip = "localhost";
588 }
589 } catch (SocketException e) {
590 throw AxisFault.makeFault(e);
591 }
592 }
593
594 String endpointRefernce = "http://" + ip + ":" + port;
595 if (configContext.getServiceContextPath().startsWith("/")) {
596 endpointRefernce = endpointRefernce +
597 configContext.getServiceContextPath() + "/" + serviceName;
598 } else {
599 endpointRefernce = endpointRefernce + '/' +
600 configContext.getServiceContextPath() + "/" + serviceName;
601 }
602 EndpointReference endpoint = new EndpointReference(endpointRefernce + "/");
603
604 return new EndpointReference[]{endpoint};
605 }
606
607 /**
608 * init(); start() and stop() wouldn't do anything.
609 *
610 * @param axisConf
611 * @param transprtIn
612 * @throws AxisFault
613 */
614 public void init(ConfigurationContext axisConf,
615 TransportInDescription transprtIn) throws AxisFault {
616 }
617
618 public void start() throws AxisFault {
619 }
620
621 public void stop() throws AxisFault {
622 }
623
624 /**
625 * @param request
626 * @param response
627 * @param invocationType : If invocationType=true; then this will be used in SOAP message
628 * invocation. If invocationType=false; then this will be used in REST message invocation.
629 * @return MessageContext
630 * @throws IOException
631 */
632 protected MessageContext createMessageContext(HttpServletRequest request,
633 HttpServletResponse response,
634 boolean invocationType) throws IOException {
635 MessageContext msgContext = configContext.createMessageContext();
636 String requestURI = request.getRequestURI();
637
638 String trsPrefix = null;
639 int sepindex = -1;
640 // Support older servlet API's
641 try {
642 trsPrefix = request.getRequestURL().toString();
643 } catch (Throwable t){
644 log.info("Old Servlet API (Fallback to HttpServletRequest.getRequestURI) :" + t);
645 trsPrefix = request.getRequestURI();
646 }
647 sepindex = trsPrefix.indexOf(':');
648 if (sepindex > -1) {
649 trsPrefix = trsPrefix.substring(0, sepindex);
650 msgContext.setIncomingTransportName(trsPrefix);
651 } else {
652 msgContext.setIncomingTransportName(Constants.TRANSPORT_HTTP);
653 trsPrefix = Constants.TRANSPORT_HTTP;
654 }
655 TransportInDescription transportIn =
656 axisConfiguration.getTransportIn(msgContext.getIncomingTransportName());
657 //set the default output description. This will be http
658
659 TransportOutDescription transportOut = axisConfiguration.getTransportOut(trsPrefix);
660 if (transportOut == null) {
661 // if the req coming via https but we do not have a https sender
662 transportOut = axisConfiguration.getTransportOut(Constants.TRANSPORT_HTTP);
663 }
664
665
666 msgContext.setTransportIn(transportIn);
667 msgContext.setTransportOut(transportOut);
668 msgContext.setServerSide(true);
669
670 if (!invocationType) {
671 String query = request.getQueryString();
672 if (query != null) {
673 requestURI = requestURI + "?" + query;
674 }
675 }
676
677 msgContext.setTo(new EndpointReference(requestURI));
678 msgContext.setFrom(new EndpointReference(request.getRemoteAddr()));
679 msgContext.setProperty(MessageContext.REMOTE_ADDR, request.getRemoteAddr());
680 msgContext.setProperty(Constants.OUT_TRANSPORT_INFO,
681 new ServletBasedOutTransportInfo(response));
682 // set the transport Headers
683 msgContext.setProperty(MessageContext.TRANSPORT_HEADERS, getTransportHeaders(request));
684 msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, request);
685 msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, response);
686 try {
687 ServletContext context = getServletContext();
688 if(context != null) {
689 msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETCONTEXT, context);
690 }
691 } catch (Exception e){
692 log.debug(e.getMessage(), e);
693 }
694
695 //setting the RequestResponseTransport object
696 msgContext.setProperty(RequestResponseTransport.TRANSPORT_CONTROL,
697 new ServletRequestResponseTransport(response));
698
699 return msgContext;
700 }
701
702 /**
703 * This method assumes, that the created MessageContext will be used in only SOAP invocation.
704 *
705 * @param req
706 * @param resp
707 * @return MessageContext
708 * @throws IOException
709 */
710
711 protected MessageContext createMessageContext(HttpServletRequest req,
712 HttpServletResponse resp) throws IOException {
713 return createMessageContext(req, resp, true);
714 }
715
716 /**
717 * Transport session management.
718 *
719 * @param messageContext
720 * @return SessionContext
721 */
722 public SessionContext getSessionContext(MessageContext messageContext) {
723 HttpServletRequest req = (HttpServletRequest) messageContext.getProperty(
724 HTTPConstants.MC_HTTP_SERVLETREQUEST);
725 SessionContext sessionContext =
726 (SessionContext) req.getSession(true).getAttribute(
727 Constants.SESSION_CONTEXT_PROPERTY);
728 String sessionId = req.getSession().getId();
729 if (sessionContext == null) {
730 sessionContext = new SessionContext(null);
731 sessionContext.setCookieID(sessionId);
732 req.getSession().setAttribute(Constants.SESSION_CONTEXT_PROPERTY,
733 sessionContext);
734 }
735 messageContext.setSessionContext(sessionContext);
736 messageContext.setProperty(SESSION_ID, sessionId);
737 return sessionContext;
738 }
739
740 protected class ServletRequestResponseTransport implements RequestResponseTransport {
741 private HttpServletResponse response;
742 private boolean responseWritten = false;
743 private CountDownLatch responseReadySignal = new CountDownLatch(1);
744 // The initial status must be WAITING, as the main servlet will do some other
745 // work after setting this RequestResponseTransport up, and we don't want to miss
746 // signals that come in before this thread gets to the awaitResponse call.
747 private RequestResponseTransportStatus status = RequestResponseTransportStatus.WAITING;
748 AxisFault faultToBeThrownOut = null;
749
750 ServletRequestResponseTransport(HttpServletResponse response) {
751 this.response = response;
752 }
753
754 public void acknowledgeMessage(MessageContext msgContext) throws AxisFault {
755 status = RequestResponseTransportStatus.ACKED;
756 responseReadySignal.countDown();
757 }
758
759 public void awaitResponse()
760 throws InterruptedException, AxisFault {
761 log.debug("Blocking servlet thread -- awaiting response");
762 responseReadySignal.await();
763
764 if (faultToBeThrownOut != null) {
765 throw faultToBeThrownOut;
766 }
767 }
768
769 public void signalResponseReady() {
770 log.debug("Signalling response available");
771 status = RequestResponseTransportStatus.SIGNALLED;
772 responseReadySignal.countDown();
773 }
774
775 public RequestResponseTransportStatus getStatus() {
776 return status;
777 }
778
779 public void signalFaultReady(AxisFault fault) {
780 faultToBeThrownOut = fault;
781 signalResponseReady();
782 }
783
784 public boolean isResponseWritten() {
785 return responseWritten;
786 }
787
788 public void setResponseWritten(boolean responseWritten) {
789 this.responseWritten = responseWritten;
790 }
791
792 }
793
794 private void setResponseState(MessageContext messageContext, HttpServletResponse response) {
795 String state = (String) messageContext.getProperty(Constants.HTTP_RESPONSE_STATE);
796 if (state != null) {
797 int stateInt = Integer.parseInt(state);
798 if (stateInt == HttpServletResponse.SC_UNAUTHORIZED) { // Unauthorized
799 String realm = (String) messageContext.getProperty(Constants.HTTP_BASIC_AUTH_REALM);
800 response.addHeader("WWW-Authenticate",
801 "basic realm=\"" + realm + "\"");
802 }
803 }
804 }
805
806 /**
807 * Ues in processing REST related Requests.
808 * This is the helper Class use in processing of doGet, doPut , doDelete and doPost.
809 */
810 protected class RestRequestProcessor {
811 protected MessageContext messageContext;
812 private HttpServletRequest request;
813 private HttpServletResponse response;
814
815 public RestRequestProcessor(String httpMethodString,
816 HttpServletRequest request,
817 HttpServletResponse response) throws IOException {
818 this.request = request;
819 this.response = response;
820 messageContext = createMessageContext(this.request, this.response, false);
821 messageContext.setProperty(org.apache.axis2.transport.http.HTTPConstants.HTTP_METHOD,
822 httpMethodString);
823 }
824
825 public void processXMLRequest() throws IOException, ServletException {
826 try {
827 RESTUtil.processXMLRequest(messageContext, request.getInputStream(),
828 response.getOutputStream(), request.getContentType());
829 this.checkResponseWritten();
830 } catch (AxisFault axisFault) {
831 processFault(axisFault);
832 }
833 closeStaxBuilder(messageContext);
834 }
835
836 public void processURLRequest() throws IOException, ServletException {
837 try {
838 RESTUtil.processURLRequest(messageContext, response.getOutputStream(),
839 request.getContentType());
840 this.checkResponseWritten();
841 } catch (AxisFault e) {
842 setResponseState(messageContext, response);
843 processFault(e);
844 }
845 closeStaxBuilder(messageContext);
846
847 }
848
849 private void checkResponseWritten() {
850 if (!TransportUtils.isResponseWritten(messageContext)) {
851 response.setStatus(HttpServletResponse.SC_ACCEPTED);
852 }
853 }
854
855 private void processFault(AxisFault e) throws ServletException, IOException {
856 log.debug(e);
857 if (messageContext != null) {
858 processAxisFault(messageContext, response, response.getOutputStream(), e);
859 } else {
860 throw new ServletException(e);
861 }
862
863 }
864
865 }
866 }