/* * 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; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; 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 javax.wsdl.extensions.soap.SOAPAddress; import javax.wsdl.extensions.soap12.SOAP12Address; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.axiom.attachments.utils.IOUtils; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.deployment.DeploymentConstants; import org.apache.axis2.description.AxisDescription; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.Parameter; import org.apache.axis2.description.PolicyInclude; import org.apache.axis2.transport.http.ListingAgent; import org.apache.axis2.util.ExternalPolicySerializer; import org.apache.axis2.util.JavaUtils; import org.apache.axis2.wsdl.WSDLConstants; import org.apache.neethi.Policy; import org.apache.neethi.PolicyRegistry; import org.apache.ws.commons.schema.XmlSchema; /** * A Tuscany specific Axis2 ListingAgent as the Axis2 one does not work * with the Tuscany sevice names which include slash ('/') characters. * Unfortunately it ends up having to copy a fair amount of Axis2 code to do this. */ public class TuscanyListingAgent extends ListingAgent { private static final String LIST_SINGLE_SERVICE_JSP_NAME = "listSingleService.jsp"; public TuscanyListingAgent(ConfigurationContext aConfigContext) { super(aConfigContext); } protected String findAxisServiceName(String path) { HashMap services = configContext.getAxisConfiguration().getServices(); if (services == null) { return null; } String[] parts = JavaUtils.split(path, '/'); 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; } @Override public void processListService(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { String filePart = req.getRequestURL().toString(); // String serviceName = filePart.substring(filePart.lastIndexOf("/") + 1, // filePart.length()); // Change the Axis2 code so as to use the complete ServletPath as the service name // this line is the only change to to Axis2 code String serviceName = findAxisServiceName(filePart); setContextRoot(filePart, serviceName); String query = req.getQueryString(); int wsdl2 = query.indexOf("wsdl2"); int wsdl = query.indexOf("wsdl"); int xsd = query.indexOf("xsd"); int policy = query.indexOf("policy"); HashMap services = configContext.getAxisConfiguration().getServices(); if ((services != null) && !services.isEmpty()) { Object serviceObj = services.get(serviceName); if (serviceObj != null) { boolean isHttp = "http".equals(req.getScheme()); if (wsdl2 >= 0) { OutputStream out = res.getOutputStream(); res.setContentType("text/xml"); String ip = extractHostAndPort(filePart, isHttp); // JIRA TUSCANY-1561 Port to Axis2 1.3 // ((AxisService) serviceObj).printWSDL2(out, ip, configContext.getServiceContextPath()); ((AxisService) serviceObj).printWSDL2(out, ip); out.flush(); out.close(); return; } else if (wsdl >= 0) { OutputStream out = res.getOutputStream(); res.setContentType("text/xml"); String ip = extractHostAndPort(filePart, isHttp); patchSOAP12Port((AxisService)serviceObj); // JIRA TUSCANY-1561 Port to Axis2 1.3 // ((AxisService) serviceObj).printWSDL(out, ip, configContext.getServicePath()); ((AxisService) serviceObj).printWSDL(out, ip); out.flush(); out.close(); return; } else if (xsd >= 0) { OutputStream out = res.getOutputStream(); res.setContentType("text/xml"); AxisService axisService = (AxisService) serviceObj; //call the populator axisService.populateSchemaMappings(); Map schemaMappingtable = axisService.getSchemaMappingTable(); ArrayList schemas = axisService.getSchema(); //a name is present - try to pump the requested schema String xsds = req.getParameter("xsd"); if (!"".equals(xsds)) { XmlSchema schema = (XmlSchema) schemaMappingtable.get(xsds); if (schema != null) { //schema is there - pump it outs schema.write(new OutputStreamWriter(out, "UTF8")); out.flush(); out.close(); } else { InputStream in = axisService.getClassLoader() .getResourceAsStream(DeploymentConstants.META_INF + "/" + xsds); if (in != null) { out.write(IOUtils.getStreamAsByteArray(in)); out.flush(); out.close(); } else { res.sendError(HttpServletResponse.SC_NOT_FOUND); } } //multiple schemas are present and the user specified //no name - in this case we cannot possibly pump a schema //so redirect to the service root } else if (schemas.size() > 1) { res.sendRedirect(""); //user specified no name and there is only one schema //so pump that out } else { XmlSchema schema = axisService.getSchema(0); if (schema != null) { schema.write(new OutputStreamWriter(out, "UTF8")); out.flush(); out.close(); } } return; } else if (policy >= 0) { OutputStream out = res.getOutputStream(); ExternalPolicySerializer serializer = new ExternalPolicySerializer(); serializer.setAssertionsToFilter(configContext .getAxisConfiguration().getLocalPolicyAssertions()); // check whether Id is set String idParam = req.getParameter("id"); if (idParam != null) { // Id is set Policy targetPolicy = findPolicy(idParam, (AxisService) serviceObj); if (targetPolicy != null) { XMLStreamWriter writer; try { writer = XMLOutputFactory.newInstance() .createXMLStreamWriter(out); res.setContentType("text/xml"); targetPolicy.serialize(writer); writer.flush(); } catch (XMLStreamException e) { throw new ServletException( "Error occured when serializing the Policy", e); } catch (FactoryConfigurationError e) { throw new ServletException( "Error occured when serializing the Policy", e); } } else { res.setContentType("text/html"); String outStr = "No policy found for id=" + idParam + ""; out.write(outStr.getBytes()); } } else { PolicyInclude policyInclude = ((AxisService) serviceObj).getPolicyInclude(); Policy effecPolicy = policyInclude.getEffectivePolicy(); if (effecPolicy != null) { XMLStreamWriter writer; try { writer = XMLOutputFactory.newInstance() .createXMLStreamWriter(out); res.setContentType("text/xml"); effecPolicy.serialize(writer); writer.flush(); } catch (XMLStreamException e) { throw new ServletException( "Error occured when serializing the Policy", e); } catch (FactoryConfigurationError e) { throw new ServletException( "Error occured when serializing the Policy", e); } } else { res.setContentType("text/html"); String outStr = "No effective policy for " + serviceName + " servcie"; out.write(outStr.getBytes()); } } return; } else { req.getSession().setAttribute(Constants.SINGLE_SERVICE, serviceObj); } } else { req.getSession().setAttribute(Constants.SINGLE_SERVICE, null); } } renderView(LIST_SINGLE_SERVICE_JSP_NAME, req, res); } /** * 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 String extractHostAndPort(String filePart, boolean isHttp) { int ipindex = filePart.indexOf("//"); String ip = null; if (ipindex >= 0) { ip = filePart.substring(ipindex + 2, filePart.length()); int seperatorIndex = ip.indexOf(":"); int slashIndex = ip.indexOf("/"); String port; if (seperatorIndex >= 0) { port = ip.substring(seperatorIndex + 1, slashIndex); ip = ip.substring(0, seperatorIndex); } else { ip = ip.substring(0, slashIndex); port = "80"; } if (isHttp) { configContext.setProperty(RUNNING_PORT, port); } } return ip; } private Policy findPolicy(String id, AxisDescription des) { List policyElements = des.getPolicyInclude().getPolicyElements(); PolicyRegistry registry = des.getPolicyInclude().getPolicyRegistry(); Object policyComponent; Policy policy = registry.lookup(id); if (policy != null) { return policy; } for (Iterator iterator = policyElements.iterator(); iterator.hasNext();) { policyComponent = iterator.next(); if (policyComponent instanceof Policy) { // policy found for the id if (id.equals(((Policy) policyComponent).getId())) { return (Policy) policyComponent; } } } AxisDescription child; for (Iterator iterator = des.getChildren(); iterator.hasNext();) { child = (AxisDescription) iterator.next(); policy = findPolicy(id, child); if (policy != null) { return policy; } } return null; } /** * Hack to get ?wsdl working with soap 1.2 * Fixed in Axis2 1.3 */ private void patchSOAP12Port(AxisService as) throws AxisFault { Parameter wsld4jdefinition = as.getParameter(WSDLConstants.WSDL_4_J_DEFINITION); Definition definition = (Definition) wsld4jdefinition.getValue(); setPortAddress(definition, null, as); } /** * This is a copy of the AxisService setPortAddress patched to work with SOAP 1.2 Addresses * Fixed in Axis2 1.3 */ private void setPortAddress(Definition definition, String requestIP, AxisService axisService) throws AxisFault { Iterator serviceItr = definition.getServices().values().iterator(); while (serviceItr.hasNext()) { Service serviceElement = (Service) serviceItr.next(); Iterator portItr = serviceElement.getPorts().values().iterator(); while (portItr.hasNext()) { Port port = (Port) portItr.next(); List list = port.getExtensibilityElements(); for (int i = 0; i < list.size(); i++) { Object extensibilityEle = list.get(i); String locationURI = null; if (requestIP == null) { locationURI = axisService.getEPRs()[0]; } else { // can't do this as the method's not visible, but Tuscany doesn't use this path anyway // locationURI = axisService.getEPRs(requestIP)[0]); } if (extensibilityEle instanceof SOAPAddress) { ((SOAPAddress) extensibilityEle).setLocationURI(locationURI); } else if (extensibilityEle instanceof SOAP12Address) { ((SOAP12Address) extensibilityEle).setLocationURI(locationURI); } } } } } }