/* * 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.tuscany.sca.binding.ws.axis2.provider; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.wsdl.Definition; import javax.wsdl.Port; import javax.wsdl.Service; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.Parameter; import org.apache.axis2.transport.http.ListingAgent; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaExternal; /** * A Tuscany specific Axis2 ListingAgent as the Axis2 one does not work * with the Tuscany service names which include slash ('/') characters. * Unfortunately it ends up having to copy a fair amount of Axis2 code to do this. * * @version $Rev$ $Date$ */ public class TuscanyListingAgent extends ListingAgent { private static final String LIST_SINGLE_SERVICE_JSP_NAME = "listSingleService.jsp"; public TuscanyListingAgent(ConfigurationContext aConfigContext) { super(aConfigContext); } /** * This method overrides the Axis2 listing agent's computation of the * service name. */ @Override public String extractServiceName(String urlString) { String serviceName = findAxisServiceName(urlString); setContextRoot(urlString, serviceName); return serviceName; } /** * Override ?xsd processing so that WSDL documents with XSD imports * and includes work correctly. When we move to Axis2 1.4, we may * be able to use SchemaSupplier to do this in a cleaner way. Also * ensure that the correct IP address and port are returned by ?wsdl. */ @Override public void processListService(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { String url = req.getRequestURL().toString(); String query = req.getQueryString(); // for ?wsdl requests, need to update the WSDL with correct IPaddr and port int wsdl = query.indexOf("wsdl"); if (wsdl >= 0) { String serviceName = extractServiceName(url); HashMap services = configContext.getAxisConfiguration().getServices(); if ((services != null) && !services.isEmpty()) { AxisService axisService = (AxisService)services.get(serviceName); Parameter wsld4jdefinition = axisService.getParameter("wsdl4jDefinition"); Definition definition = (Definition)wsld4jdefinition.getValue(); for (Object s : definition.getServices().values()) { for (Object p : ((Service)s).getPorts().values()) { String endpointURL = Axis2EngineIntegration.getPortAddress((Port)p); String modifiedURL = setIPAddress(endpointURL, url); modifiedURL = addContextRoot(modifiedURL, serviceName); Axis2EngineIntegration.setPortAddress((Port)p, modifiedURL); } } } } // handle ?xsd requests here int xsd = query.indexOf("xsd"); if (xsd >= 0) { String serviceName = extractServiceName(url); HashMap services = configContext.getAxisConfiguration().getServices(); if ((services != null) && !services.isEmpty()) { Object serviceObj = services.get(serviceName); if (serviceObj != null) { String xsds = req.getParameter("xsd"); if (xsds != null && !"".equals(xsds)) { // a schema name (perhaps with path) is present AxisService axisService = (AxisService)serviceObj; ArrayList schemas = axisService.getSchema(); for (Object rootSchema : axisService.getSchema()) { XmlSchema schema = getSchema(((XmlSchema)rootSchema), xsds); if (schema != null) { // found the schema res.setContentType("text/xml"); OutputStream out = res.getOutputStream(); schema.write(new OutputStreamWriter(out, "UTF8")); out.flush(); out.close(); return; } } } } } } // in all other cases, delegate to the Axis2 code super.processListService(req, res); } private String addContextRoot(String modifiedURL, String serviceName) { if (!"/".equals(configContext.getContextRoot())) { if (modifiedURL.endsWith(serviceName)) { URI uri = URI.create(modifiedURL); if (!uri.getPath().startsWith(configContext.getContextRoot())) { modifiedURL = modifiedURL.substring(0, modifiedURL.length() - serviceName.length()) + configContext.getContextRoot() + serviceName; } } } return modifiedURL; } private XmlSchema getSchema(XmlSchema parentSchema, String name) { for (Iterator iter = parentSchema.getIncludes().getIterator(); iter.hasNext();) { Object obj = iter.next(); if (obj instanceof XmlSchemaExternal) { XmlSchemaExternal extSchema = (XmlSchemaExternal)obj; if (extSchema.getSchemaLocation().endsWith(name)) { return extSchema.getSchema(); } else { XmlSchema schema = getSchema(extSchema.getSchema(), name); if (schema != null) { return schema; } } } } return null; } private String findAxisServiceName(String path) { HashMap services = configContext.getAxisConfiguration().getServices(); if (services == null) { return null; } String[] parts = path.split("/"); String serviceName = ""; for (int i=parts.length-1; i>=0; i--) { serviceName = parts[i] + serviceName; if (services.containsKey(serviceName)) { return serviceName; } serviceName = "/" + serviceName; if (services.containsKey(serviceName)) { return serviceName; } } return null; } /** * Hack for Tuscany to get ?wsdl working with Tuscany service names * Can go once moved up to Axis2 1.3 */ private void setContextRoot(String filePart, String serviceName) { String contextRoot = configContext.getContextRoot(); if (contextRoot != null && contextRoot.length() > 0) { if (contextRoot.equals("/")) { configContext.setServicePath("/"); } else { int i = filePart.indexOf(contextRoot) + contextRoot.length(); int j = filePart.lastIndexOf(serviceName); if (i>=j || (i+1 == j)) { configContext.setServicePath("/"); } else { String mapping = filePart.substring(i+1, j); configContext.setServicePath(mapping); } } configContext.setContextRoot(contextRoot); } } private static String setIPAddress(String wsdlURI, String requestURI) { try { URI wsdlURIObj = new URI(wsdlURI); String wsdlHost = wsdlURIObj.getHost(); int wsdlPort = wsdlURIObj.getPort(); String wsdlAddr = wsdlHost + (wsdlPort != -1 ? ":" + Integer.toString(wsdlPort) : ""); URI requestURIObj = new URI(requestURI); // not in Axis2 1.5.1 // String ipAddr = HttpUtils.getIpAddress(); // int requestPort = requestURIObj.getPort(); // String newAddr = ipAddr + (requestPort != -1 ? ":" + Integer.toString(requestPort) : ""); // return wsdlURI.replace(wsdlAddr, newAddr); return wsdlURI; } catch (Exception e) { // URI string not in expected format, so return the WSDL URI unmodified return wsdlURI; } } }