Java tutorial
/* * Author: Chris Grzegorczyk grze@cs.ucsb.edu * Author: Sunil Soman sunils@cs.ucsb.edu */ package edu.ucsb.eucalyptus.transport.http; import edu.ucsb.eucalyptus.util.Messaging; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.builder.BuilderUtil; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.MessageContext; import org.apache.axis2.engine.AxisEngine; import org.apache.axis2.engine.Handler; import org.apache.axis2.transport.RequestResponseTransport; import org.apache.axis2.transport.TransportUtils; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.axis2.transport.http.HTTPTransportReceiver; import org.apache.axis2.transport.http.HTTPTransportUtils; import org.apache.axis2.transport.http.server.AxisHttpRequest; import org.apache.axis2.transport.http.server.AxisHttpResponse; import org.apache.axis2.transport.http.server.HttpUtils; import org.apache.axis2.transport.http.server.Worker; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpStatus; import org.apache.http.MethodNotSupportedException; import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HTTP; import org.apache.http.util.EncodingUtils; import org.apache.log4j.Logger; import org.mule.transport.NullPayload; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /******************************************************************************* * Copyright (c) 2009 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, only version 3 of the License. * * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. * * Please contact Eucalyptus Systems, Inc., 130 Castilian * Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> * if you need additional information or have any questions. * * This file may incorporate work covered under the following copyright and * permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF * THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE * LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS * SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA * BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN * THE REGENTS DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT * OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR * WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH * ANY SUCH LICENSES OR RIGHTS. ******************************************************************************/ public class Axis2HttpWorker implements Worker { private static Logger LOG = Logger.getLogger(Axis2HttpWorker.class); public static String REAL_HTTP_REQUEST = "HAI_IS_REAL_HTTP_REQUEST"; public static String REAL_HTTP_RESPONSE = "YHALO_I_ARE_TEH_HTTP_RESPONSE"; public static String HTTP_STATUS = "IS_IT_CAN_BE_HTTP_STATUS"; public Axis2HttpWorker() { } public void service(final AxisHttpRequest request, final AxisHttpResponse response, final MessageContext msgContext) throws HttpException, IOException { ConfigurationContext configurationContext = msgContext.getConfigurationContext(); final String servicePath = configurationContext.getServiceContextPath(); final String contextPath = (servicePath.startsWith("/") ? servicePath : "/" + servicePath) + "/"; String uri = request.getRequestURI(); String method = request.getMethod(); String soapAction = HttpUtils.getSoapAction(request); Handler.InvocationResponse pi = null; msgContext.setProperty(REAL_HTTP_REQUEST, request); msgContext.setProperty(REAL_HTTP_RESPONSE, response); Header[] headers = request.getHeaders(HTTP.CONTENT_LEN); if (headers != null && headers.length > 0) { String contentLength = headers[0].getValue(); msgContext.setProperty(HTTP.CONTENT_LEN, contentLength); } if (method.equals(HTTPConstants.HEADER_GET)) { if ((uri.startsWith("/latest/") || uri.matches("/\\d\\d\\d\\d-\\d\\d-\\d\\d/.*")) && handleMetaData(response, msgContext, uri)) return; if (!uri.startsWith(contextPath)) { response.setStatus(HttpStatus.SC_MOVED_PERMANENTLY); response.addHeader(new BasicHeader("Location", (contextPath + uri).replaceAll("//", "/"))); return; } if (uri.endsWith("services/")) { handleServicesList(response, configurationContext); return; } if (uri.endsWith("?wsdl")) { handleWSDL(response); return; } pi = handleGet(request, response, msgContext); } else if (method.equals(HTTPConstants.HEADER_POST)) { String contentType = request.getContentType(); if (HTTPTransportUtils.isRESTRequest(contentType)) pi = Axis2HttpWorker.processXMLRequest(msgContext, request.getInputStream(), response.getOutputStream(), contentType); else { String ip = (String) msgContext.getProperty(MessageContext.TRANSPORT_ADDR); if (ip != null) uri = ip + uri; pi = HTTPTransportUtils.processHTTPPostRequest(msgContext, request.getInputStream(), response.getOutputStream(), contentType, soapAction, uri); } } else if (method.equals(HTTPConstants.HEADER_PUT)) { String contentType = request.getContentType(); msgContext.setProperty(Constants.Configuration.CONTENT_TYPE, contentType); pi = Axis2HttpWorker.processXMLRequest(msgContext, request.getInputStream(), response.getOutputStream(), contentType); } else if (method.equals(HTTPConstants.HEADER_DELETE)) pi = Axis2HttpWorker.processURLRequest(msgContext, response.getOutputStream(), null); else if (method.equals("HEAD")) pi = Axis2HttpWorker.processURLRequest(msgContext, response.getOutputStream(), null); else throw new MethodNotSupportedException(method + " method not supported"); Boolean holdResponse = (Boolean) msgContext.getProperty(RequestResponseTransport.HOLD_RESPONSE); if (pi.equals(Handler.InvocationResponse.SUSPEND) || (holdResponse != null && Boolean.TRUE.equals(holdResponse))) try { ((RequestResponseTransport) msgContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL)) .awaitResponse(); } catch (InterruptedException e) { throw new IOException("We were interrupted, so this may not function correctly:" + e.getMessage()); } RequestResponseTransport requestResponseTransportControl = (RequestResponseTransport) msgContext .getProperty(RequestResponseTransport.TRANSPORT_CONTROL); if (TransportUtils.isResponseWritten(msgContext) || ((requestResponseTransportControl != null) && requestResponseTransportControl.getStatus() .equals(RequestResponseTransport.RequestResponseTransportStatus.SIGNALLED))) ; else response.setStatus(HttpStatus.SC_ACCEPTED); Integer status = (Integer) msgContext.getProperty(HTTP_STATUS); if (status != null) response.setStatus(status); } private void handleServicesList(final AxisHttpResponse response, final ConfigurationContext configurationContext) throws IOException { String s = HTTPTransportReceiver.getServicesHTML(configurationContext); response.setStatus(HttpStatus.SC_OK); response.setContentType("text/html"); OutputStream out = response.getOutputStream(); out.write(EncodingUtils.getBytes(s, HTTP.ISO_8859_1)); } private void handleWSDL(final AxisHttpResponse response) throws IOException { String s = "A sensible response."; response.setStatus(HttpStatus.SC_OK); response.setContentType("text/html"); OutputStream out = response.getOutputStream(); out.write(EncodingUtils.getBytes(s, HTTP.ISO_8859_1)); } private boolean handleMetaData(final AxisHttpResponse response, final MessageContext msgContext, final String uri) { try { String newUri = null; if (uri.startsWith("/latest/")) newUri = uri.replaceAll("/latest/", msgContext.getProperty(MessageContext.REMOTE_ADDR) + ":"); else newUri = uri.replaceAll("/\\d\\d\\d\\d-\\d\\d-\\d\\d/", msgContext.getProperty(MessageContext.REMOTE_ADDR) + ":"); LOG.debug("Metadata request: " + newUri); Object reply = Messaging.send("vm://VmMetadata", newUri); if (!(reply instanceof NullPayload)) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/html"); OutputStream out = response.getOutputStream(); out.write(EncodingUtils.getBytes(((String) reply), HTTP.ISO_8859_1)); } else response.setStatus(HttpStatus.SC_NOT_FOUND); return true; } catch (Exception e) { LOG.error(e, e); } return false; } private Handler.InvocationResponse handleGet(final AxisHttpRequest request, final AxisHttpResponse response, final MessageContext msgContext) throws AxisFault { Handler.InvocationResponse pi; String contentType = null; Header[] headers = request.getHeaders(HTTPConstants.HEADER_CONTENT_TYPE); if (headers != null && headers.length > 0) { contentType = headers[0].getValue(); int index = contentType.indexOf(';'); if (index > 0) { contentType = contentType.substring(0, index); } } pi = Axis2HttpWorker.processURLRequest(msgContext, response.getOutputStream(), contentType); return pi; } public static Handler.InvocationResponse processURLRequest(MessageContext msgContext, OutputStream out, String contentType) throws AxisFault { try { if (contentType == null || "".equals(contentType)) { contentType = HTTPConstants.MEDIA_TYPE_X_WWW_FORM; } msgContext.setDoingREST(true); msgContext.setProperty(MessageContext.TRANSPORT_OUT, out); String charSetEncoding = BuilderUtil.getCharSetEncoding(contentType); msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEncoding); SOAPEnvelope soapEnvelope = TransportUtils.createSOAPMessage(msgContext, null, contentType); msgContext.setEnvelope(soapEnvelope); } catch (Exception e) { throw e instanceof AxisFault ? (AxisFault) e : AxisFault.makeFault(e); } finally { String messageType = (String) msgContext.getProperty(Constants.Configuration.MESSAGE_TYPE); if (HTTPConstants.MEDIA_TYPE_X_WWW_FORM.equals(messageType) || HTTPConstants.MEDIA_TYPE_MULTIPART_FORM_DATA.equals(messageType)) msgContext.setProperty(Constants.Configuration.MESSAGE_TYPE, HTTPConstants.MEDIA_TYPE_APPLICATION_XML); } AxisEngine axisEngine = new AxisEngine(msgContext.getConfigurationContext()); return axisEngine.receive(msgContext); } public static Handler.InvocationResponse processXMLRequest(MessageContext msgContext, InputStream in, OutputStream out, String contentType) throws AxisFault { try { msgContext.setDoingREST(true); String charSetEncoding = BuilderUtil.getCharSetEncoding(contentType); msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEncoding); SOAPFactory soapFactory = new SOAP11Factory(); SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope(); msgContext.setEnvelope(soapEnvelope); in = HTTPTransportUtils.handleGZip(msgContext, in); msgContext.setProperty(Constants.Configuration.CONTENT_TYPE, contentType); msgContext.setProperty(MessageContext.TRANSPORT_OUT, out); msgContext.setProperty(MessageContext.TRANSPORT_IN, in); } catch (Exception e) { throw e instanceof AxisFault ? (AxisFault) e : AxisFault.makeFault(e); } finally { String messageType = (String) msgContext.getProperty(Constants.Configuration.MESSAGE_TYPE); if (HTTPConstants.MEDIA_TYPE_X_WWW_FORM.equals(messageType) || HTTPConstants.MEDIA_TYPE_MULTIPART_FORM_DATA.equals(messageType)) msgContext.setProperty(Constants.Configuration.MESSAGE_TYPE, HTTPConstants.MEDIA_TYPE_APPLICATION_XML); } AxisEngine axisEngine = new AxisEngine(msgContext.getConfigurationContext()); return axisEngine.receive(msgContext); } }