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