/* * 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.http; import org.apache.axis2.Constants; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.MessageContext; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.Parameter; import org.apache.axis2.engine.Handler.InvocationResponse; import org.apache.axis2.transport.RequestResponseTransport; import org.apache.axis2.transport.TransportUtils; 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.axis2.transport.http.util.RESTUtil; import org.apache.axis2.util.JavaUtils; 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.ws.commons.schema.XmlSchema; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class HTTPWorker implements Worker { public HTTPWorker() { } 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); InvocationResponse pi; if (method.equals(HTTPConstants.HEADER_GET)) { if (uri.equals("/favicon.ico")) { response.setStatus(HttpStatus.SC_MOVED_PERMANENTLY); response.addHeader(new BasicHeader("Location", "http://ws.apache.org/favicon.ico")); return; } if (!uri.startsWith(contextPath)) { response.setStatus(HttpStatus.SC_MOVED_PERMANENTLY); response.addHeader(new BasicHeader("Location", contextPath)); return; } if (uri.endsWith(contextPath)) { 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)); return; } if (uri.indexOf("?") < 0) { if (!uri.endsWith(contextPath)) { if (HttpUtils.endsWithIgnoreCase(uri , ".xsd") || HttpUtils.endsWithIgnoreCase(uri , ".wsdl")){ HashMap services = configurationContext.getAxisConfiguration().getServices(); String file = uri.substring(uri.lastIndexOf("/") + 1, uri.length()); if ((services != null) && !services.isEmpty()) { Iterator i = services.values().iterator(); while (i.hasNext()) { AxisService service = (AxisService) i.next(); InputStream stream = HTTPTransportUtils.getMetaInfResourceAsStream(service, file); if (stream != null) { OutputStream out = response.getOutputStream(); response.setContentType("text/xml"); ListingAgent.copy(stream, out); out.flush(); out.close(); return; } } } } } } if (HttpUtils.endsWithIgnoreCase(uri , "?wsdl2")) { String serviceName = uri.substring(uri.lastIndexOf("/") + 1, uri.length() - 6); HashMap services = configurationContext.getAxisConfiguration().getServices(); AxisService service = (AxisService) services.get(serviceName); if (service != null) { boolean canExposeServiceMetadata = canExposeServiceMetadata(service); if (canExposeServiceMetadata) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); service.printWSDL2(response.getOutputStream(), getHost(request)); } else { response.setStatus(HttpStatus.SC_FORBIDDEN); } return; } } if (HttpUtils.endsWithIgnoreCase(uri , "?wsdl")) { /** * service name can be hierarchical (axis2/services/foo/1.0.0/Version?wsdl) or * normal (axis2/services/Version?wsdl). */ String[] temp = uri.split(configurationContext.getServiceContextPath() + "/"); String serviceName = temp[1].substring(0, temp[1].length() - 5); HashMap services = configurationContext.getAxisConfiguration().getServices(); AxisService service = (AxisService) services.get(serviceName); if (service != null) { boolean canExposeServiceMetadata = canExposeServiceMetadata(service); if (canExposeServiceMetadata) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); service.printWSDL(response.getOutputStream(), getHost(request)); } else { response.setStatus(HttpStatus.SC_FORBIDDEN); } return; } } if (HttpUtils.endsWithIgnoreCase(uri , "?xsd")) { String serviceName = uri.substring(uri.lastIndexOf("/") + 1, uri.length() - 4); HashMap services = configurationContext.getAxisConfiguration().getServices(); AxisService service = (AxisService) services.get(serviceName); if (service != null) { boolean canExposeServiceMetadata = canExposeServiceMetadata(service); if (canExposeServiceMetadata) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); service.printSchema(response.getOutputStream()); } else { response.setStatus(HttpStatus.SC_FORBIDDEN); } return; } } //cater for named xsds - check for the xsd name if (HttpUtils.indexOfIngnoreCase(uri , "?xsd=") > 0) { // fix for imported schemas String[] uriParts = uri.split("[?]xsd="); String serviceName = uri.substring(uriParts[0].lastIndexOf("/") + 1, uriParts[0].length()); String schemaName = uri.substring(uri.lastIndexOf("=") + 1); HashMap services = configurationContext.getAxisConfiguration().getServices(); AxisService service = (AxisService) services.get(serviceName); if (service != null) { boolean canExposeServiceMetadata = canExposeServiceMetadata(service); if (!canExposeServiceMetadata) { response.setStatus(HttpStatus.SC_FORBIDDEN); return; } //run the population logic just to be sure service.populateSchemaMappings(); //write out the correct schema Map schemaTable = service.getSchemaMappingTable(); XmlSchema schema = (XmlSchema) schemaTable.get(schemaName); if (schema == null) { int dotIndex = schemaName.lastIndexOf('.'); if (dotIndex > 0) { String schemaKey = schemaName.substring(0,dotIndex); schemaKey = schemaKey.replace("./", ""); schema = (XmlSchema) schemaTable.get(schemaKey); } } //schema found - write it to the stream if (schema != null) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); schema.write(response.getOutputStream()); return; } else { InputStream instream = HTTPTransportUtils.getMetaInfResourceAsStream(service, schemaName); if (instream != null) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); OutputStream outstream = response.getOutputStream(); boolean checkLength = true; int length = Integer.MAX_VALUE; int nextValue = instream.read(); if (checkLength) length--; while (-1 != nextValue && length >= 0) { outstream.write(nextValue); nextValue = instream.read(); if (checkLength) length--; } outstream.flush(); return; } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int ret = service.printXSD(baos, schemaName); if(ret>0) { baos.flush(); instream = new ByteArrayInputStream(baos.toByteArray()); response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); OutputStream outstream = response.getOutputStream(); boolean checkLength = true; int length = Integer.MAX_VALUE; int nextValue = instream.read(); if (checkLength) length--; while (-1 != nextValue && length >= 0) { outstream.write(nextValue); nextValue = instream.read(); if (checkLength) length--; } outstream.flush(); return; } // no schema available by that name - send 404 response.sendError(HttpStatus.SC_NOT_FOUND, "Schema Not Found!"); return; } } } } if (HttpUtils.indexOfIngnoreCase(uri , "?wsdl2=") > 0) { String serviceName = uri.substring(uri.lastIndexOf("/") + 1, HttpUtils.lastIndexOfIgnoreCase(uri , "?wsdl2=")); if (processInternalWSDL(uri, configurationContext, serviceName, response, getHost(request))) return; } if (HttpUtils.indexOfIngnoreCase(uri , "?wsdl=") > 0) { String serviceName = uri.substring(uri.lastIndexOf("/") + 1, HttpUtils.lastIndexOfIgnoreCase(uri , "?wsdl=")); if (processInternalWSDL(uri, configurationContext, serviceName, response, getHost(request))) return; } 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); } } // deal with GET request pi = RESTUtil.processURLRequest( msgContext, response.getOutputStream(), contentType); } else if (method.equals(HTTPConstants.HEADER_POST)) { // deal with POST request String contentType = request.getContentType(); if (HTTPTransportUtils.isRESTRequest(contentType)) { pi = RESTUtil.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 = RESTUtil.processXMLRequest( msgContext, request.getInputStream(), response.getOutputStream(), contentType); } else if (method.equals(HTTPConstants.HEADER_DELETE)) { pi = RESTUtil.processURLRequest( msgContext, response.getOutputStream(), null); } else { throw new MethodNotSupportedException(method + " method not supported"); } Boolean holdResponse = (Boolean) msgContext.getProperty(RequestResponseTransport.HOLD_RESPONSE); if (pi.equals(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()); } } // Finalize response RequestResponseTransport requestResponseTransportControl = (RequestResponseTransport) msgContext. getProperty(RequestResponseTransport.TRANSPORT_CONTROL); if (TransportUtils.isResponseWritten(msgContext) || ((requestResponseTransportControl != null) && requestResponseTransportControl.getStatus().equals( RequestResponseTransport.RequestResponseTransportStatus.SIGNALLED))) { // The response is written or signalled. The current status is used (probably SC_OK). } else { // The response may be ack'd, mark the status as accepted. response.setStatus(HttpStatus.SC_ACCEPTED); } } /** * Checks whether exposing the WSDL & WSDL elements such as schema & policy have been allowed * * @param service The AxisService which needs to be verified * @throws IOException If exposing WSDL & WSDL elements has been restricted. * @return true - if service metadata can be exposed, false - otherwise */ private boolean canExposeServiceMetadata(AxisService service) throws IOException { Parameter exposeServiceMetadata = service.getParameter("exposeServiceMetadata"); if (exposeServiceMetadata != null && JavaUtils.isFalseExplicitly(exposeServiceMetadata.getValue())) { return false; } return true; } private boolean processInternalWSDL(String uri, ConfigurationContext configurationContext, String serviceName, AxisHttpResponse response, String ip) throws IOException { String wsdlName = uri.substring(uri.lastIndexOf("=") + 1); HashMap services = configurationContext.getAxisConfiguration().getServices(); AxisService service = (AxisService) services.get(serviceName); if (service != null) { response.setStatus(HttpStatus.SC_OK); response.setContentType("text/xml"); service.printUserWSDL(response.getOutputStream(), wsdlName, ip); response.getOutputStream().flush(); return true; } else { // no schema available by that name - send 404 response.sendError(HttpStatus.SC_NOT_FOUND, "Schema Not Found!"); return true; } } public String getHost(AxisHttpRequest request) throws java.net.SocketException { String host = null; Header hostHeader = request.getFirstHeader("host"); if (hostHeader != null) { String parts[] = hostHeader.getValue().split("[:]"); if (parts.length > 0) { host = parts[0].trim(); } } return host; } }