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