Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.transport.nhttp; import org.safehaus.asyncweb.http.*; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.OperationContext; import org.apache.axis2.context.SessionContext; import org.apache.axis2.Constants; import org.apache.axis2.AxisFault; import org.apache.axis2.engine.AxisEngine; import org.apache.axis2.transport.http.HTTPTransportUtils; import org.apache.axis2.transport.http.HTTPTransportReceiver; import org.apache.axis2.transport.http.server.SessionManager; import org.apache.axis2.util.UUIDGenerator; import org.apache.axis2.util.threadpool.DefaultThreadFactory; import org.apache.axis2.description.TransportOutDescription; import org.apache.axis2.description.TransportInDescription; import org.apache.axis2.description.AxisService; import org.apache.ws.commons.schema.XmlSchema; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.xml.namespace.QName; import java.io.OutputStreamWriter; import java.io.IOException; import java.io.OutputStream; import java.util.*; import java.net.SocketException; import java.net.NetworkInterface; import java.net.InetAddress; import edu.emory.mathcs.backport.java.util.concurrent.*; public class Axis2AsyncWebProcessor implements HttpService { private static final Log log = LogFactory.getLog(Axis2AsyncWebProcessor.class); private static final String TEXT_PLAIN = "text/plain"; private static final String CONTENT_TYPE = "ContentType"; private static final int WORKERS_MAX_THREADS = 40; private static final long WORKER_KEEP_ALIVE = 100L; private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; private Executor workerPool = null; private SessionManager sessionManager = new SessionManager(); private int port = 8080; private ConfigurationContext configurationContext = null; Axis2AsyncWebProcessor(int port) { this.port = port; // create thread pool of workers workerPool = new ThreadPoolExecutor(1, WORKERS_MAX_THREADS, WORKER_KEEP_ALIVE, TIME_UNIT, new LinkedBlockingQueue(), new DefaultThreadFactory(new ThreadGroup("HTTP Worker thread group"), "HTTPWorker")); } public void setConfigurationContext(ConfigurationContext configurationContext) { this.configurationContext = configurationContext; } public void handleRequest(HttpRequest request) { log.debug("@@@@ Got new Async HTTP request for: " + request.getRequestURI() + " on port : " + port); MessageContext msgContext = new MessageContext(); msgContext.setIncomingTransportName(Constants.TRANSPORT_HTTP); try { TransportOutDescription transportOut = configurationContext.getAxisConfiguration() .getTransportOut(new QName(Constants.TRANSPORT_HTTP)); TransportInDescription transportIn = configurationContext.getAxisConfiguration() .getTransportIn(new QName(Constants.TRANSPORT_HTTP)); msgContext.setConfigurationContext(configurationContext); String sessionKey = request.getSession(true).getId(); if (configurationContext.getAxisConfiguration().isManageTransportSession()) { SessionContext sessionContext = sessionManager.getSessionContext(sessionKey); msgContext.setSessionContext(sessionContext); } msgContext.setTransportIn(transportIn); msgContext.setTransportOut(transportOut); msgContext.setServiceGroupContextId(UUIDGenerator.getUUID()); msgContext.setServerSide(true); msgContext.setProperty(Constants.Configuration.TRANSPORT_IN_URL, request.getRequestURI()); // set the transport Headers Map headerMap = new HashMap(); for (Iterator it = request.getHeaderNames(); it.hasNext();) { String headerName = (String) it.next(); headerMap.put(headerName, request.getHeader(headerName)); } msgContext.setProperty(MessageContext.TRANSPORT_HEADERS, headerMap); msgContext.setProperty(Constants.OUT_TRANSPORT_INFO, request); workerPool.execute(new Worker(msgContext, request)); } catch (AxisFault e) { HttpResponse response = request.createHttpResponse(); try { AxisEngine engine = new AxisEngine(configurationContext); msgContext.setProperty(MessageContext.TRANSPORT_OUT, response.getOutputStream()); msgContext.setProperty(Constants.OUT_TRANSPORT_INFO, response.getOutputStream()); MessageContext faultContext = engine.createFaultMessageContext(msgContext, e); engine.sendFault(faultContext); response.setStatus(ResponseStatus.INTERNAL_SERVER_ERROR); } catch (Exception ex) { response.setStatus(ResponseStatus.INTERNAL_SERVER_ERROR); response.setHeader(CONTENT_TYPE, TEXT_PLAIN); OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); try { out.write(ex.getMessage()); out.close(); } catch (IOException ee) { } } request.commitResponse(response); return; } } public void start() { } public void stop() { } class Worker implements Runnable { private MessageContext msgContext = null; private HttpRequest request = null; private String contextPath = null; private String servicePath = null; private static final String SOAPACTION = "SOAPAction"; private static final String TEXT_HTML = "text/html"; private static final String CONTENT_TYPE = Axis2AsyncWebProcessor.CONTENT_TYPE; private static final String TRANSFER_ENCODING = "Transfer-Encoding"; private static final String CHUNKED = "chunked"; private static final String LOCATION = "Location"; Worker(MessageContext msgContext, HttpRequest request) { this.msgContext = msgContext; this.request = request; contextPath = configurationContext.getContextRoot() + "/"; servicePath = configurationContext.getServiceContextPath(); } public void run() { // TODO handle chunking and correct http versions HttpResponse response = request.createHttpResponse(); if (HttpMethod.GET.equals(request.getMethod())) { processGet(response); } else if (HttpMethod.POST.equals(request.getMethod())) { processPost(response); /*// Finalize response OperationContext operationContext = msgContext.getOperationContext(); Object contextWritten = null; if (operationContext != null) { contextWritten = operationContext.getProperty(Constants.RESPONSE_WRITTEN); } if (!(contextWritten != null && "SKIP".equals(contextWritten))) { if ((contextWritten != null) && Constants.VALUE_TRUE.equals(contextWritten)) { response.setStatus(ResponseStatus.OK); } else { response.setStatus(ResponseStatus.ACCEPTED); } request.commitResponse(response); }*/ } else { handleException("Unsupported method : " + request.getMethod(), null, response); } } private void processGet(HttpResponse response) { String uri = request.getRequestURI(); String serviceName = uri.substring(uri.lastIndexOf("/") + 1); Map parameters = new HashMap(); Iterator iter = request.getParameterNames(); while (iter.hasNext()) { String name = (String) iter.next(); parameters.put(name, request.getParameter(name)); } if (uri.equals("/favicon.ico")) { response.setStatus(ResponseStatus.MOVED_PERMANENTLY); response.addHeader(LOCATION, "http://ws.apache.org/favicon.ico"); } else if (!uri.startsWith(contextPath)) { response.setStatus(ResponseStatus.MOVED_PERMANENTLY); response.addHeader(LOCATION, contextPath); } else if (parameters.containsKey("wsdl")) { AxisService service = (AxisService) configurationContext.getAxisConfiguration().getServices() .get(serviceName); if (service != null) { try { service.printWSDL(response.getOutputStream(), getIpAddress(), servicePath); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } catch (AxisFault e) { handleException("Axis2 fault writing ?wsdl output", e, response); return; } catch (SocketException e) { handleException("Error getting ip address for ?wsdl output", e, response); return; } } } else if (parameters.containsKey("wsdl2")) { AxisService service = (AxisService) configurationContext.getAxisConfiguration().getServices() .get(serviceName); if (service != null) { try { service.printWSDL2(response.getOutputStream(), getIpAddress(), servicePath); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } catch (AxisFault e) { handleException("Axis2 fault writing ?wsdl2 output", e, response); return; } catch (SocketException e) { handleException("Error getting ip address for ?wsdl2 output", e, response); return; } } } else if (parameters.containsKey("xsd")) { if (parameters.get("xsd") == null || "".equals(parameters.get("xsd"))) { AxisService service = (AxisService) configurationContext.getAxisConfiguration().getServices() .get(serviceName); if (service != null) { try { service.printSchema(response.getOutputStream()); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } catch (AxisFault axisFault) { handleException("Error writing ?xsd output to client", axisFault, response); return; } } } else { //cater for named xsds - check for the xsd name String schemaName = (String) parameters.get("xsd"); AxisService service = (AxisService) configurationContext.getAxisConfiguration().getServices() .get(serviceName); if (service != null) { //run the population logic just to be sure service.populateSchemaMappings(); //write out the correct schema Map schemaTable = service.getSchemaMappingTable(); final XmlSchema schema = (XmlSchema) schemaTable.get(schemaName); //schema found - write it to the stream if (schema != null) { schema.write(response.getOutputStream()); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } else { // no schema available by that name - send 404 response.setStatus(ResponseStatus.NOT_FOUND, "Schema Not Found"); } } } } else if (parameters.isEmpty()) { // request is for a service over GET without params, send service HTML if (!(uri.endsWith(contextPath) || uri.endsWith(contextPath + "/"))) { OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); try { out.write(HTTPTransportReceiver.printServiceHTML(serviceName, configurationContext)); out.close(); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } catch (IOException e) { handleException("Error writing service HTML to client", e, response); return; } } else { processAxisGet(response, parameters); } } request.commitResponse(response); } public void processPost(HttpResponse response) { try { HTTPTransportUtils.processHTTPPostRequest(msgContext, request.getInputStream(), response.getOutputStream(), request.getHeader(CONTENT_TYPE), request.getHeader(SOAPACTION), request.getRequestURI()); } catch (AxisFault e) { handleException("Error processing POST request ", e, response); } } private void processAxisGet(HttpResponse response, Map parameters) { try { // deal with GET request boolean processed = HTTPTransportUtils.processHTTPGetRequest(msgContext, response.getOutputStream(), request.getHeader(SOAPACTION), request.getRequestURI(), configurationContext, parameters); if (!processed) { OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); try { out.write(HTTPTransportReceiver.getServicesHTML(configurationContext)); out.flush(); response.setHeader(CONTENT_TYPE, TEXT_HTML); response.setStatus(ResponseStatus.OK); } catch (IOException e) { handleException("Error writing ? output to client", e, response); } } } catch (AxisFault e) { handleException("Axis fault while serving GET request", e, response); } } private void handleException(String msg, Exception e, HttpResponse response) { log.error(msg, e); try { AxisEngine engine = new AxisEngine(configurationContext); msgContext.setProperty(MessageContext.TRANSPORT_OUT, response.getOutputStream()); msgContext.setProperty(Constants.OUT_TRANSPORT_INFO, response.getOutputStream()); MessageContext faultContext = engine.createFaultMessageContext(msgContext, e); engine.sendFault(faultContext); } catch (Exception ex) { response.setHeader(CONTENT_TYPE, TEXT_PLAIN); OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); try { out.write(ex.getMessage()); out.close(); } catch (IOException ee) { } } finally { response.setStatus(ResponseStatus.INTERNAL_SERVER_ERROR); request.commitResponse(response); } } } /** * Copied from transport.http of Axis2 * * Returns the ip address to be used for the replyto epr * CAUTION: * This will go through all the available network interfaces and will try to return an ip address. * First this will try to get the first IP which is not loopback address (127.0.0.1). If none is found * then this will return this will return 127.0.0.1. * This will <b>not<b> consider IPv6 addresses. * <p/> * TODO: * - Improve this logic to genaralize it a bit more * - Obtain the ip to be used here from the Call API * * @return Returns String. * @throws SocketException */ private static String getIpAddress() throws SocketException { Enumeration e = NetworkInterface.getNetworkInterfaces(); String address = "127.0.0.1"; while (e.hasMoreElements()) { NetworkInterface netface = (NetworkInterface) e.nextElement(); Enumeration addresses = netface.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress ip = (InetAddress) addresses.nextElement(); if (!ip.isLoopbackAddress() && isIP(ip.getHostAddress())) { return ip.getHostAddress(); } } } return address; } private static boolean isIP(String hostAddress) { return hostAddress.split("[.]").length == 4; } }