/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.wsdl; import java.io.File; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.xmlbeans.ResourceLoader; import org.apache.xmlbeans.SchemaCodePrinter; import org.apache.xmlbeans.SchemaTypeLoader; import org.apache.xmlbeans.SchemaTypeSystem; import org.apache.xmlbeans.SimpleValue; import org.apache.xmlbeans.XmlBeans; import org.apache.xmlbeans.XmlError; import org.apache.xmlbeans.XmlErrorCodes; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.impl.common.IOUtil; import org.apache.xmlbeans.impl.common.XmlErrorWatcher; import org.apache.xmlbeans.impl.schema.PathResourceLoader; import org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl; import org.apache.xmlbeans.impl.schema.SchemaTypeSystemCompiler; import org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl; import org.apache.xmlbeans.impl.schema.StscState; import org.apache.xmlbeans.impl.util.FilerImpl; import org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument; import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument; import org.xml.sax.EntityResolver; import repackage.Repackager; /** * inspired from Jeff Hanson which copy-pasted method from XmlBeans' SchemaCompiler Modified with more options from the original class (for * example, more params (for download import) * * @author <a href="mailto:jeff@jeffhanson.com">Jeff Hanson</a> * <p/> * <p> * <b>Revisions:</b> * <p/> * <p> * <b>Aug 3, 2005 jhanson:</b> * <ul> * <li>Created file. * </ul> */ public class WSDL2Java { public static class MyResolver implements org.xml.sax.EntityResolver { @Override public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) { System.out.println("System ID: " + systemId); return null; } } /** * System.out.println("Options include:"); System.out.println(" -cp [a;b;c] - classpath"); * System.out.println(" -d [dir] - target binary directory for .class and .xsb files"); * System.out.println(" -src [dir] - target directory for generated .java files"); * System.out.println(" -srconly - do not compile .java files or jar the output."); * System.out.println(" -out [xmltypes.jar] - the name of the output jar"); * System.out.println(" -dl - permit network downloads for imports and includes (default is off)"); * System.out.println(" -noupa - do not enforce the unique particle attribution rule"); * System.out.println(" -nopvr - do not enforce the particle valid (restriction) rule"); * System.out.println(" -noann - ignore annotations"); * System.out.println(" -novdoc - do not validate contents of <documentation>"); * System.out.println(" -compiler - path to external java compiler"); * System.out.println(" -javasource [version] - generate java source compatible for a Java version (1.4 or 1.5)"); * System.out.println(" -ms - initial memory for external java compiler (default '" + CodeGenUtil.DEFAULT_MEM_START + "')"); * System.out.println(" -mx - maximum memory for external java compiler (default '" + CodeGenUtil.DEFAULT_MEM_MAX + "')"); * System.out.println(" -debug - compile with debug symbols"); System.out.println(" -quiet - print fewer informational messages"); * System.out.println(" -verbose - print more informational messages"); * System.out.println(" -version - prints version information"); System.out.println(" -license - prints license information"); * System.out.println(" -allowmdef \"[ns] [ns] [ns]\" - ignores multiple defs in given namespaces (use ##local for no-namespace)"); * System.out.println( * " -catalog [file] - catalog file for org.apache.xml.resolver.tools.CatalogResolver. (Note: needs resolver.jar from http://xml.apache.org/commons/components/resolver/index.html)" * ); * * @param name * @param wsdlFile * @param download * @return */ public static SchemaTypeSystem loadTypeSystem(String name, File wsdlFile, boolean download) throws XmlException { File baseDir = null;// params.getBaseDir(); File[] xsdFiles = null;// params.getXsdFiles(); File[] wsdlFiles = new File[] { wsdlFile };// params.getWsdlFiles(); URL[] urlFiles = null;// params.getUrlFiles(); File[] javaFiles = null;// params.getJavaFiles(); File[] configFiles = null;// params.getConfigFiles(); File[] classpath = null;// params.getClasspath(); File outputJar = null;// params.getOutputJar(); // String name = null;//params.getName(); File srcDir = null;// params.getSrcDir(); File classesDir = null;// params.getClassesDir(); String compiler = null;// params.getCompiler(); String javasource = null;// params.getJavaSource(); String memoryInitialSize = null;// params.getMemoryInitialSize(); String memoryMaximumSize = null;// params.getMemoryMaximumSize(); boolean nojavac = true;// params.isNojavac(); boolean debug = false;// params.isDebug(); boolean verbose = false;// params.isVerbose(); boolean quiet = false;// params.isQuiet(); // boolean download = download;//params.isDownload(); boolean noUpa = false;// params.isNoUpa(); boolean noPvr = false;// params.isNoPvr(); boolean noAnn = true;// params.isNoAnn(); boolean noVDoc = true;// params.isNoVDoc(); boolean incrSrcGen = false;// params.isIncrementalSrcGen(); Collection outerErrorListener = new ArrayList(); String repackage = null;// params.getRepackage(); if (repackage != null) { SchemaTypeLoaderImpl.METADATA_PACKAGE_LOAD = SchemaTypeSystemImpl.METADATA_PACKAGE_GEN; String stsPackage = SchemaTypeSystem.class.getPackage().getName(); Repackager repackager = new Repackager(repackage); SchemaTypeSystemImpl.METADATA_PACKAGE_GEN = repackager.repackage(new StringBuffer(stsPackage)).toString().replace('.', '_'); System.out.println("\n\n\n" + stsPackage + ".SchemaCompiler Metadata LOAD:" + SchemaTypeLoaderImpl.METADATA_PACKAGE_LOAD + " GEN:" + SchemaTypeSystemImpl.METADATA_PACKAGE_GEN); } SchemaCodePrinter codePrinter = null;// params.getSchemaCodePrinter(); List extensions = null;// params.getExtensions(); Set mdefNamespaces = null;// params.getMdefNamespaces(); /* EntityResolver cmdLineEntRes = params.getEntityResolver() == null ? ResolverUtil.resolverForCatalog(params.getCatalogFile()) : params.getEntityResolver(); */ MyResolver entityResolver = new MyResolver(); /*if (srcDir == null || classesDir == null) throw new IllegalArgumentException("src and class gen directories may not be null."); long start = System.currentTimeMillis(); */ // Calculate the usenames based on the relativized filenames on the filesystem /* if (baseDir == null) baseDir = new File(SystemProperties.getProperty("user.dir")); */ ResourceLoader cpResourceLoader = null; Map sourcesToCopyMap = new HashMap(); if (classpath != null) { cpResourceLoader = new PathResourceLoader(classpath); } boolean result = true; File schemasDir = null;// IOUtil.createDir(classesDir, "schema" + SchemaTypeSystemImpl.METADATA_PACKAGE_GEN + "/src"); // build the in-memory type system XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener); SchemaTypeSystem stsi = loadTypeSystem(name, xsdFiles, wsdlFiles, urlFiles, configFiles, javaFiles, cpResourceLoader, download, noUpa, noPvr, noAnn, noVDoc, mdefNamespaces, baseDir, sourcesToCopyMap, outerErrorListener, schemasDir, entityResolver, classpath, javasource); if (errorListener.hasError() && stsi == null) { XmlError error = errorListener.firstError(); System.out.println("Error:" + error.toString()); throw new XmlException(errorListener.firstError()); } return stsi; } private static SchemaTypeSystem loadTypeSystem(String name, File[] xsdFiles, File[] wsdlFiles, URL[] urlFiles, File[] configFiles, File[] javaFiles, ResourceLoader cpResourceLoader, boolean download, boolean noUpa, boolean noPvr, boolean noAnn, boolean noVDoc, Set mdefNamespaces, File baseDir, Map sourcesToCopyMap, Collection outerErrorListener, File schemasDir, EntityResolver entResolver, File[] classpath, String javasource) { XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener); // construct the state (have to initialize early in case of errors) StscState state = StscState.start(); state.setErrorListener(errorListener); // For parsing XSD and WSDL files, we should use the SchemaDocument // classloader rather than the thread context classloader. This is // because in some situations (such as when being invoked by ant // underneath the ide) the context classloader is potentially weird // (because of the design of ant). SchemaTypeLoader loader = XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader()); // step 1, parse all the XSD files. ArrayList scontentlist = new ArrayList(); if (xsdFiles != null) { System.out.println("CODE DELETED FOR XSD FILES: SEE org.apache.xmlbeans.impl.tool.SchemaCompiler loadTypeSystem method"); } // step 2, parse all WSDL files if (wsdlFiles != null) { for (int i = 0; i < wsdlFiles.length; i++) { try { XmlOptions options = new XmlOptions(); options.setLoadLineNumbers(); options.setLoadSubstituteNamespaces(Collections.singletonMap("http://schemas.xmlsoap.org/wsdl/", "http://www.apache.org/internal/xmlbeans/wsdlsubst")); options.setEntityResolver(entResolver); XmlObject wsdldoc = loader.parse(wsdlFiles[i], null, options); if (!(wsdldoc instanceof org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument)) { StscState.addError(errorListener, XmlErrorCodes.INVALID_DOCUMENT_TYPE, new Object[] { wsdlFiles[i], "wsdl" }, wsdldoc); } else { addWsdlSchemas(wsdlFiles[i].toString(), (org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument) wsdldoc, errorListener, noVDoc, scontentlist); } } catch (XmlException e) { errorListener.add(e.getError()); } catch (Exception e) { StscState.addError(errorListener, XmlErrorCodes.CANNOT_LOAD_FILE, new Object[] { "wsdl", wsdlFiles[i], e.getMessage() }, wsdlFiles[i]); } } } // step 3, parse all URL files // XMLBEANS-58 - Ability to pass URLs instead of Files for Wsdl/Schemas if (urlFiles != null) { for (int i = 0; i < urlFiles.length; i++) { try { XmlOptions options = new XmlOptions(); options.setLoadLineNumbers(); options.setLoadSubstituteNamespaces(Collections.singletonMap("http://schemas.xmlsoap.org/wsdl/", "http://www.apache.org/internal/xmlbeans/wsdlsubst")); options.setEntityResolver(entResolver); XmlObject urldoc = loader.parse(urlFiles[i], null, options); if (urldoc instanceof org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument) { addWsdlSchemas(urlFiles[i].toString(), (org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument) urldoc, errorListener, noVDoc, scontentlist); } else if (urldoc instanceof SchemaDocument) { System.out .println("CODE DELETED FOR XSD FILES: SEE org.apache.xmlbeans.impl.tool.SchemaCompiler loadTypeSystem method"); } else { StscState.addError(errorListener, XmlErrorCodes.INVALID_DOCUMENT_TYPE, new Object[] { urlFiles[i], "wsdl or schema" }, urldoc); } } catch (XmlException e) { errorListener.add(e.getError()); } catch (Exception e) { StscState.addError(errorListener, XmlErrorCodes.CANNOT_LOAD_FILE, new Object[] { "url", urlFiles[i], e.getMessage() }, urlFiles[i]); } } } SchemaDocument.Schema[] sdocs = (SchemaDocument.Schema[]) scontentlist.toArray(new SchemaDocument.Schema[scontentlist.size()]); // now the config files. ArrayList cdoclist = new ArrayList(); if (configFiles != null) { System.out.println("CODE DELETED FOR CONFIG FILES: SEE org.apache.xmlbeans.impl.tool.SchemaCompiler loadTypeSystem method"); } // ConfigDocument.Config[] cdocs = (ConfigDocument.Config[])cdoclist.toArray(new ConfigDocument.Config[cdoclist.size()]); SchemaTypeLoader linkTo = SchemaTypeLoaderImpl.build(null, cpResourceLoader, null); URI baseURI = null; if (baseDir != null) { baseURI = baseDir.toURI(); } XmlOptions opts = new XmlOptions(); if (download) { opts.setCompileDownloadUrls(); } if (noUpa) { opts.setCompileNoUpaRule(); } if (noPvr) { opts.setCompileNoPvrRule(); } if (noAnn) { opts.setCompileNoAnnotations(); } if (mdefNamespaces != null) { opts.setCompileMdefNamespaces(mdefNamespaces); } opts.setCompileNoValidation(); // already validated here opts.setEntityResolver(entResolver); if (javasource != null) { opts.setGenerateJavaVersion(javasource); } // now pass it to the main compile function SchemaTypeSystemCompiler.Parameters params = new SchemaTypeSystemCompiler.Parameters(); params.setName(name); params.setSchemas(sdocs); // params.setConfig(BindingConfigImpl.forConfigDocuments(cdocs, javaFiles, classpath)); params.setLinkTo(linkTo); params.setOptions(opts); params.setErrorListener(errorListener); params.setJavaize(true); params.setBaseURI(baseURI); params.setSourcesToCopyMap(sourcesToCopyMap); params.setSchemasDir(schemasDir); SchemaTypeSystem stsi = SchemaTypeSystemCompiler.compile(params); return stsi; /* * return compileImpl(params.getExistingTypeSystem(), params.getName(), params.getSchemas(), params.getConfig(), params.getLinkTo(), params.getOptions(), params.getErrorListener(), params.isJavaize(), params.getBaseURI(), params.getSourcesToCopyMap(), params.getSchemasDir()); */ } /** * return the schemas * * @param schemaFilesDir * @param schemaClassesDir * @param schemaSrcDir * @param wsdlFileName * @return */ public List generate(String schemaFilesDir, String schemaClassesDir, String schemaSrcDir, String wsdlFileName) { boolean doNotValidateContents = false; XmlObject wsdlDoc = null; MyResolver entityResolver = new MyResolver(); ArrayList outerErrorListener = new ArrayList(); XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener); ArrayList scontentlist = new ArrayList(); try { SchemaTypeLoader loader = XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader()); XmlOptions options = new XmlOptions(); options.setLoadLineNumbers(); options.setLoadSubstituteNamespaces(Collections.singletonMap("http://schemas.xmlsoap.org/wsdl/", "http://www.apache.org/internal/xmlbeans/wsdlsubst")); options.setEntityResolver(entityResolver); System.out.println("Parsing WSDL: " + wsdlFileName + "..."); wsdlDoc = loader.parse(new File(wsdlFileName), null, options); if (!(wsdlDoc instanceof DefinitionsDocument)) { // Create new definitions doc DefinitionsDocument.Definitions definitions = DefinitionsDocument.Definitions.Factory.newInstance(); // Set types array definitions.setTypesArray(wsdlDoc.selectPath("wsdl:types")); DefinitionsDocument defDoc = DefinitionsDocument.Factory.newInstance(); defDoc.setDefinitions(definitions); // Adding constructed schema addWsdlSchemas(wsdlFileName, defDoc, errorListener, doNotValidateContents, scontentlist); } else { addWsdlSchemas(wsdlFileName, (DefinitionsDocument) wsdlDoc, errorListener, doNotValidateContents, scontentlist); } } catch (XmlException e) { errorListener.add(e.getError()); } catch (Exception e) { StscState.addError(errorListener, XmlErrorCodes.CANNOT_LOAD_FILE, new Object[] { "wsdl", wsdlFileName, e.getMessage() }, wsdlDoc); } /** * SchemaTypeSystem sts = compileSchemas(schemaFilesDir, scontentlist, entityResolver, errorListener); * * return generateJavaSource(schemaClassesDir, schemaSrcDir, sts); */ return scontentlist; } private SchemaTypeSystem compileSchemas(String schemaFilesDir, ArrayList scontentlist, MyResolver entityResolver, XmlErrorWatcher errorListener) { SchemaDocument.Schema[] sdocs = (SchemaDocument.Schema[]) scontentlist.toArray(new SchemaDocument.Schema[scontentlist.size()]); ResourceLoader cpResourceLoader = null; SchemaTypeLoader linkTo = SchemaTypeLoaderImpl.build(null, cpResourceLoader, null); File baseDir = new File(System.getProperty("user.dir")); java.net.URI baseURI = baseDir.toURI(); XmlOptions opts = new XmlOptions(); opts.setCompileNoValidation(); opts.setEntityResolver(entityResolver); // DVA download import statement opts.setCompileDownloadUrls(); Map sourcesToCopyMap = new HashMap(); File schemasDir = IOUtil.createDir(new File("."), schemaFilesDir); // create parameters for the main compile function SchemaTypeSystemCompiler.Parameters params = new SchemaTypeSystemCompiler.Parameters(); params.setName(null); params.setSchemas(sdocs); params.setLinkTo(linkTo); params.setOptions(opts); params.setErrorListener(errorListener); params.setJavaize(true); params.setBaseURI(baseURI); params.setSourcesToCopyMap(sourcesToCopyMap); params.setSchemasDir(schemasDir); System.out.println("Compiling schemas..."); try { // create schema files (.xsb's) SchemaTypeSystem sts = SchemaTypeSystemCompiler.compile(params); // now save .xsb's to disk sts.saveToDirectory(schemasDir); System.out.println("Schema compilation succeeded"); return sts; } catch (Exception e) { e.printStackTrace(); } return null; } private List generateJavaSource(String schemaClassesDir, String schemaSrcDir, SchemaTypeSystem sts) { File classesDir = new File(schemaClassesDir); File srcDir = IOUtil.createDir(new File("."), schemaSrcDir); // now, generate the source files XmlOptions options = new XmlOptions(); boolean verbose = false; boolean incrSrcGen = false; Repackager repackager = null; FilerImpl filer = new FilerImpl(classesDir, srcDir, repackager, verbose, incrSrcGen); System.out.println("Generating Java source..."); if (SchemaTypeSystemCompiler.generateTypes(sts, filer, options)) { System.out.println("Java source generation succeeded"); return filer.getSourceFiles(); } else { System.out.println("Java source generation failed"); } return null; } /** * original version from SchemaCompiler * * @param name * @param wsdldoc * @param errorListener * @param noVDoc * @param scontentlist */ private static void addWsdlSchemas(String name, org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument wsdldoc, XmlErrorWatcher errorListener, boolean noVDoc, List scontentlist) { if (wsdlContainsEncoded(wsdldoc)) { StscState .addWarning(errorListener, "The WSDL " + name + " uses SOAP encoding. SOAP encoding is not compatible with literal XML Schema.", XmlErrorCodes.GENERIC_ERROR, wsdldoc); } StscState.addInfo(errorListener, "Loading wsdl file " + name); XmlOptions opts = new XmlOptions().setErrorListener(errorListener); if (noVDoc) { opts.setValidateTreatLaxAsSkip(); } XmlObject[] types = wsdldoc.getDefinitions().getTypesArray(); int count = 0; for (int j = 0; j < types.length; j++) { XmlObject[] schemas = types[j].selectPath("declare namespace xs=\"http://www.w3.org/2001/XMLSchema\" xs:schema"); if (schemas.length == 0) { StscState.addWarning(errorListener, "The WSDL " + name + " did not have any schema documents in namespace 'http://www.w3.org/2001/XMLSchema'", XmlErrorCodes.GENERIC_ERROR, wsdldoc); continue; } for (int k = 0; k < schemas.length; k++) { if (schemas[k] instanceof SchemaDocument.Schema && schemas[k].validate(opts)) { count++; scontentlist.add(schemas[k]); } } } StscState.addInfo(errorListener, "Processing " + count + " schema(s) in " + name); } private static boolean wsdlContainsEncoded(XmlObject wsdldoc) { // search for any <soap:body use="encoded"/> etc. XmlObject[] useAttrs = wsdldoc.selectPath("declare namespace soap='http://schemas.xmlsoap.org/wsdl/soap/' " + ".//soap:body/@use|.//soap:header/@use|.//soap:fault/@use"); for (int i = 0; i < useAttrs.length; i++) { if ("encoded".equals(((SimpleValue) useAttrs[i]).getStringValue())) { return true; } } return false; } /** * modified version from Jeff Hanson * * @param wsdlFileName * @param definitionsDocument * @param errorListener * @param doNotValidateContents * @param scontentlist */ /* private void addWsdlSchemas(String wsdlFileName, DefinitionsDocument definitionsDocument, XmlErrorWatcher errorListener, boolean doNotValidateContents, ArrayList scontentlist) { XmlOptions opts = new XmlOptions().setErrorListener(errorListener); if (doNotValidateContents) { opts.setValidateTreatLaxAsSkip(); } XmlObject[] types = definitionsDocument.getDefinitions().getTypesArray(); for (int j = 0; j < types.length; j++) { XmlObject[] schemas = types[j].selectPath("declare namespace" + " xs=\"http://www.w3.org/2001/XMLSchema\"" + " xs:schema"); if (schemas.length == 0) { StscState.addWarning(errorListener, "The WSDL " + wsdlFileName + " has no schema documents in namespace " + "'http://www.w3.org/2001/XMLSchema'", XmlErrorCodes.GENERIC_ERROR, definitionsDocument); continue; } for (int k = 0; k < schemas.length; k++) { if (schemas[k] instanceof SchemaDocument.Schema) { SchemaDocumentImpl.SchemaImpl schemaImpl = (SchemaDocumentImpl.SchemaImpl)schemas[k]; System.out.println("Validating schema..."); if (schemaImpl.validate(opts)) { System.out.println("Schema passed validation"); scontentlist.add(schemas[k]); } else { System.out.println("Schema failed validation"); scontentlist.add(schemas[k]); } } } } } */ }