All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ws.jaxme.generator.XJCTask Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2003,2004  The Apache Software Foundation
 * 
 * Licensed 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.ws.jaxme.generator;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.ws.jaxme.generator.impl.GeneratorImpl;
import org.apache.ws.jaxme.generator.sg.SGFactoryChain;
import org.apache.ws.jaxme.generator.sg.SchemaSG;
import org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader;
import org.apache.ws.jaxme.generator.sg.impl.JaxMeSchemaReader;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.apache.ws.jaxme.js.TextFile;
import org.apache.ws.jaxme.logging.AntProjectLoggerFactory;
import org.apache.ws.jaxme.logging.LoggerAccess;
import org.apache.ws.jaxme.logging.LoggerFactory;
import org.apache.ws.jaxme.util.ClassLoader;
import org.apache.ws.jaxme.xs.parser.impl.LocSAXException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.XMLCatalog;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;


/** 

An Ant task for running JaxMe, designed to be JAXB compatible.

*

This task supports the following attributes:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameDescriptionRequired/Default
schemaName of a schema file being compiledThis or nested <schema> elements are required
bindingAn external binding file being applied to the schema fileNo
forceSetting this option to true forces the up-to-date check to fail. * This option is mainly useful while working on the JaxMe generator. * For JaxMe users, which only change schema files, this option isn't of much * use. It is designed for JaxMe developers.No, false
packageSpecifies the generated Java sources package name. Overrides package specifications in * the schema bindings, if any.No, a package may be specified in the schema bindings.
targetSpecifies the target directory for generated Java source files. A package * structure will be created below that directory. For example, with target="src" and * package="org.acme", you will have files being created in "src/org/acme".No, defaults to the current directory
resourceTargetSpecifies the target directory for generated resource files. A package * structure will be created below that directory. For example, with target="src" and * package="org.acme", you will have files being created in "src/org/acme".No, defaults to the "target" directory
readonlyGenerated Java source files are in read-only mode, if true is specifiedNo, defaults to false
extensionIf set to true, the XJC binding compiler will run in the extension mode. * Otherwise, it will run in the strict conformance mode.No, defaults to false
stackSizeSpecify the thread stack size for the XJC binding compiler (J2SE SDK v1.4 or higher). * The XJC binding compiler can fail to compile large schemas with StackOverflowError and, * in that case, this option can be used to extend the stack size. If unspecified, the default * VM size is used. The format is equivalent to the -Xss command-line argument for Sun Microsystems JVM. * This value can be specified in bytes (stackSize="2097152"), kilobytes (stackSize="2048kb"), * or megabytes (stackSize="2mb").
* This attribute is ignored by the JaxMe ant task and present for compatibility reasons only.
No, defaults to false
removeOldOutputIf one or more nested <produces> elements are specified and this attribute is * set to true, then the Ant task will ensure that only generated files will remain. In other * words, if you had removed an element named "Foo" from the previous schema version, then the * Ant task will remove "Foo.java".No, defaults to false
validatingSets whether the XML schema parser is validating. By default it isn't.No, defaults to false
*

Besides the attributes, the ant task also supports the following nested elements:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameDescriptionRequired/Multiplicity
schemaMultiple schema files may be compiled in one or more nested <schema> * elements. The element syntax is equivalent to a nested <fileset>. * Use of a nested <schema> element is mutually exclusive with the use * of a "schema" attribute.0 - Unbounded
bindingMultiple external binding files may be specified. The element syntax is equivalent * to a nested <fileset>. Use of a nested <binding> element is * mutually exclusive with the use of a "binding" attribute.0 - Unbounded
classpathThis nested element is ignored by the JaxMe ant task and exists for compatibility * to the JAXB ant task only. In the case of JAXB it specifies a classpath for loading * user defined types (required in the case of a <javaType> customization) * 0 - Unbounded
argThis nested element is ignored by the JaxMe ant task and exists for compatibility * to the JAXB ant task only. In the case of JAXB it specifies additional command line * arguments being passed to the XJC. For details about the syntax, see the relevant * section in the Ant manual.
* This nested element can be used to specify various options not natively supported in * the xjc Ant task. For example, currently there is no native support for the following * xjc command-line options: *
    *
  • -nv
  • *
  • -catalog
  • *
  • -use-runtime
  • *
  • -schema
  • *
  • -dtd
  • *
  • -relaxng
  • *
*
0 - Unbounded
dtdIf this nested element is used to specify, that the input files * aren't instances of XML Schema, but DTD's. The nested element may * have an attribute "targetNamespace", which specifies an optional * target namespace. * No
dependsBy default the JaxMe Ant tasks up-to-date check considers the specified schema * and binding files only. This is insufficient, if other schema files are included, * imported or redefined.
* The nested <depends> element allows to specify additional files to consider * for the up-to-date check. Typically these are the additional schema files.
* Syntactically the <depends> element specifies a nested <fileset>.
0 - Unbounded
producesSpecifies the set of files being created by the JaxMe ant task. These files are * considered as targets for the up-to-date check. The syntax of the <produces> * element is equivalent to a nested <fileset>. However, you typically do not * need to set the "dir" attribute, because it defaults to the target directory.0 - Unbounded
propertySets a property value. These properties may be used by the various source * generators to configure the behaviour. For example, the JDBC schema reader uses * the options "jdbc.driver", "jdbc.url", "jdbc.user", and "jdbc.password" to * configure the database connection. Each property must have attributes "name" (the * property name) and "value" (the property value).0 - Unbounded
schemaReaderConfigures the schema reader to use. Defaults to * "org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader", which is the JAXB compliant * schema reader. An alternative schema readers is, for example, * "org.apache.ws.jaxme.generator.sg.impl.JaxMeSchemaReader" (a subclass of JAXBSchemaReader * with JaxMe specific extensions).0 - 1
sgFactoryChainIf the schema reader is an instance of * {@link org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader}, then you may * add instances of {@link org.apache.ws.jaxme.generator.sg.SGFactoryChain} to * the schema generation process. For example, such chains are used to create * the persistency layer. The best example is the * {@link org.apache.ws.jaxme.pm.generator.jdbc.JaxMeJdbcSG}, which is able to * populate the schema with tables and columns read from a database via * JDBC metadata.0 - Unbounded
xmlCatalogAdds an XML catalog to our internal catalog, which is used * to resolve external entities and URI's. See the * * Ant documentation for details on XML catalogs.0 - Unbounded
*

By default, the JaxMe ant task will always run the generator and create new files. This * is typically inappropriate for an ant script where your desire is to have as little * modifications as possible, because new files also need to be recompiled, which is slow * and time consuming.

*

To achieve a better behaviour, use the nested <produces> and <depends> elements. * If one or more <produces> element is specified, then an up-to-date check is performed * as follows: *

    *
  1. If either of the filesets specified by the <produces> elements is empty, * then the binding compiler will run.
  2. *
  3. Otherwise the sets of source and target files will be created. The set of source * files is specified by the "schema" and "binding" attributes, and by the nested * <schema>, <binding>, and <depends> elements. If any of the files * in the source set is newer than any of the files in the target set, then the * binding comoiler will run.
  4. *
* * @author Jochen Wiedmann */ public class XJCTask extends Task { /** This class is used to store the nested element "dtd". */ public static class Dtd { private String targetNamespace; /** Sets the target namespace being used. */ public void setTargetNamespace(String pTargetNamespace) { targetNamespace = pTargetNamespace; } /** Returns the target namespace being used. */ public String getTargetNamespace() { return targetNamespace; } } public static class Property { private String name; private String value; public void setName(String pName) { name = pName; } public void setValue(String pValue) { value = pValue; } public String getName() { return name; } public String getValue() { return value; } public void finish() { if (name == null) { throw new NullPointerException("Missing attribute: 'name'"); } if (value == null) { throw new NullPointerException("Missing attribute: 'value'"); } } } public static class ClassType { private String className; public void setClassName(String pClassName) { className = pClassName; } public String getClassName() { return className; } public Object getInstance(Class pInstanceClass) { if (className == null) { throw new NullPointerException("Missing attribute: 'class'"); } Class cl; try { cl = ClassLoader.getClass(className, pInstanceClass); } catch (ClassNotFoundException e) { throw new BuildException("Could not load class " + className, e); } catch (IllegalArgumentException e) { throw new BuildException(e); } try { return cl.newInstance(); } catch (Exception e) { throw new BuildException("The class " + className + " could not be instantiated: " + e.getMessage(), e); } } } private File binding, schema, target, resourceTarget; private String packageName; private boolean readOnly, extension, removeOldOutput, force, isValidating; private boolean isSettingLoggerFactory = true; private String stackSize; private List bindings = new ArrayList(), schemas = new ArrayList(); private List depends = new ArrayList(), produces = new ArrayList(); private List sgFactoryChains = new ArrayList(); private ClassType schemaReader; private List properties = new ArrayList(); private Dtd dtd; private final XMLCatalog xmlCatalog = new XMLCatalog(); /**

Sets a property value. These properties may be used by the various source * generators to configure the behaviour. For example, the JDBC schema reader uses * the options "jdbc.driver", "jdbc.url", "jdbc.user", and "jdbc.password" to * configure the database connection. Each property must have attributes "name" (the * property name) and "value" (the property value).

*/ public Property createProperty() { Property property = new Property(); properties.add(property); return property; } /**

Returns the configured property values. These properties may be used by the various source * generators to configure the behaviour. For example, the JDBC schema reader uses * the options "jdbc.driver", "jdbc.url", "jdbc.user", and "jdbc.password" to * configure the database connection. Each property must have attributes "name" (the * property name) and "value" (the property value).

*/ public Property[] getProperties() { return (Property[]) properties.toArray(new Property[properties.size()]); } /**

Configures the schema reader to use. Defaults to * "org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader", which is the JAXB compliant * schema reader. An alternative schema readers is, for example, * "org.apache.ws.jaxme.generator.sg.impl.JaxMeSchemaReader" (a subclass of JAXBSchemaReader * with JaxMe specific extensions).

*/ public ClassType createSchemaReader() { if (schemaReader != null) { throw new BuildException("Only one SchemaReader may be configured"); } schemaReader = new ClassType(); return schemaReader; } /**

Returns the configured schema reader to use. Defaults to * "org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader", which is the JAXB compliant * schema reader. An alternative schema readers is, for example, * "org.apache.ws.jaxme.generator.sg.impl.JaxMeSchemaReader" (a subclass of JAXBSchemaReader * with JaxMe specific extensions).

*/ public SchemaReader getSchemaReader() { if (schemaReader == null) { if (isExtension()) { return new JaxMeSchemaReader(); } else { return new JAXBSchemaReader(); } } else { return (SchemaReader) schemaReader.getInstance(SchemaReader.class); } } /**

Configures a new instance of * {@link org.apache.ws.jaxme.generator.sg.SGFactoryChain} being included into * the schema generation process. This option is valid only, if the schema reader * is an instance of {@link JAXBSchemaReader}, because its method * {@link JAXBSchemaReader#addSGFactoryChain(Class)} must be invoked.

*

The order of the chain elements may be significant. The schema reader * itself will always be the last element in the chain.

*/ public ClassType createSGFactoryChain() { ClassType result = new ClassType(); sgFactoryChains.add(result); return result; } /**

Returns the array of configured instances of * {@link org.apache.ws.jaxme.generator.sg.SGFactoryChain}. The order of * the array is significant. The schema reader itself will always be the * last element in the chain. Therefore, it is not present in the array.

*/ public ClassType[] getSGFactoryChains() { return (ClassType[]) sgFactoryChains.toArray(new ClassType[sgFactoryChains.size()]); } /**

Returns the ant tasks description.

*/ public String getDescription() { return "A JaxMe generator task converting XML schemata into Java source files."; } /**

Sets whether the XML schema parser is validating.

*/ public void setValidating(boolean pValidating) { isValidating = pValidating; } /**

Returns whether the XML schema parser is validating.

*/ public boolean isValidating() { return isValidating; } /**

Setting this option to true forces the up-to-date check to fail. * This option is mainly useful while working on the JaxMe generator. * For JaxMe users, which only change schema files, this option isn't of much * use. It is designed for JaxMe developers.

*/ public boolean isForce() { return force; } /**

Setting this option to true forces the up-to-date check to fail. * This option is mainly useful while working on the JaxMe generator. * For JaxMe users, which only change schema files, this option isn't of much * use. It is designed for JaxMe developers.

*/ public void setForce(boolean pForce) { force = pForce; } /**

Returns whether the ant task is setting the {@link LoggerFactory}. This * option is only useful, if you are using the Ant task from another Java class * and not from within Ant.

*/ public boolean isSettingLoggerFactory() { return isSettingLoggerFactory; } /**

Sets whether the ant task is setting the {@link LoggerFactory}. This * option is only useful, if you are using the Ant task from another Java class * and not from within Ant.

*/ public void setSettingLoggerFactory(boolean pIsSettingLoggerFactory) { isSettingLoggerFactory = pIsSettingLoggerFactory; } /**

Returns an external binding file being applied to the schema file.

*/ public File getBinding() { return binding; } /**

Sets an external binding file being applied to the schema file.

*/ public void setBinding(File pBinding) { binding = pBinding; } /**

Returns, whether the XJC binding compiler will run in the extension mode. * By default, it will run in the strict conformance mode.

*/ public boolean isExtension() { return extension; } /**

Sets, whether the XJC binding compiler will run in the extension mode. * By default, it will run in the strict conformance mode.

*/ public void setExtension(boolean pExtension) { extension = pExtension; } /**

Returns the generated Java sources package name. A non-null package specification * overrides package specifications in the schema bindings, if any.

*/ public String getPackage() { return packageName; } /**

Sets the generated Java sources package name. A non-null package specification * overrides package specifications in the schema bindings, if any.

*/ public void setPackage(String pPackageName) { packageName = pPackageName; } /** @deprecated Use {@link #setPackage(String)}. */ public void setPackageName(String pPackageName) { log("Warning: The 'packageName' attribute is updated to 'package', for compatibility reasons. Please update your build script.", Project.MSG_WARN); setPackage(pPackageName); } /**

Returns, whether generated Java source files are in read-only mode.

*/ public boolean isReadOnly() { return readOnly; } /**

Sets, whether generated Java source files are in read-only mode.

*/ public void setReadOnly(boolean pReadOnly) { readOnly = pReadOnly; } /**

If one or more nested <produces> elements are specified and * this attribute is set to true, then the Ant task will ensure that only * generated files will remain. In other words, if you had removed an element * named "Foo" from the previous schema version, then the Ant task will remove * "Foo.java".

*/ public boolean isRemoveOldOutput() { return removeOldOutput; } /**

If one or more nested <produces> elements are specified and * this attribute is set to true, then the Ant task will ensure that only * generated files will remain. In other words, if you had removed an element * named "Foo" from the previous schema version, then the Ant task will remove * "Foo.java".

*/ public void setRemoveOldOutput(boolean pRemoveOldOutput) { removeOldOutput = pRemoveOldOutput; } /**

Returns the name of the schema file being compiled.

*/ public File getSchema() { return schema; } /**

Sets the name of the schema file being compiled.

*/ public void setSchema(File pSchema) { schema = pSchema; } /**

Returns the thread stack size for the XJC binding compiler (J2SE SDK v1.4 or higher). * The XJC binding compiler can fail to compile large schemas with StackOverflowError and, * in that case, this option can be used to extend the stack size. If unspecified, the default * VM size is used. The format is equivalent to the -Xss command-line argument for Sun Microsystems JVM. * This value can be specified in bytes (stackSize="2097152"), kilobytes (stackSize="2048kb"), * or megabytes (stackSize="2mb").

*

This attribute is ignored by the JaxMe ant task and present for compatibility reasons only.

*/ public String getStackSize() { return stackSize; } /**

Sets the thread stack size for the XJC binding compiler (J2SE SDK v1.4 or higher). * The XJC binding compiler can fail to compile large schemas with StackOverflowError and, * in that case, this option can be used to extend the stack size. If unspecified, the default * VM size is used. The format is equivalent to the -Xss command-line argument for Sun Microsystems JVM. * This value can be specified in bytes (stackSize="2097152"), kilobytes (stackSize="2048kb"), * or megabytes (stackSize="2mb").

*

This attribute is ignored by the JaxMe ant task and present for compatibility reasons only.

*/ public void setStackSize(String pStackSize) { stackSize = pStackSize; log("The 'stackSize' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); } /** Returns the target directory for generating Java source files. A package * structure will be created below that directory. For example, with target="src" and * package="org.acme", you will have files being created in "src/org/acme". */ public File getTarget() { return target; } /** Sets the target directory for generating Java source files. A package * structure will be created below that directory. For example, with target="src" and * package="org.acme", you will have files being created in "src/org/acme". */ public void setTarget(File pTarget) { target = pTarget; } /** Returns the target directory for generating resource files. A package * structure will be created below that directory. For example, with target="src" * and package="org.acme", you will have files being created in "src/org/acme". * By default, the same directory is being used for Java source files and * resource files. */ public File getResourceTarget() { return resourceTarget; } /** Sets the target directory for generating resource files. A package * structure will be created below that directory. For example, with target="src" * and package="org.acme", you will have files being created in "src/org/acme". * By default, the same directory is being used for Java source files and * resource files. */ public void setResourceTarget(File pTarget) { resourceTarget = pTarget; } /**

Multiple schema files may be compiled in one or more nested <schema> * elements. The element syntax is equivalent to a nested <fileset>. * Use of a nested <schema> element is mutually exclusive with the use * of a "schema" attribute.

*/ public void addSchema(FileSet pSchemas) { if (getSchema() != null) { throw new BuildException("The 'schema' attribute and the nested 'schema' element are mutually exclusive."); } schemas.add(pSchemas); } /**

Multiple schema files may be compiled in one or more nested <schema> * elements. The element syntax is equivalent to a nested <fileset>. * Use of a nested <schema> element is mutually exclusive with the use * of a "schema" attribute.

*/ public FileSet[] getSchemas() { return (FileSet[]) schemas.toArray(new FileSet[schemas.size()]); } /**

Multiple external binding files may be specified. The element syntax is equivalent * to a nested <fileset>. Use of a nested <binding> element is * mutually exclusive with the use of a "binding" attribute.

*/ public void addBinding(FileSet pBindings) { if (getBinding() != null) { throw new BuildException("The 'binding' attribute and the nested 'binding' element are mutually exclusive."); } bindings.add(pBindings); } /**

Multiple external binding files may be specified. The element syntax is equivalent * to a nested <fileset>. Use of a nested <binding> element is * mutually exclusive with the use of a "binding" attribute.

*/ public FileSet[] getBindings() { return (FileSet[]) bindings.toArray(new FileSet[bindings.size()]); } /**

This nested element is ignored by the JaxMe ant task and exists for compatibility * to the JAXB ant task only. In the case of JAXB it specifies a classpath for loading * user defined types (required in the case of a <javaType> customization)

*/ public void addClasspath(Path pClasspath) { log("The 'classpath' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); } /**

This nested element is ignored by the JaxMe ant task and exists for compatibility * to the JAXB ant task only. In the case of JAXB it specifies additional command line * arguments being passed to the XJC. For details about the syntax, see the relevant * section in the Ant manual.
* This nested element can be used to specify various options not natively supported in * the xjc Ant task. For example, currently there is no native support for the following * xjc command-line options: *

    *
  • -nv
  • *
  • -catalog
  • *
  • -use-runtime
  • *
  • -schema
  • *
  • -dtd
  • *
  • -relaxng
  • *

*/ public void addArg(Commandline.Argument pArg) { log("The 'arg' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); } /**

By default the JaxMe Ant tasks up-to-date check considers the specified schema * and binding files only. This is insufficient, if other schema files are included, * imported or redefined.
* The nested <depends> element allows to specify additional files to consider * for the up-to-date check. Typically these are the additional schema files.
* Syntactically the <depends> element specifies a nested <fileset>.

*/ public void addDepends(FileSet pDepends) { depends.add(pDepends); } /**

By default the JaxMe Ant tasks up-to-date check considers the specified schema * and binding files only. This is insufficient, if other schema files are included, * imported or redefined.
* The nested <depends> element allows to specify additional files to consider * for the up-to-date check. Typically these are the additional schema files.
* Syntactically the <depends> element specifies a nested <fileset>.

*/ public FileSet[] getDepends() { return (FileSet[]) depends.toArray(new FileSet[depends.size()]); } /**

Specifies the set of files being created by the JaxMe ant task. These files are * considered as targets for the up-to-date check. The syntax of the <produces> * element is equivalent to a nested <fileset>.

*/ public FileSet createProduces() { FileSet result = new FileSet(); produces.add(result); return result; } /**

Returns the set of files being created by the JaxMe ant task. These files are * considered as targets for the up-to-date check. The syntax of the <produces> * element is equivalent to a nested <fileset>.

*/ public FileSet[] getProduces() { return (FileSet[]) produces.toArray(new FileSet[produces.size()]); } /** Creates a nested element "dtd". */ public Dtd createDtd() { if (dtd == null) { dtd = new Dtd(); return dtd; } else { throw new BuildException("Multiple nested 'dtd' elements are forbidden.", getLocation()); } } /** Returns the nested element "dtd". */ public Dtd getDtd() { return dtd; } public void finish() { if (getSchema() == null && getSchemas().length == 0) { throw new BuildException("Either of the 'schema' attribute or the nested 'schema' elements must be given.", getLocation()); } } private File[] getFiles(FileSet[] pFileSets) { List list = new ArrayList(); for (int i = 0; i < pFileSets.length; i++) { FileSet fileSet = pFileSets[i]; DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject()); scanner.scan(); String[] files = scanner.getIncludedFiles(); for (int j = 0; j < files.length; j++) { list.add(new File(fileSet.getDir(getProject()), files[j])); } } return (File[]) list.toArray(new File[list.size()]); } private File[] getSchemaFiles() { if (getSchema() != null) { return new File[]{getSchema()}; } else { return getFiles(getSchemas()); } } private File[] getBindingFiles() { if (getBinding() != null) { return new File[]{getBinding()}; } else { return getFiles(getBindings()); } } private File[] getDependsFiles() { return getFiles(getDepends()); } public boolean isUpToDate(File[] pSchemaFiles, File[] pBindingFiles, File[] pDependsFiles, List pProducesList) { FileSet[] myProduces = getProduces(); if (myProduces.length == 0) { log("No nested 'produces' elements, up-to-date check returns false", Project.MSG_VERBOSE); return false; } boolean result = true; long firstTarget = 0; File firstTargetFile = null; for (int i = 0; i < myProduces.length; i++) { File dir = myProduces[i].getDir(getProject()); if (dir == null) { dir = getTarget(); if (dir == null) { dir = getProject().getBaseDir(); } myProduces[i].setDir(dir); } if (!dir.exists()) { log("The directory specified by the nested 'produces' element #" + i + " does not exist, up-to-date check returns false", Project.MSG_VERBOSE); result = false; continue; } DirectoryScanner scanner = myProduces[i].getDirectoryScanner(getProject()); scanner.scan(); String[] files = scanner.getIncludedFiles(); if (files.length == 0) { log("The fileset specified by the nested 'produces' element #" + i + " is empty, up-to-date check returns false", Project.MSG_VERBOSE); result = false; } for (int j = 0; j < files.length; j++) { File f = new File(dir, files[j]).getAbsoluteFile(); if (pProducesList != null) { pProducesList.add(f); } long l = f.lastModified(); if (l == -1) { log("Unable to determine timestamp of target file " + f + ", up-to-date check returns false.", Project.MSG_VERBOSE); result = false; } if (firstTargetFile == null || firstTarget > l) { firstTargetFile = f; firstTarget = l; } } } if (isForce()) { log("Force option is set, up-to-date check returns false", Project.MSG_VERBOSE); result = false; } if (!result) { return false; } List sourceFiles = new ArrayList(); for (int i = 0; i < pSchemaFiles.length; i++) { sourceFiles.add(pSchemaFiles[i]); } for (int i = 0; i < pBindingFiles.length; i++) { sourceFiles.add(pBindingFiles[i]); } for (int i = 0; i < pDependsFiles.length; i++) { sourceFiles.add(pDependsFiles[i]); } long lastSource = 0; File lastSourceFile = null; for (Iterator iter = sourceFiles.iterator(); iter.hasNext(); ) { File f = (File) iter.next(); long l = f.lastModified(); if (l == -1) { log("Unable to determine timestamp of source file " + f + ", up-to-date check returns false.", Project.MSG_VERBOSE); result = false; } if (lastSourceFile == null || lastSource < l) { lastSource = l; lastSourceFile = f; } } if (lastSourceFile == null) { log("No source files found, up-to-date check returns false.", Project.MSG_VERBOSE); return false; } if (!result) { return false; } try { URL url = Generator.class.getClassLoader().getResource(Generator.class.getName().replace('.', '/') + ".class"); if (url != null) { long l = url.openConnection().getLastModified(); if (l != 0 && lastSource < l) { log("Generator class is newer than any schema files, using Generator classes timestamp as schema timestamp.", Project.MSG_DEBUG); lastSource = l; } } } catch (IOException e) { } if (lastSource >= firstTarget) { log("Source file " + lastSourceFile + " is more recent than target file " + firstTargetFile + ", up-to-date check returns false", Project.MSG_VERBOSE); return false; } log("All target files are up-to-date.", Project.MSG_VERBOSE); return true; } public class MyClassLoader extends java.lang.ClassLoader { private java.lang.ClassLoader parent; public java.lang.ClassLoader getMyParent() { return parent; } public MyClassLoader(java.lang.ClassLoader pParent) { super(XJCTask.this.getClass().getClassLoader()); parent = pParent; } public Class findClass(String name) throws ClassNotFoundException { return parent.loadClass(name); } public URL findResource(String resource) { return parent.getResource(resource); } public Enumeration findResources(String resource) throws IOException { return parent.getResources(resource); } } public void stopLogging(LoggerFactory pFactory) { if (pFactory != null) { LoggerAccess.setLoggerFactory(pFactory); } } public LoggerFactory initLogging() { if (!isSettingLoggerFactory()) { return null; } LoggerFactory loggerFactory = LoggerAccess.getLoggerFactory(); if (!(loggerFactory instanceof AntProjectLoggerFactory)) { loggerFactory = new AntProjectLoggerFactory(this); LoggerAccess.setLoggerFactory(loggerFactory); return loggerFactory; } return null; } /** * Initialize internal instance of XMLCatalog */ public void init() { super.init(); xmlCatalog.setProject(getProject()); } /** Adds an XML catalog to our internal catalog. See the * * Ant documentation for details on XML catalogs. * @param xmlCatalog the XMLCatalog instance to use to look up DTDs */ public void addConfiguredXMLCatalog(XMLCatalog pXmlCatalog) { xmlCatalog.addConfiguredXMLCatalog(pXmlCatalog); } public void execute() { java.lang.ClassLoader parent = Thread.currentThread().getContextClassLoader(); MyClassLoader cl = new MyClassLoader(parent == null ? getClass().getClassLoader() : parent); LoggerFactory loggerFactory = initLogging(); try { Thread.currentThread().setContextClassLoader(cl); File[] schemaFiles = getSchemaFiles(); if (schemaFiles.length == 0) { log("No schema files specified", Project.MSG_WARN); return; } File[] bindingFiles = getBindingFiles(); File[] dependFiles = getDependsFiles(); List producesFiles = isRemoveOldOutput() ? new ArrayList() : null; if (isUpToDate(schemaFiles, bindingFiles, dependFiles, producesFiles)) { return; } Set producesFilesSet = null; if (producesFiles != null) { producesFilesSet = new HashSet(); for (Iterator iter = producesFiles.iterator(); iter.hasNext(); ) { File f = ((File) iter.next()); producesFilesSet.add(f); } } Generator generator = new GeneratorImpl(); generator.setEntityResolver(xmlCatalog); generator.setForcingOverwrite(isForce()); generator.setSettingReadOnly(isReadOnly()); generator.setValidating(isValidating()); for (int i = 0; i < bindingFiles.length; i++) { try { String systemId = bindingFiles[i].toURL().toExternalForm(); generator.addBindings(new InputSource(systemId)); } catch (Exception e) { throw new BuildException("Failed to read external binding file " + bindingFiles[i] + ": " + e.getMessage(), e, getLocation()); } } if (getPackage() != null) { generator.setProperty("jaxme.package.name", getPackage()); } Dtd myDtd = getDtd(); if (myDtd != null) { generator.setProperty("jaxme.dtd.input", "true"); if (myDtd.getTargetNamespace() != null) { generator.setProperty("jaxme.dtd.targetNamespace", myDtd.getTargetNamespace()); } } Property[] myProperties = getProperties(); for (int i = 0; i < myProperties.length; i++) { Property ot = myProperties[i]; log("Option " + ot.getName() + "=" + ot.getValue(), Project.MSG_VERBOSE); generator.setProperty(ot.getName(), ot.getValue()); } SchemaReader reader = getSchemaReader(); if (reader instanceof JAXBSchemaReader) { ((JAXBSchemaReader) reader).setSupportingExtensions(isExtension()); } generator.setSchemaReader(reader); reader.setGenerator(generator); generator.setTargetDirectory(getTarget()); generator.setResourceTargetDirectory(getResourceTarget()); ClassType[] mySgFactoryChains = getSGFactoryChains(); if (mySgFactoryChains.length > 0) { if (!(reader instanceof JAXBSchemaReader)) { throw new BuildException("The nested child element 'sgFactoryChain' is valid only, if the schema reader is an instance of " + JAXBSchemaReader.class.getName(), getLocation()); } for (int i = 0; i < mySgFactoryChains.length; i++) { ClassType ct = mySgFactoryChains[i]; Class c; try { c = cl.loadClass(ct.getClassName()); } catch (ClassNotFoundException e) { throw new BuildException("Failed to load SGFactoryChain implementation class " + ct.getClassName(), getLocation()); } if (!SGFactoryChain.class.isAssignableFrom(c)) { throw new BuildException("The SGFactoryChain class " + c.getName() + " is not implementing " + SGFactoryChain.class.getName(), getLocation()); } reader.addSGFactoryChain(c); } } for (int i = 0; i < schemaFiles.length; i++) { log("Reading schema file " + schemaFiles[i], Project.MSG_VERBOSE); try { SchemaSG schemaSG = generator.generate(schemaFiles[i]); if (producesFilesSet != null) { JavaSourceFactory jsf = schemaSG.getJavaSourceFactory(); File targetDirectory = getTarget(); for (Iterator iter = jsf.getJavaSources(); iter.hasNext(); ) { JavaSource js = (JavaSource) iter.next(); File f = jsf.getLocation(targetDirectory, js).getAbsoluteFile(); producesFilesSet.remove(f); } for (Iterator iter = jsf.getTextFiles(); iter.hasNext(); ) { TextFile tf = (TextFile) iter.next(); File f = jsf.getLocation(targetDirectory, tf).getAbsoluteFile(); producesFilesSet.remove(f); } } } catch (SAXParseException e) { String msg = LocSAXException.formatMsg(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), e.getPublicId(), e.getSystemId(), e.getLineNumber(), e.getColumnNumber()); throw new BuildException(msg, e, getLocation()); } catch (Exception e) { String msg = e.getMessage(); if (msg == null) { msg = e.getClass().getName(); } throw new BuildException(schemaFiles[i] + ": " + msg, e, getLocation()); } } if (producesFilesSet != null) { for (Iterator iter = producesFilesSet.iterator(); iter.hasNext(); ) { File f = (File) iter.next(); log("Removing orphan file " + f, Project.MSG_VERBOSE); if (!f.delete()) { throw new BuildException("Unable to delete file " + f); } } } } finally { Thread.currentThread().setContextClassLoader(parent); stopLogging(loggerFactory); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy