001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.server.axis2;
017:
018: import org.apache.axiom.om.util.UUIDGenerator;
019: import org.apache.axis2.Constants;
020: import org.apache.axis2.addressing.AddressingHelper;
021: import org.apache.axis2.addressing.EndpointReference;
022: import org.apache.axis2.context.ConfigurationContext;
023: import org.apache.axis2.context.ConfigurationContextFactory;
024: import org.apache.axis2.context.MessageContext;
025: import org.apache.axis2.context.OperationContext;
026: import org.apache.axis2.description.AxisService;
027: import org.apache.axis2.description.TransportInDescription;
028: import org.apache.axis2.description.TransportOutDescription;
029: import org.apache.axis2.engine.AxisEngine;
030: import org.apache.axis2.engine.Handler.InvocationResponse;
031: import org.apache.axis2.jaxws.description.EndpointDescription;
032: import org.apache.axis2.jaxws.description.impl.DescriptionUtils;
033: import org.apache.axis2.jaxws.handler.lifecycle.factory.HandlerLifecycleManagerFactory;
034: import org.apache.axis2.jaxws.registry.FactoryRegistry;
035: import org.apache.axis2.transport.OutTransportInfo;
036: import org.apache.axis2.transport.RequestResponseTransport;
037: import org.apache.axis2.transport.http.HTTPConstants;
038: import org.apache.axis2.transport.http.HTTPTransportReceiver;
039: import org.apache.axis2.transport.http.HTTPTransportUtils;
040: import org.apache.axis2.transport.http.TransportHeaders;
041: import org.apache.axis2.transport.http.util.RESTUtil;
042: import org.apache.axis2.util.MessageContextBuilder;
043: import org.apache.openejb.core.webservices.HandlerResolverImpl;
044: import org.apache.openejb.core.webservices.PortData;
045: import org.apache.openejb.server.axis2.client.Axis2Config;
046: import org.apache.openejb.server.httpd.HttpRequest;
047: import org.apache.openejb.server.httpd.HttpResponse;
048: import org.apache.openejb.server.httpd.HttpListener;
049: import org.apache.openejb.server.webservices.WsConstants;
050: import org.apache.openejb.server.webservices.saaj.SaajUniverse;
051: import org.apache.openejb.util.Logger;
052: import org.apache.openejb.util.LogCategory;
053:
054: import javax.naming.Context;
055: import javax.servlet.ServletContext;
056: import javax.servlet.http.HttpServletRequest;
057: import javax.servlet.http.HttpServletResponse;
058: import javax.xml.ws.handler.Handler;
059: import java.io.PrintWriter;
060: import java.net.HttpURLConnection;
061: import java.net.URL;
062: import java.util.List;
063:
064: public abstract class Axis2WsContainer implements HttpListener {
065: private static final Logger logger = Logger.getInstance(
066: LogCategory.AXIS2, Axis2WsContainer.class);
067:
068: public static final String REQUEST = Axis2WsContainer.class
069: .getName()
070: + "@Request";
071: public static final String RESPONSE = Axis2WsContainer.class
072: .getName()
073: + "@Response";
074:
075: protected String endpointClassName;
076: protected PortData port;
077: protected ConfigurationContext configurationContext;
078: protected final Class<?> endpointClass;
079: protected AxisService service;
080: protected WsdlQueryHandler wsdlQueryHandler;
081: protected Context context;
082: private HandlerResolverImpl handlerResolver;
083:
084: public Axis2WsContainer(PortData port, Class<?> endpointClass,
085: Context context) {
086: this .endpointClass = endpointClass;
087: this .port = port;
088: this .context = context;
089: }
090:
091: public void start() throws Exception {
092: Axis2Config.initialize();
093:
094: configurationContext = ConfigurationContextFactory
095: .createBasicConfigurationContext("META-INF/openejb-axis2.xml");
096:
097: AxisServiceGenerator serviceGen = createServiceGenerator();
098: if (port.getWsdlUrl() != null) {
099: // WSDL file has been provided
100: service = serviceGen
101: .getServiceFromWSDL(port, endpointClass);
102: } else {
103: // No WSDL, let Axis2 handle it.
104: service = serviceGen.getServiceFromClass(endpointClass);
105: }
106:
107: service.setScope(Constants.SCOPE_APPLICATION);
108: configurationContext.getAxisConfiguration().addService(service);
109:
110: wsdlQueryHandler = new WsdlQueryHandler(service);
111:
112: /*
113: * This replaces HandlerLifecycleManagerFactory for all web services.
114: * This should be ok as we do our own handler instance managment and injection.
115: * Also, this does not affect service-ref clients, as we install our own
116: * HandlerResolver.
117: */
118: FactoryRegistry.setFactory(
119: HandlerLifecycleManagerFactory.class,
120: new HandlerLifecycleManagerFactoryImpl());
121: }
122:
123: protected AxisServiceGenerator createServiceGenerator() {
124: return new AxisServiceGenerator();
125: }
126:
127: public void getWsdl(HttpRequest request, HttpResponse response)
128: throws Exception {
129: doService(request, response);
130: }
131:
132: public void onMessage(HttpRequest request, HttpResponse response)
133: throws Exception {
134: SaajUniverse universe = new SaajUniverse();
135: universe.set(SaajUniverse.AXIS2);
136: try {
137: doService(request, response);
138: } finally {
139: universe.unset();
140: }
141: }
142:
143: protected void doService(HttpRequest request, HttpResponse response)
144: throws Exception {
145:
146: if (logger.isDebugEnabled()) {
147: logger.debug("Target URI: " + request.getURI());
148: }
149:
150: MessageContext msgContext = new MessageContext();
151: msgContext.setIncomingTransportName(Constants.TRANSPORT_HTTP);
152: msgContext.setProperty(MessageContext.REMOTE_ADDR, request
153: .getRemoteAddr());
154:
155: try {
156: TransportOutDescription transportOut = this .configurationContext
157: .getAxisConfiguration().getTransportOut(
158: Constants.TRANSPORT_HTTP);
159: TransportInDescription transportIn = this .configurationContext
160: .getAxisConfiguration().getTransportIn(
161: Constants.TRANSPORT_HTTP);
162:
163: msgContext
164: .setConfigurationContext(this .configurationContext);
165:
166: //TODO: Port this segment for session support.
167: // String sessionKey = (String) this.httpcontext.getAttribute(HTTPConstants.COOKIE_STRING);
168: // if (this.configurationContext.getAxisConfiguration().isManageTransportSession()) {
169: // SessionContext sessionContext = this.sessionManager.getSessionContext(sessionKey);
170: // msgContext.setSessionContext(sessionContext);
171: // }
172: msgContext.setTransportIn(transportIn);
173: msgContext.setTransportOut(transportOut);
174: msgContext
175: .setServiceGroupContextId(UUIDGenerator.getUUID());
176: msgContext.setServerSide(true);
177: msgContext.setAxisService(this .service);
178:
179: doService2(request, response, msgContext);
180: } catch (Throwable e) {
181: String msg = "Exception occurred while trying to invoke service method doService()";
182: logger.error(msg, e);
183: try {
184: msgContext.setProperty(MessageContext.TRANSPORT_OUT,
185: response.getOutputStream());
186: msgContext.setProperty(Constants.OUT_TRANSPORT_INFO,
187: new Axis2TransportInfo(response));
188:
189: MessageContext faultContext = MessageContextBuilder
190: .createFaultMessageContext(msgContext, e);
191: // If the fault is not going along the back channel we should be 202ing
192: if (AddressingHelper.isFaultRedirected(msgContext)) {
193: response
194: .setStatusCode(HttpURLConnection.HTTP_ACCEPTED);
195: } else {
196: response
197: .setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR);
198: }
199: AxisEngine.sendFault(faultContext);
200: } catch (Exception ex) {
201: if (AddressingHelper.isFaultRedirected(msgContext)) {
202: response
203: .setStatusCode(HttpURLConnection.HTTP_ACCEPTED);
204: } else {
205: response
206: .setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR);
207: response.setHeader(
208: HTTPConstants.HEADER_CONTENT_TYPE,
209: "text/plain");
210: PrintWriter pw = new PrintWriter(response
211: .getOutputStream());
212: ex.printStackTrace(pw);
213: pw.flush();
214: logger.error(msg, ex);
215: }
216: }
217: }
218:
219: }
220:
221: protected String getServicePath(String contextRoot) {
222: String location = port.getLocation();
223: if (location != null && location.startsWith(contextRoot)) {
224: return location.substring(contextRoot.length());
225: }
226: return null;
227: }
228:
229: public static String trimContext(String contextPath) {
230: if (contextPath != null) {
231: if (contextPath.startsWith("/")) {
232: contextPath = contextPath.substring(1);
233: }
234: if (contextPath.endsWith("/")) {
235: contextPath = contextPath.substring(0, contextPath
236: .length() - 1);
237: }
238: }
239: return contextPath;
240: }
241:
242: public void doService2(HttpRequest request, HttpResponse response,
243: MessageContext msgContext) throws Exception {
244:
245: if (request.getMethod() == HttpRequest.Method.GET) {
246: processGETRequest(request, response, this .service,
247: msgContext);
248: } else if (request.getMethod() == HttpRequest.Method.POST) {
249: processPOSTRequest(request, response, this .service,
250: msgContext);
251: } else {
252: throw new UnsupportedOperationException("["
253: + request.getMethod() + " ] method not supported");
254: }
255:
256: // Finalize response
257: OperationContext operationContext = msgContext
258: .getOperationContext();
259: Object contextWritten = null;
260: Object isTwoChannel = null;
261: if (operationContext != null) {
262: contextWritten = operationContext
263: .getProperty(Constants.RESPONSE_WRITTEN);
264: isTwoChannel = operationContext
265: .getProperty(Constants.DIFFERENT_EPR);
266: }
267:
268: if ((contextWritten != null)
269: && Constants.VALUE_TRUE.equals(contextWritten)) {
270: if ((isTwoChannel != null)
271: && Constants.VALUE_TRUE.equals(isTwoChannel)) {
272: response.setStatusCode(HttpURLConnection.HTTP_ACCEPTED);
273: return;
274: }
275: response.setStatusCode(HttpURLConnection.HTTP_OK);
276: } else {
277: response.setStatusCode(HttpURLConnection.HTTP_ACCEPTED);
278: }
279: }
280:
281: public void destroy() {
282: }
283:
284: public static class Axis2TransportInfo implements OutTransportInfo {
285: private HttpResponse response;
286:
287: public Axis2TransportInfo(HttpResponse response) {
288: this .response = response;
289: }
290:
291: public void setContentType(String contentType) {
292: response.setHeader(HTTPConstants.HEADER_CONTENT_TYPE,
293: contentType);
294: }
295: }
296:
297: protected void processGETRequest(HttpRequest request,
298: HttpResponse response, AxisService service,
299: MessageContext msgContext) throws Exception {
300: if (request.getURI().getQuery() != null
301: && (request.getURI().getQuery().startsWith("wsdl") || request
302: .getURI().getQuery().startsWith("xsd"))) {
303: // wsdl or xsd request
304:
305: if (port.getWsdlUrl() != null) {
306: URL wsdlURL = port.getWsdlUrl();
307: this .wsdlQueryHandler.writeResponse(request.getURI()
308: .toString(), wsdlURL.toString(), response
309: .getOutputStream());
310: } else {
311: service.printWSDL(response.getOutputStream());
312: }
313: } else if (AxisServiceGenerator.isSOAP11(service)) {
314: response.setContentType("text/html");
315: PrintWriter pw = new PrintWriter(response.getOutputStream());
316: pw.write("<html><title>Web Service</title><body>");
317: pw.write("Hi, this is '" + service.getName()
318: + "' web service.");
319: pw.write("</body></html>");
320: pw.flush();
321: } else {
322: // REST request
323: setMsgContextProperties(request, response, service,
324: msgContext);
325:
326: String contentType = request
327: .getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
328:
329: msgContext.setTo(new EndpointReference(request.getURI()
330: .toString()));
331:
332: msgContext.setProperty(MessageContext.TRANSPORT_OUT,
333: response.getOutputStream());
334: msgContext.setProperty(Constants.OUT_TRANSPORT_INFO,
335: new Axis2TransportInfo(response));
336:
337: InvocationResponse processed = RESTUtil
338: .processURLRequest(msgContext, response
339: .getOutputStream(), contentType);
340:
341: if (!processed.equals(InvocationResponse.CONTINUE)) {
342: response.setStatusCode(HttpURLConnection.HTTP_OK);
343: String s = HTTPTransportReceiver
344: .getServicesHTML(configurationContext);
345: PrintWriter pw = new PrintWriter(response
346: .getOutputStream());
347: pw.write(s);
348: pw.flush();
349: }
350: }
351: }
352:
353: protected void setMsgContextProperties(HttpRequest request,
354: HttpResponse response, AxisService service,
355: MessageContext msgContext) {
356: msgContext.setProperty(MessageContext.TRANSPORT_OUT, response
357: .getOutputStream());
358: msgContext.setProperty(Constants.OUT_TRANSPORT_INFO,
359: new Axis2TransportInfo(response));
360: msgContext.setProperty(
361: RequestResponseTransport.TRANSPORT_CONTROL,
362: new Axis2RequestResponseTransport(response));
363: msgContext.setProperty(
364: Constants.Configuration.TRANSPORT_IN_URL, request
365: .getURI().toString());
366: msgContext.setIncomingTransportName(Constants.TRANSPORT_HTTP);
367:
368: HttpServletRequest servletRequest = (HttpServletRequest) request
369: .getAttribute(HttpRequest.SERVLET_REQUEST);
370: msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST,
371: servletRequest);
372:
373: HttpServletResponse servletResponse = (HttpServletResponse) request
374: .getAttribute(HttpRequest.SERVLET_RESPONSE);
375: msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE,
376: servletResponse);
377:
378: ServletContext servletContext = (ServletContext) request
379: .getAttribute(HttpRequest.SERVLET_CONTEXT);
380: msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETCONTEXT,
381: servletContext);
382:
383: if (servletRequest != null) {
384: msgContext.setProperty(MessageContext.TRANSPORT_HEADERS,
385: new TransportHeaders(servletRequest));
386: }
387: }
388:
389: protected void processPOSTRequest(HttpRequest request,
390: HttpResponse response, AxisService service,
391: MessageContext msgContext) throws Exception {
392: String contentType = request
393: .getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
394: String soapAction = request
395: .getHeader(HTTPConstants.HEADER_SOAP_ACTION);
396: if (soapAction == null) {
397: soapAction = "\"\"";
398: }
399:
400: ConfigurationContext configurationContext = msgContext
401: .getConfigurationContext();
402: configurationContext
403: .fillServiceContextAndServiceGroupContext(msgContext);
404:
405: setMsgContextProperties(request, response, service, msgContext);
406:
407: HTTPTransportUtils.processHTTPPostRequest(msgContext, request
408: .getInputStream(), response.getOutputStream(),
409: contentType, soapAction, request.getURI().getPath());
410: }
411:
412: /*
413: * Gets the right handlers for the port/service/bindings and performs injection.
414: */
415: protected void configureHandlers() throws Exception {
416: EndpointDescription desc = AxisServiceGenerator
417: .getEndpointDescription(this .service);
418: if (desc != null) {
419: handlerResolver = new HandlerResolverImpl(port
420: .getHandlerChains(), port.getInjections(), context);
421: List<Handler> handlers = handlerResolver
422: .getHandlerChain(port);
423:
424: DescriptionUtils.registerHandlerHeaders(desc
425: .getAxisService(), handlers);
426: }
427: }
428:
429: protected void destroyHandlers() {
430: if (this.handlerResolver != null) {
431: handlerResolver.destroyHandlers();
432: handlerResolver = null;
433: }
434: }
435: }
|