/* Copyright (c) 2004-2008, Dennis M. Sosnoski All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jibx.binding; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.jibx.binding.classes.ClassCache; import org.jibx.binding.classes.ClassFile; import org.jibx.binding.model.BindingElement; import org.jibx.binding.model.ClassWrapper; import org.jibx.binding.model.CollectionElement; import org.jibx.binding.model.ContainerElementBase; import org.jibx.binding.model.DefinitionContext; import org.jibx.binding.model.ElementBase; import org.jibx.binding.model.IClass; import org.jibx.binding.model.IClassLocator; import org.jibx.binding.model.MappingElement; import org.jibx.binding.model.NestingAttributes; import org.jibx.binding.model.NestingElementBase; import org.jibx.binding.model.StructureElement; import org.jibx.binding.model.StructureElementBase; import org.jibx.binding.model.TemplateElementBase; import org.jibx.binding.model.ValidationContext; import org.jibx.binding.model.ValidationProblem; import org.jibx.binding.model.ValueElement; import org.jibx.binding.util.ObjectStack; import org.jibx.runtime.JiBXException; import org.jibx.runtime.ValidationException; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Binding generator. This loads the specified input classes and processes them * to generate a default binding definition. * * @author Dennis M. Sosnoski */ public class SchemaGenerator { /** Generator version. */ private static String CURRENT_VERSION = "0.4"; /** Schema namespace URI. */ private static final String XSD_URI = "http://www.w3.org/2001/XMLSchema"; /** Fixed XML namespace. */ public static final String XML_URI = "http://www.w3.org/XML/1998/namespace"; /** Fixed XML namespace namespace. */ public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; /** Set of object types mapped to schema types. */ private static HashMap s_objectTypeMap = new HashMap(); static { s_objectTypeMap.put("java.lang.Boolean", "xsd:boolean"); s_objectTypeMap.put("java.lang.Byte", "xsd:byte"); s_objectTypeMap.put("java.lang.Char", "xsd:unsignedInt"); s_objectTypeMap.put("java.lang.Double", "xsd:double"); s_objectTypeMap.put("java.lang.Float", "xsd:float"); s_objectTypeMap.put("java.lang.Integer", "xsd:int"); s_objectTypeMap.put("java.lang.Long", "xsd:long"); s_objectTypeMap.put("java.lang.Short", "xsd:short"); s_objectTypeMap.put("java.math.BigDecimal", "xsd:decimal"); s_objectTypeMap.put("java.math.BigInteger", "xsd:integer"); //#!j2me{ s_objectTypeMap.put("java.sql.Date", "xsd:date"); s_objectTypeMap.put("java.sql.Time", "xsd:time"); s_objectTypeMap.put("java.sql.Timestamp", "xsd:dateTime"); //#j2me} s_objectTypeMap.put("java.util.Date", "xsd:dateTime"); s_objectTypeMap.put("byte[]", "xsd:base64"); } /** Set of primitive types mapped to schema types. */ private static HashMap s_primitiveTypeMap = new HashMap(); static { s_primitiveTypeMap.put("boolean", "xsd:boolean"); s_primitiveTypeMap.put("byte", "xsd:byte"); s_primitiveTypeMap.put("char", "xsd:unsignedInt"); s_primitiveTypeMap.put("double", "xsd:double"); s_primitiveTypeMap.put("float", "xsd:float"); s_primitiveTypeMap.put("int", "xsd:int"); s_primitiveTypeMap.put("long", "xsd:long"); s_primitiveTypeMap.put("short", "xsd:short"); } /** Show verbose output flag. */ private boolean m_verbose; /** Use qualified elements default in schema flag. */ private boolean m_isElementQualified; /** Use qualified attributes default in schema flag. */ private boolean m_isAttributeQualified; /** Indentation sequence per level of nesting. */ private String m_indentSequence; /** Map from namespaces to schemas. */ private HashMap m_schemaMap; /** Locator for finding classes referenced by binding. */ private IClassLocator m_classLocator; /** Document used for all schema definitions. */ private Document m_document; /** Stack of structure definitions in progress (used to detect cycles). */ private ObjectStack m_structureStack; /** * Constructor with only paths supplied. This just initializes all other * options disabled. * * @param paths class paths to be checked for classes referenced by bindings */ public SchemaGenerator(ArrayList paths) { m_structureStack = new ObjectStack(); m_schemaMap = new HashMap(); // set paths to be used for loading referenced classes String[] parray = (String[])paths.toArray(new String[paths.size()]); ClassCache.setPaths(parray); ClassFile.setPaths(parray); // set class locator m_classLocator = new IClassLocator() { public IClass getClassInfo(String name) { try { return new ClassWrapper(this, ClassCache.getClassFile(name)); } catch (JiBXException e) { throw new IllegalStateException("Class not found " + name); } } }; try { // create the document used for all schemas DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); m_document = dbf.newDocumentBuilder().newDocument(); } catch (ParserConfigurationException e) { throw new IllegalStateException("Parser configuration error " + e.getMessage()); } catch (FactoryConfigurationError e) { throw new IllegalStateException("Factory configuration error " + e.getMessage()); } } /** * Constructor with settings specified. * * @param verbose report binding details and results * @param equal use element form default qualified flag * @param aqual use attribute form default qualified flag * @param paths class paths to be checked for classes referenced by bindings */ public SchemaGenerator(boolean verbose, boolean equal, boolean aqual, ArrayList paths) { this(paths); m_verbose = verbose; m_isElementQualified = equal; m_isAttributeQualified = aqual; m_indentSequence = " "; } /** * Set control flag for verbose processing reports. * * @param verbose report verbose information in processing bindings flag */ public void setVerbose(boolean verbose) { m_verbose = verbose; } /** * Set control flag for element qualified default schema. * * @param qual element qualified default schemas flag */ public void setElementQualified(boolean qual) { m_isElementQualified = qual; } /** * Set control flag for attribute qualified default schema. * * @param qual attribute qualified default schemas flag */ public void setAttributeQualified(boolean qual) { m_isAttributeQualified = qual; } /** * Get array of generated schemas. * * @return array of schema elements */ public Element[] getSchemas() { Element[] schemas = new Element[m_schemaMap.size()]; int fill = 0; for (Iterator iter = m_schemaMap.values().iterator(); iter.hasNext();) { schemas[fill++] = (Element)iter.next(); } return schemas; } /** * Generate indentation to proper depth for current item. This creates the * indentation text and appends it to the supplied parent. The generated * indentation is appropriate for the close tag of the parent element; if * a child element is to be added following this indentation it needs to * use an additional leading indent. * * @param parent element to contain indented child item */ private void indentForClose(Element parent) { StringBuffer buff = new StringBuffer(20); buff.append('\n'); Element ancestor = parent; boolean count = false; while (ancestor != null) { if (count) { buff.append(m_indentSequence); } ancestor = (Element)ancestor.getParentNode(); count = true; } parent.appendChild(m_document.createTextNode(buff.toString())); } /** * Add comment with appropriate indentation. * * @param parent element to contain indented child item * @param text comment text */ private void addComment(Element parent, String text) { if (parent.getChildNodes().getLength() == 0) { indentForClose(parent); } parent.appendChild(m_document.createTextNode(m_indentSequence)); parent.appendChild(m_document.createComment(text)); indentForClose(parent); } /** * Add child element with appropriate indentation. This generates and * returns the child element after adding it to the supplied parent, * allowing further modification of the new child element. * * @param parent element to contain indented child item * @param name child element name */ private Element addChildElement(Element parent, String name) { if (parent.getChildNodes().getLength() == 0) { indentForClose(parent); } parent.appendChild(m_document.createTextNode(m_indentSequence)); Element element = m_document.createElementNS(XSD_URI, name); element.setPrefix(parent.getPrefix()); parent.appendChild(element); indentForClose(parent); return element; } /** * Get innermost containing definition context. * * @return innermost definition context containing this element */ public DefinitionContext getDefinitions() { int index = 0; while (index < m_structureStack.size()) { NestingElementBase nest = (NestingElementBase)m_structureStack.peek(index++); if (nest.getDefinitions() != null) { return nest.getDefinitions(); } } throw new IllegalStateException ("Internal error: no definition context"); } /** * Process a structure component (structure or collection element) with no * name and no child components. This adds the appropriate type of element * or any definition to the container schema element. * * @param comp structure component to be processed * @param egroup schema element to contain element definitions * @param agroup schema element to contain attribute definitions */ private void defineEmptyStructureComponent(StructureElementBase comp, Element egroup, Element agroup) { NestingElementBase parent = (NestingElementBase)m_structureStack.peek(0); boolean only = parent.children().size() == 1; if (comp.type() == ElementBase.COLLECTION_ELEMENT) { // collection may define type or not CollectionElement collection = (CollectionElement)comp; String itype = collection.getItemTypeClass().getName(); DefinitionContext dctx = getDefinitions(); TemplateElementBase templ = dctx.getSpecificTemplate(itype); Element element = null; if (! (templ instanceof MappingElement)) { if (only) { addComment(egroup, " Replace \"any\" with details of " + "content to complete schema "); element = addChildElement(egroup, "any"); } else { addComment(egroup, " No mapping for items of collection at " + ValidationException.describe(collection) + " "); addComment(egroup, " Fill in details of content to complete schema "); } } else { element = addChildElement(egroup, "element"); String name = ((MappingElement)templ).getName(); if (element.getPrefix() == null) { name = "tns:" + name; } element.setAttribute("ref", name); } if (element != null) { element.setAttribute("minOccurs", "0"); element.setAttribute("maxOccurs", "unbounded"); } } else { // check for reference to a mapped class StructureElement structure = (StructureElement)comp; TemplateElementBase templ = structure.getEffectiveMapping(); if (! (templ instanceof MappingElement)) { // unknown content, leave it to user to fill in details if (only) { addComment(egroup, " Replace \"any\" with details of " + "content to complete schema "); addChildElement(egroup, "any"); } else { addComment(egroup, " No mapping for structure at " + ValidationException.describe(structure) + " "); addComment(egroup, " Fill in details of content here to complete schema "); } } else { MappingElement mapping = (MappingElement)templ; if (mapping.isAbstract()) { // check name to be used for instance of type String ename = structure.getName(); if (ename == null) { ename = mapping.getName(); } if (ename == null) { // no schema equivalent, embed definition directly addComment(egroup, "No schema representation for " + "directly-embedded type, inlining definition"); addComment(egroup, "Add element name to structure at " + ValidationException.describe(structure) + " to avoid inlining"); defineList(mapping.children(), egroup, agroup, false); } else { // handle abstract mapping element as reference to type Element element = addChildElement(egroup, "element"); String tname = simpleClassName(mapping.getClassName()); if (element.getPrefix() == null) { tname = "tns:" + tname; } element.setAttribute("type", tname); String name = structure.getName(); if (name == null) { name = mapping.getName(); } element.setAttribute("name", name); if (structure.isOptional()) { element.setAttribute("minOccurs", "0"); } } } else { // concrete mapping, check for name overridden String sname = structure.getName(); String mname = mapping.getName(); if (sname != null && !sname.equals(mname)) { // inline definition for overridden name addComment(egroup, "No schema representation for " + "element reference with different name, inlining " + "definition"); addComment(egroup, "Remove name on mapping reference at " + ValidationException.describe(structure) + " to avoid inlining"); defineList(mapping.children(), egroup, agroup, false); } else { // use element reference for concrete mapping Element element = addChildElement(egroup, "element"); String tname = simpleClassName(mapping.getClassName()); if (element.getPrefix() == null) { tname = "tns:" + tname; } element.setAttribute("ref", tname); if (structure.isOptional()) { element.setAttribute("minOccurs", "0"); } } } } } } /** * Process a structure component (structure or collection element) within a * list of child components. This adds the appropriate type of element or * any definition to the container, if necessary calling other methods for * recursive handling of nested child components. * * @param comp structure component to be processed * @param egroup schema element to contain element definitions * @param agroup schema element to contain attribute definitions * @param mult allow any number of occurrences of components flag */ private void defineStructureComponent(StructureElementBase comp, Element egroup, Element agroup, boolean mult) { // check for element defined by binding component if (comp.getName() != null) { // create basic element definition for name Element element = addChildElement(egroup, "element"); element.setAttribute("name", comp.getName()); if (mult) { element.setAttribute("minOccurs", "0"); element.setAttribute("maxOccurs", "unbounded"); } else if (comp.isOptional()) { element.setAttribute("minOccurs", "0"); } // check for children present if (comp.children().size() > 0) { defineNestedStructure(comp, element); } else { // nest complex type definition for actual content Element type = addChildElement(element, "complexType"); Element seq = addChildElement(type, "sequence"); // process the content description defineEmptyStructureComponent(comp, seq, type); } } else if (comp.children().size() > 0) { // handle child components with recursive call boolean coll = comp.type() == ElementBase.COLLECTION_ELEMENT; m_structureStack.push(comp); defineList(comp.children(), egroup, agroup, coll); m_structureStack.pop(); } else { // handle empty structure definition inline defineEmptyStructureComponent(comp, egroup, agroup); } } /** * Create the schema definition list for a binding component list. This * builds the sequence of elements and attributes defined by the binding * components, including nested complex types for elements with structure. * * @param comps binding component list * @param egroup schema element to contain element definitions * @param agroup schema element to contain attribute definitions * @param mult allow any number of occurrences of components flag */ private void defineList(ArrayList comps, Element egroup, Element agroup, boolean mult) { // handle all nested elements of container for (int i = 0; i < comps.size(); i++) { ElementBase child = (ElementBase)comps.get(i); switch (child.type()) { case ElementBase.COLLECTION_ELEMENT: case ElementBase.STRUCTURE_ELEMENT: { defineStructureComponent((StructureElementBase)child, egroup, agroup, mult); break; } case ElementBase.MAPPING_ELEMENT: { // nested mapping definitions not handled System.err.println("Error: nested mapping not supported " + "(class " + ((MappingElement)child).getClassName() + ")"); break; } case ElementBase.TEMPLATE_ELEMENT: { // templates to be added once usable in binding System.err.println ("Error: template component not yet supported"); break; } case ElementBase.VALUE_ELEMENT: { // get type information for value ValueElement value = (ValueElement)child; String tname = value.getType().getName(); String stype = (String)s_primitiveTypeMap.get(tname); if (stype == null) { stype = (String)s_objectTypeMap.get(tname); if (stype == null) { stype = "xsd:string"; } } // build schema element or attribute for value Element element; int style = value.getStyle(); if (style == NestingAttributes.ATTRIBUTE_STYLE) { // append attribute as child of type element = addChildElement(agroup, "attribute"); if (!value.isOptional()) { element.setAttribute("use", "required"); } } else if (style == NestingAttributes.ELEMENT_STYLE) { // append simple element as child of grouping element = addChildElement(egroup, "element"); if (mult) { element.setAttribute("minOccurs", "0"); element.setAttribute("maxOccurs", "unbounded"); } else if (value.isOptional()) { element.setAttribute("minOccurs", "0"); } } else { // other types are not currently handled System.err.println("Error: value type " + value.getEffectiveStyleName() + " not supported"); break; } // set common attributes on definition element.setAttribute("name", value.getName()); element.setAttribute("type", stype); break; } } } } /** * Create the schema definition for a nested structure. This defines a * complex type, if necessary calling itself recursively for elements which * are themselves complex types. In the special case where the container * element is a mapping which extends an abstract base class this generates * the complex type as an extension of the base class complex type. * * @param container binding definition element containing nested structure * @param parent schema element to hold the definition * @return constructed complex type */ private Element defineNestedStructure(ContainerElementBase container, Element parent) { // create complex type as holder for definition Element type = addChildElement(parent, "complexType"); // check whether ordered or unordered container Element group; ArrayList childs = container.children(); if (container.isOrdered()) { // define content list as sequence group = addChildElement(type, "sequence"); // check for mapping which extends another mapping /* if (container instanceof MappingElement) { MappingElement mapping = (MappingElement)container; MappingElement extended = mapping.getExtendsMapping(); if (extended != null) { // now see if the mapping can extend base complex type boolean extend = false; for (int i = 0; i < childs.size(); i++) { ElementBase child = (ElementBase)childs.get(i); if (child instanceof StructureElement) { StructureElement struct = (StructureElement)child; if (struct.getMapAsMapping() == extended) { if (struct.getName() == null) { extend = true; } } } if (child instanceof IComponent) { } } } } */ } else { group = addChildElement(type, "all"); } // handle all nested elements of container m_structureStack.push(container); defineList(childs, group, type, container.type() == ElementBase.COLLECTION_ELEMENT); m_structureStack.pop(); return type; } /** * Generate a schema from a binding using supplied classpaths. If the schema * for the binding namespace (or default namespace) already exists the * definitions from this binding are added to the existing schema; otherwise * a new schema is created and added to the collection defined. * * @param binding root element of binding */ private void generateSchema(BindingElement binding) { // process each mapping definition for binding m_structureStack.push(binding); ArrayList tops = binding.topChildren(); for (int i = 0; i < tops.size(); i++) { ElementBase top = (ElementBase)tops.get(i); if (top.type() == ElementBase.MAPPING_ELEMENT) { // find or create schema for mapped class MappingElement mapping = (MappingElement)top; String uri = mapping.getNamespace().getUri(); Element schema = (Element)m_schemaMap.get(uri); if (schema == null) { // build new schema element for this namespace schema = m_document.createElementNS(XSD_URI, "schema"); m_schemaMap.put(uri, schema); // set qualification attributes if needed if (m_isElementQualified) { schema.setAttribute("elementFormDefault", "qualified"); } if (m_isAttributeQualified) { schema.setAttribute("attributeFormDefault", "qualified"); } // add namespace declarations to element if (uri == null) { schema.setPrefix("xsd"); } else { schema.setAttribute("targetNamespace", uri); schema.setAttributeNS(XMLNS_URI, "xmlns:tns", uri); schema.setAttributeNS(XMLNS_URI, "xmlns", XSD_URI); } schema.setAttributeNS(XMLNS_URI, "xmlns:xsd", XSD_URI); // add spacing for first child node indentForClose(schema); } // add spacer and comment before actual definition indentForClose(schema); String cname = mapping.getClassName(); addComment(schema, " Created from mapping for class " + cname + " "); if (mapping.isAbstract()) { // add mapping as global type in binding Element type = defineNestedStructure(mapping, schema); type.setAttribute("name", simpleClassName(cname)); } else { // add mapping as global element in binding Element element = addChildElement(schema, "element"); element.setAttribute("name", mapping.getName()); // check type of mapping definition if (mapping.getMarshaller() != null || mapping.getUnmarshaller() != null) { // use "any" for custom marshaller/unmarshaller Element type = addChildElement(element, "complexType"); Element seq = addChildElement(type, "sequence"); addComment(seq, " Replace \"any\" with details of " + "content to complete schema "); addChildElement(seq, "any"); } else { // use complex type for embedded definition defineNestedStructure(mapping, element); } } } } m_structureStack.pop(); } /** * Process a binding definition for schema generation. This first validates * the binding definition, and if it is valid then handles schema generation * from the binding. * * @param binding root element of binding * @exception JiBXException if error in generating the schema */ public void generate(BindingElement binding) throws JiBXException { // validate the binding definition ValidationContext vctx = new ValidationContext(m_classLocator); binding.runValidation(vctx); boolean usable = true; if (vctx.getProblems().size() > 0) { // report problems found System.err.println("Problems found in binding " + binding.getName()); ArrayList probs = vctx.getProblems(); for (int i = 0; i < probs.size(); i++) { ValidationProblem prob = (ValidationProblem)probs.get(i); System.err.println(prob.getDescription()); if (prob.getSeverity() > ValidationProblem.WARNING_LEVEL) { usable = false; } } } // check if binding usable for schema generation if (usable) { generateSchema(binding); } else { System.err.println ("Binding validation errors prevent schema generation"); System.exit(1); } } /** * Get simple class name. * * @param cname class name with full package specification * @return class name only */ private String simpleClassName(String cname) { int split = cname.lastIndexOf('.'); if (split >= 0) { cname = cname.substring(split+1); } return cname; } /** * Main method for running compiler as application. * * @param args command line arguments */ public static void main(String[] args) { if (args.length > 0) { try { // check for various flags set boolean verbose = false; boolean edflt = true; boolean adflt = false; ArrayList paths = new ArrayList(); int offset = 0; for (; offset < args.length; offset++) { String arg = args[offset]; if ("-v".equalsIgnoreCase(arg)) { verbose = true; } else if ("-e".equalsIgnoreCase(arg)) { edflt = false; } else if ("-a".equalsIgnoreCase(arg)) { adflt = true; } else if ("-p".equalsIgnoreCase(arg)) { paths.add(args[++offset]); } else { break; } } // set up path and binding lists String[] vmpaths = Utility.getClassPaths(); for (int i = 0; i < vmpaths.length; i++) { paths.add(vmpaths[i]); } ArrayList bindings = new ArrayList(); for (int i = offset; i < args.length; i++) { bindings.add(args[i]); } // report on the configuration System.out.println("Running schema generator version " + CURRENT_VERSION); if (verbose) { System.out.println("Using paths:"); for (int i = 0; i < paths.size(); i++) { System.out.println(" " + paths.get(i)); } System.out.println("Using input bindings:"); for (int i = 0; i < bindings.size(); i++) { System.out.println(" " + bindings.get(i)); } } // process all specified binding files SchemaGenerator schemagen = new SchemaGenerator(verbose, edflt, adflt, paths); for (int i = 0; i < bindings.size(); i++) { // read binding from file String bpath = (String)bindings.get(i); String name = Utility.fileName(bpath); File file = new File(bpath); BindingElement binding = Utility.validateBinding(name, new URL("file://" + file.getAbsolutePath()), new FileInputStream(file)); // convert the binding to a schema if (binding != null) { schemagen.generate(binding); } } // output each schema to separate file Element[] schemas = schemagen.getSchemas(); for (int i = 0; i < schemas.length; i++) { // get base name for output file from last part of namespace Element schema = schemas[i]; String tns = schema.getAttribute("targetNamespace"); String name = tns; if (name.length() == 0) { // fix this to relate back to binding name = (String)bindings.get(0); int split = name.lastIndexOf('.'); if (split >= 0) { name = name.substring(0, split); } } else { int split = name.lastIndexOf('/'); if (split >= 0) { name = name.substring(split+1); } } try { // write schema to output file name += ".xsd"; FileOutputStream out = new FileOutputStream(name); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty("indent", "no"); DOMSource source = new DOMSource(schema); Result result = new StreamResult(out); transformer.transform(source, result); out.close(); System.out.print("Wrote schema " + name); if (tns.length() == 0) { System.out.println(" for default namespace"); } else { System.out.println(" for namespace " + tns); } } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } catch (JiBXException ex) { ex.printStackTrace(); System.exit(1); } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(2); } catch (MalformedURLException e) { e.printStackTrace(); System.exit(3); } } else { System.out.println ("\nUsage: java org.jibx.binding.SchemaGenerator [-v] [-e]" + " [-a] [-p path]* binding1 binding2 ...\nwhere:" + "\n -v turns on verbose output," + "\n -e sets elementFormDefault=\"false\" for the schemas," + "\n -a sets attributeFormDefault=\"true\" for the schemas, " + "and\n -p gives a path component for looking up the classes " + "referenced in the binding\nThe binding# files are " + "different bindings to be used for schema generation.\n"); System.exit(1); } } }