/* * JBoss, Home of Professional Open Source * Copyright 2008-11, Red Hat Middleware LLC, and others contributors as indicated * by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.savara.switchyard.java.generator; import java.util.logging.Level; import java.util.logging.Logger; import javax.wsdl.PortType; import javax.xml.namespace.QName; import org.savara.common.resources.DefaultResourceLocator; import org.savara.common.resources.ResourceLocator; import org.savara.java.generator.JavaBehaviourGenerator; import org.savara.java.generator.util.JavaGeneratorUtil; import org.scribble.protocol.model.ProtocolModel; import org.scribble.protocol.model.Role; public class SwitchyardJavaGenerator extends org.savara.java.generator.JavaServiceGenerator { private static final Logger logger=Logger.getLogger(SwitchyardJavaGenerator.class.getName()); public static void main(String[] args) { SwitchyardJavaGenerator gen=new SwitchyardJavaGenerator(); if (args.length != 3) { System.err.println("Usage: SwitchyardJavaGenerator WSDLPath RelativeWSDLLocation DestinationFolder"); } try { gen.createServiceInterfaceFromWSDL(args[0], args[1], args[2]); } catch(Exception e) { e.printStackTrace(); } } public SwitchyardJavaGenerator() { } /** * {@inheritDoc} */ @Override public void createServiceInterfaceFromWSDL(String wsdlPath, String wsdlLocation, String srcFolder) throws Exception { super.createServiceInterfaceFromWSDL(wsdlPath, wsdlLocation, srcFolder); removeWebServiceAndClientAnnotations(wsdlPath, srcFolder); } /** * {@inheritDoc} */ @Override public void createServiceImplementationFromWSDL(Role role, java.util.List<Role> refRoles, ProtocolModel behaviour, String wsdlPath, String wsdlLocation, java.util.List<String> refWsdlPaths, String srcFolder, ResourceLocator locator) throws Exception { super.createServiceImplementationFromWSDL(role, refRoles, behaviour, wsdlPath, wsdlLocation, refWsdlPaths, srcFolder, locator); // Process the service implementation class javax.wsdl.Definition defn=getWSDLReader().readWSDL(wsdlPath); if (defn != null) { // Use the namespace to obtain a Java package String pack=JavaGeneratorUtil.getJavaPackage(defn.getTargetNamespace()); String folder=pack.replace('.', java.io.File.separatorChar); @SuppressWarnings("unchecked") java.util.Iterator<PortType> portTypes=defn.getPortTypes().values().iterator(); while (portTypes.hasNext()) { PortType portType=portTypes.next(); java.io.File f=new java.io.File(srcFolder+java.io.File.separatorChar+ folder+java.io.File.separatorChar+portType.getQName().getLocalPart()+"Impl.java"); if (f.exists()) { makeSwitchyardService(f, portType, srcFolder); addServiceReferencesToImplementation(f, role, refRoles, refWsdlPaths, srcFolder); addServiceBehaviour(f, role, refRoles, behaviour, srcFolder, locator); } else { logger.severe("Service file '"+f.getAbsolutePath()+"' does not exist"); } } removeWebServiceAndClientAnnotations(wsdlPath, srcFolder); } else { logger.severe("Failed to retrieve WSDL definition '"+wsdlPath+"'"); } } protected void makeSwitchyardService(java.io.File implFile, PortType portType, String srcFolder) throws Exception { java.io.FileInputStream fis=new java.io.FileInputStream(implFile); byte[] b=new byte[fis.available()]; fis.read(b); StringBuffer text=new StringBuffer(); text.append(new String(b)); fis.close(); int startindex=text.indexOf("import"); int endindex=text.indexOf("public class"); if (startindex != -1 && endindex != -1) { text.replace(startindex, endindex, "import java.util.logging.Logger;\r\n\r\n" + "@org.switchyard.component.bean.Service("+ portType.getQName().getLocalPart()+".class)\r\n"); java.io.FileOutputStream fos=new java.io.FileOutputStream(implFile); fos.write(text.toString().getBytes()); fos.close(); } else { logger.severe("Service file '"+implFile.getAbsolutePath()+ "' could not change to switchyard Service annotation"); } } protected void addServiceReferencesToImplementation(java.io.File implFile, Role role, java.util.List<Role> refRoles, java.util.List<String> refWsdlPaths, String srcFolder) throws Exception { // Check that the number of reference roles and wsdl paths are the same if (refRoles.size() != refWsdlPaths.size()) { throw new IllegalArgumentException("The number of reference roles and wsdl paths are not consistent"); } java.io.FileInputStream fis=new java.io.FileInputStream(implFile); byte[] b=new byte[fis.available()]; fis.read(b); StringBuffer text=new StringBuffer(); text.append(new String(b)); fis.close(); int index=text.indexOf("private static final Logger"); if (index != -1) { for (int i=0; i < refRoles.size(); i++) { javax.wsdl.Definition refDefn=getWSDLReader().readWSDL(refWsdlPaths.get(i)); if (refDefn != null) { // Use the namespace to obtain a Java package String refPack=JavaGeneratorUtil.getJavaPackage(refDefn.getTargetNamespace()); @SuppressWarnings("unchecked") java.util.Iterator<PortType> refPortTypes=refDefn.getPortTypes().values().iterator(); int refPortCount=1; while (refPortTypes.hasNext()) { PortType refPortType=refPortTypes.next(); String name=JavaBehaviourGenerator.getVariableName(refRoles.get(i).getName()); if (refDefn.getPortTypes().size() > 1) { name += refPortCount; } text.insert(index, "@javax.inject.Inject @org.switchyard.component.bean.Reference\r\n "+ refPack+"."+refPortType.getQName().getLocalPart()+" _"+ name+";\r\n\r\n "); } } } java.io.FileOutputStream fos=new java.io.FileOutputStream(implFile); fos.write(text.toString().getBytes()); fos.close(); } else { logger.severe("Service implementation file '"+implFile.getAbsolutePath()+ "' does not have 'private static final Logger' as location to insert references"); } } public void createServiceComposite(Role role, java.util.List<Role> refRoles, String wsdlPath, java.util.List<String> refWsdlPaths, String resourceFolder, String srcFolder) throws Exception { javax.wsdl.Definition defn=getWSDLReader().readWSDL(wsdlPath); if (defn != null) { java.io.File wsdlFile=new java.io.File(wsdlPath); if (!wsdlFile.exists()) { java.net.URL url=ClassLoader.getSystemResource(wsdlPath); wsdlFile = new java.io.File(url.getFile()); if (!wsdlFile.exists()) { logger.severe("Failed to find WSDL file '"+wsdlPath+"'"); } } ResourceLocator locator=new DefaultResourceLocator(wsdlFile.getParentFile()); StringBuffer composite=new StringBuffer(); StringBuffer transformers=new StringBuffer(); StringBuffer component=new StringBuffer(); String targetNamespace=defn.getTargetNamespace(); String name=role.getName(); composite.append("<switchyard xmlns=\"urn:switchyard-config:switchyard:1.0\"\r\n"); // TODO: May need to add other namespaces here composite.append("\t\ttargetNamespace=\""+targetNamespace+"\"\r\n"); composite.append("\t\tname=\""+name+"\">\r\n"); composite.append("\t<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\"\r\n"); composite.append("\t\t\ttargetNamespace=\""); composite.append(targetNamespace); composite.append("\"\r\n\t\t\tname=\""); composite.append(name); composite.append("\" >\r\n"); @SuppressWarnings("unchecked") java.util.Iterator<PortType> portTypes=defn.getPortTypes().values().iterator(); while (portTypes.hasNext()) { PortType portType=portTypes.next(); // Define transformers addPortTypeTransformers(portType, true, transformers, defn, locator, srcFolder); String wsdlName=wsdlPath; int ind=wsdlName.lastIndexOf('/'); String wsdlLocation=wsdlName; if (ind != -1) { wsdlLocation = wsdlName.substring(ind+1); wsdlName = wsdlName.substring(ind+1) +"#wsdl.porttype("+portType.getQName().getLocalPart()+")"; } composite.append("\t\t<service name=\""+portType.getQName().getLocalPart()+ "\" promote=\""+portType.getQName().getLocalPart()+"Component/" +portType.getQName().getLocalPart()+"\">\r\n"); composite.append("\t\t\t<interface.wsdl interface=\"wsdl/" +wsdlName+"\" />\r\n"); composite.append("\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\">\r\n"); composite.append("\t\t\t\t<wsdl>wsdl/"+wsdlLocation+"</wsdl>\r\n"); composite.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n"); composite.append("\t\t\t</binding.soap>\r\n"); composite.append("\t\t</service>\r\n"); String pack=JavaGeneratorUtil.getJavaPackage(defn.getTargetNamespace()); component.append("\t\t<component name=\""+portType.getQName().getLocalPart()+"Component\">\r\n"); component.append("\t\t\t<implementation.bean xmlns=\"urn:switchyard-component-bean:config:1.0\" " + "class=\""+pack+"."+portType.getQName().getLocalPart()+"Impl\"/>\r\n"); component.append("\t\t\t<service name=\""+portType.getQName().getLocalPart()+"\" >\r\n"); component.append("\t\t\t\t<interface.java interface=\""+pack+"." +portType.getQName().getLocalPart()+"\"/>\r\n"); component.append("\t\t\t</service>\r\n"); for (int i=0; i < refWsdlPaths.size(); i++){ String refWsdlPath=refWsdlPaths.get(i); javax.wsdl.Definition refDefn=getWSDLReader().readWSDL(refWsdlPath); java.io.File refWsdlFile=new java.io.File(refWsdlPath); if (!refWsdlFile.exists()) { java.net.URL url=ClassLoader.getSystemResource(refWsdlPath); refWsdlFile = new java.io.File(url.getFile()); if (!refWsdlFile.exists()) { logger.severe("Failed to find ref WSDL file '"+refWsdlPath+"'"); } } ResourceLocator refLocator=new DefaultResourceLocator(refWsdlFile.getParentFile()); if (refDefn != null) { @SuppressWarnings("unchecked") java.util.Iterator<PortType> refPortTypes=refDefn.getPortTypes().values().iterator(); while (refPortTypes.hasNext()) { PortType refPortType=refPortTypes.next(); // Define transformers addPortTypeTransformers(refPortType, false, transformers, refDefn, refLocator, srcFolder); String refWsdlName=refWsdlPath; wsdlLocation=refWsdlName; ind = refWsdlName.lastIndexOf('/'); if (ind != -1) { wsdlLocation = refWsdlName.substring(ind+1); refWsdlName = refWsdlName.substring(ind+1) +"#wsdl.porttype("+refPortType.getQName().getLocalPart()+")"; } composite.append("\t\t<reference name=\""+refPortType.getQName().getLocalPart()+ "\" promote=\""+portType.getQName().getLocalPart()+"Component/" +refPortType.getQName().getLocalPart()+"\" multiplicity=\"1..1\" >\r\n"); composite.append("\t\t\t<interface.wsdl interface=\"wsdl/" +refWsdlName+"\" />\r\n"); composite.append("\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\">\r\n"); composite.append("\t\t\t\t<wsdl>wsdl/"+wsdlLocation+"</wsdl>\r\n"); composite.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n"); composite.append("\t\t\t</binding.soap>\r\n"); composite.append("\t\t</reference>\r\n"); String refPack=JavaGeneratorUtil.getJavaPackage(refDefn.getTargetNamespace()); component.append("\t\t\t<reference name=\""+refPortType.getQName().getLocalPart()+"\" >\r\n"); component.append("\t\t\t\t<interface.java interface=\""+refPack+"." +refPortType.getQName().getLocalPart()+"\"/>\r\n"); component.append("\t\t\t</reference>\r\n"); } } } component.append("\t\t</component>\r\n"); composite.append(component.toString()); } composite.append("\t</composite>\r\n"); if (transformers.length() > 0) { composite.append("\t<transforms xmlns:xform=\"urn:switchyard-config:transform:1.0\">\r\n"); composite.append(transformers.toString()); composite.append("\t</transforms>\r\n"); } composite.append("</switchyard>\r\n"); java.io.FileOutputStream fos=new java.io.FileOutputStream(resourceFolder+ java.io.File.separatorChar+"switchyard.xml"); fos.write(composite.toString().getBytes()); fos.close(); } } protected void addPortTypeTransformers(PortType portType, boolean provider, StringBuffer transformers, javax.wsdl.Definition wsdl, ResourceLocator locator, String srcFolder) { String attr1=(provider ? "from" : "to"); String attr2=(provider ? "to" : "from"); for (Object opobj : portType.getOperations()) { if (opobj instanceof javax.wsdl.Operation) { javax.wsdl.Operation op=(javax.wsdl.Operation)opobj; String qname=""; String javaType=""; String javaPackage=""; javax.wsdl.Part p=(javax.wsdl.Part)op.getInput().getMessage(). getParts().values().iterator().next(); qname = p.getElementName().toString(); javaType = getJavaType(wsdl, p.getElementName(), locator); if (javaType != null) { int ind=javaType.lastIndexOf('.'); if (ind != -1) { javaPackage = javaType.substring(0, ind); } } transformers.append("\t\t<xform:transform.jaxb\r\n"); transformers.append("\t\t\t"+attr1+"=\""+qname+"\"\r\n"); transformers.append("\t\t\t"+attr2+"=\"java:"+javaType+"\"\r\n"); transformers.append("\t\t\tcontextPath=\""+javaPackage+"\"/>\r\n"); if (op.getOutput() != null) { p = (javax.wsdl.Part)op.getOutput().getMessage(). getParts().values().iterator().next(); qname = p.getElementName().toString(); javaType = getJavaType(wsdl, p.getElementName(), locator); if (javaType != null) { int ind=javaType.lastIndexOf('.'); if (ind != -1) { javaPackage = javaType.substring(0, ind); } } transformers.append("\t\t<xform:transform.jaxb\r\n"); transformers.append("\t\t\t"+attr2+"=\""+qname+"\"\r\n"); transformers.append("\t\t\t"+attr1+"=\"java:"+javaType+"\"\r\n"); transformers.append("\t\t\tcontextPath=\""+javaPackage+"\"/>\r\n"); } for (Object faultObj : op.getFaults().values()) { if (faultObj instanceof javax.wsdl.Fault) { javax.wsdl.Fault fault=(javax.wsdl.Fault)faultObj; p = (javax.wsdl.Part)fault.getMessage(). getParts().values().iterator().next(); qname = p.getElementName().toString(); String javaFaultType = getJavaType(wsdl, p.getElementName(), locator); String pack=JavaGeneratorUtil.getJavaPackage(fault.getMessage().getQName().getNamespaceURI()); javaType = pack+"."+JavaGeneratorUtil.getJavaClassName(fault.getMessage().getQName().getLocalPart()); String transformerClassName=getFaultTransformerClassName(javaType, provider); String faultTransClass=pack+"."+transformerClassName; transformers.append("\t\t<xform:transform.java class=\""+faultTransClass+"\"\r\n"); transformers.append("\t\t\t"+attr2+"=\""+qname+"\"\r\n"); transformers.append("\t\t\t"+attr1+"=\"java:"+javaType+"\"/>\r\n"); // Create transformer class String folder=pack.replace('.', java.io.File.separatorChar); String javaFile=folder+java.io.File.separator+transformerClassName; java.io.File jFile=new java.io.File(srcFolder+java.io.File.separator+javaFile+".java"); jFile.getParentFile().mkdirs(); try { java.io.FileOutputStream fos=new java.io.FileOutputStream(jFile); generateFaultTransformer(qname, javaType, javaFaultType, provider, fos); fos.close(); } catch (Exception e) { logger.log(Level.SEVERE, "Failed to create fault transformer", e); } } } } } } /** * This method returns the Java fault transformer class name. * * @param javaFaultName The fault class name * @param provider Whether the fault is generated for the provider * @return The fault transformer class name */ protected String getFaultTransformerClassName(String javaFaultName, boolean provider) { int ind=javaFaultName.lastIndexOf('.'); String clsName=javaFaultName.substring(ind+1); String ret = clsName + (provider ? "Provider" : "Consumer") + "Transformer"; return (ret); } /** * This method generates the contents of a fault transformer. * * @param qname The XML type's fully qualified name * @param javaFaultName The Java class for the fault name * @param javaFaultType The Java class for the fault type * @param os The output stream * @throws Exception Failed to generate fault transformer */ protected void generateFaultTransformer(String qname, String javaFaultName, String javaFaultType, boolean provider, java.io.OutputStream os) throws Exception { int ind=javaFaultName.lastIndexOf('.'); String pack=javaFaultName.substring(0, ind); String clsName=getFaultTransformerClassName(javaFaultName, provider); ind = javaFaultType.lastIndexOf('.'); String faultTypePackage=javaFaultType.substring(0, ind); // Get template String template=(provider ? "JavaTypeToQName" : "QNameToJavaType"); java.io.InputStream is=SwitchyardJavaGenerator.class.getResourceAsStream("/templates/" +template+"Transformer.java"); if (is == null) { logger.severe("Failed to load template '"+template+"'"); return; } byte[] b=new byte[is.available()]; is.read(b); is.close(); String str=new String(b); str = str.replaceAll("%PACKAGE%", pack); str = str.replaceAll("%CLASSNAME%", clsName); str = str.replaceAll("%FAULTCLASS%", javaFaultName); str = str.replaceAll("%FAULTTYPE%", javaFaultType); str = str.replaceAll("%FAULTTYPEPACKAGE%", faultTypePackage); str = str.replaceAll("%FAULTQNAME%", qname); str = str.replaceAll("%FAULTMESSAGE%", clsName); os.write(str.getBytes()); } /** * This method scans the supplied wsdl to locate the element definition and return * the Java type associated with its type. * * @param wsdl The WSDL * @param element The element * @param locator The locator * @return The Java type, or null if not found */ protected String getJavaType(javax.wsdl.Definition wsdl, QName element, ResourceLocator locator) { return (JavaGeneratorUtil.getJavaPackage(element.getNamespaceURI())+"."+ JavaGeneratorUtil.getJavaClassName(element.getLocalPart())); /* Return the Element as the Java type (SAVARA-379) * java.util.List<?> elems=wsdl.getTypes().getExtensibilityElements(); if (elems != null) { for (Object obj : elems) { if (obj instanceof javax.wsdl.extensions.schema.Schema) { javax.wsdl.extensions.schema.Schema schema=(javax.wsdl.extensions.schema.Schema)obj; for (Object value : schema.getImports().values()) { if (value instanceof java.util.List<?>) { for (Object si : (java.util.List<?>)value) { if (si instanceof javax.wsdl.extensions.schema.SchemaImport) { String javaType=JavaGeneratorUtil.getElementJavaType(element, ((javax.wsdl.extensions.schema.SchemaImport)si).getSchemaLocationURI(), locator); if (javaType != null) { return (javaType); } } } } } } } logger.warning("Failed to find java type for element '"+element+ "' in wsdl: "+wsdl); } else { logger.warning("Getting java type for element '"+element+ "' failed as unable to find extensibility elements in wsdl: "+wsdl); } return (null); */ } protected void addServiceBehaviour(java.io.File implFile, Role role, java.util.List<Role> refRoles, ProtocolModel behaviour, String srcFolder, ResourceLocator locator) throws Exception { java.io.FileInputStream fis=new java.io.FileInputStream(implFile); byte[] b=new byte[fis.available()]; fis.read(b); fis.close(); // Create variable/role mapping java.util.Map<Role, String> roleMapping=new java.util.HashMap<Role, String>(); for (Role r : refRoles) { String varName="_"+Character.toLowerCase(r.getName().charAt(0))+r.getName().substring(1); roleMapping.put(r, varName); } // Process the Java class to replace the operation bodies String str=new String(b); int index=0; JavaBehaviourGenerator bg=new JavaBehaviourGenerator(behaviour, locator); // NOTE: Tried using Eclipse JDT, but pulled in many dependencies and // was an over complex approach to just replace a method body, so decided // to do it the low tech way :) do { index = str.indexOf(" public ", index); if (index != -1) { int startIndex = str.indexOf("{", index); int endIndex = str.indexOf("\n }", startIndex); if (startIndex != -1 && endIndex != -1) { // Find out operation name String[] reg=str.substring(index, startIndex).split("[ \\(\\)]"); String opbody=bg.getOperationBody(reg[6], reg[5], reg[7], reg[8], roleMapping); if (opbody != null) { str = str.substring(0, startIndex+1)+ opbody+str.substring(endIndex); index = startIndex+1+opbody.length(); } else { index = endIndex; } } else { index = -1; } } } while (index != -1); // Insert the import statements String importStatements=bg.getImportStatements(); if (importStatements != null) { int ind=str.indexOf("import"); if (ind != -1) { str = str.substring(0, ind)+importStatements+"\r\n"+str.substring(ind); } } java.io.FileOutputStream fos=new java.io.FileOutputStream(implFile); fos.write(str.getBytes()); fos.close(); } }