JomcModelTask.java
- /*
- * Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * o Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * o 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.
- *
- * THIS SOFTWARE IS PROVIDED "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 AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * $JOMC: JomcModelTask.java 5043 2015-05-27 07:03:39Z schulte $
- *
- */
- package org.jomc.ant;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.SocketTimeoutException;
- import java.net.URISyntaxException;
- import java.net.URL;
- import java.net.URLConnection;
- import java.util.HashSet;
- import java.util.Set;
- import java.util.logging.Level;
- import javax.xml.bind.JAXBElement;
- import javax.xml.bind.JAXBException;
- import javax.xml.bind.Unmarshaller;
- import javax.xml.transform.Source;
- import javax.xml.transform.stream.StreamSource;
- import org.apache.tools.ant.BuildException;
- import org.apache.tools.ant.Project;
- import org.jomc.ant.types.KeyValueType;
- import org.jomc.ant.types.ModuleResourceType;
- import org.jomc.ant.types.ResourceType;
- import org.jomc.model.Module;
- import org.jomc.model.Modules;
- import org.jomc.model.modlet.DefaultModelProcessor;
- import org.jomc.model.modlet.DefaultModelProvider;
- import org.jomc.model.modlet.DefaultModelValidator;
- import org.jomc.model.modlet.ModelHelper;
- import org.jomc.modlet.Model;
- import org.jomc.modlet.ModelContext;
- import org.jomc.modlet.ModelException;
- import org.jomc.tools.modlet.ToolsModelProcessor;
- import org.jomc.tools.modlet.ToolsModelProvider;
- /**
- * Base class for executing model based tasks.
- *
- * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
- * @version $JOMC: JomcModelTask.java 5043 2015-05-27 07:03:39Z schulte $
- */
- public class JomcModelTask extends JomcTask
- {
- /**
- * Controls model object class path resolution.
- */
- private boolean modelObjectClasspathResolutionEnabled = true;
- /**
- * The location to search for modules.
- */
- private String moduleLocation;
- /**
- * The location to search for transformers.
- */
- private String transformerLocation;
- /**
- * Module resources.
- */
- private Set<ModuleResourceType> moduleResources;
- /**
- * The flag indicating JAXP schema validation of model resources is enabled.
- */
- private boolean modelResourceValidationEnabled = true;
- /**
- * The flag indicating Java validation is enabled.
- */
- private boolean javaValidationEnabled = true;
- /**
- * Creates a new {@code JomcModelTask} instance.
- */
- public JomcModelTask()
- {
- super();
- }
- /**
- * Gets the location searched for modules.
- *
- * @return The location searched for modules or {@code null}.
- *
- * @see #setModuleLocation(java.lang.String)
- */
- public final String getModuleLocation()
- {
- return this.moduleLocation;
- }
- /**
- * Sets the location to search for modules.
- *
- * @param value The new location to search for modules or {@code null}.
- *
- * @see #getModuleLocation()
- */
- public final void setModuleLocation( final String value )
- {
- this.moduleLocation = value;
- }
- /**
- * Gets the location searched for transformers.
- *
- * @return The location searched for transformers or {@code null}.
- *
- * @see #setTransformerLocation(java.lang.String)
- */
- public final String getTransformerLocation()
- {
- return this.transformerLocation;
- }
- /**
- * Sets the location to search for transformers.
- *
- * @param value The new location to search for transformers or {@code null}.
- *
- * @see #getTransformerLocation()
- */
- public final void setTransformerLocation( final String value )
- {
- this.transformerLocation = value;
- }
- /**
- * Gets a flag indicating model object class path resolution is enabled.
- *
- * @return {@code true}, if model object class path resolution is enabled; {@code false}, else.
- *
- * @see #setModelObjectClasspathResolutionEnabled(boolean)
- */
- public final boolean isModelObjectClasspathResolutionEnabled()
- {
- return this.modelObjectClasspathResolutionEnabled;
- }
- /**
- * Sets the flag indicating model object class path resolution is enabled.
- *
- * @param value {@code true}, to enable model object class path resolution; {@code false}, to disable model object
- * class path resolution.
- *
- * @see #isModelObjectClasspathResolutionEnabled()
- */
- public final void setModelObjectClasspathResolutionEnabled( final boolean value )
- {
- this.modelObjectClasspathResolutionEnabled = value;
- }
- /**
- * Gets a set of module resources.
- * <p>
- * This accessor method returns a reference to the live set, not a snapshot. Therefore any modification you make
- * to the returned set will be present inside the object. This is why there is no {@code set} method for the
- * module resources property.
- * </p>
- *
- * @return A set of module resources.
- *
- * @see #createModuleResource()
- */
- public Set<ModuleResourceType> getModuleResources()
- {
- if ( this.moduleResources == null )
- {
- this.moduleResources = new HashSet<ModuleResourceType>();
- }
- return this.moduleResources;
- }
- /**
- * Creates a new {@code moduleResource} element instance.
- *
- * @return A new {@code moduleResource} element instance.
- *
- * @see #getModuleResources()
- */
- public ModuleResourceType createModuleResource()
- {
- final ModuleResourceType moduleResource = new ModuleResourceType();
- this.getModuleResources().add( moduleResource );
- return moduleResource;
- }
- /**
- * Gets a flag indicating JAXP schema validation of model resources is enabled.
- *
- * @return {@code true}, if JAXP schema validation of model resources is enabled; {@code false}, else.
- *
- * @see #setModelResourceValidationEnabled(boolean)
- */
- public final boolean isModelResourceValidationEnabled()
- {
- return this.modelResourceValidationEnabled;
- }
- /**
- * Sets the flag indicating JAXP schema validation of model resources is enabled.
- *
- * @param value {@code true}, to enable JAXP schema validation of model resources; {@code false}, to disable JAXP
- * schema validation of model resources.
- *
- * @see #isModelResourceValidationEnabled()
- */
- public final void setModelResourceValidationEnabled( final boolean value )
- {
- this.modelResourceValidationEnabled = value;
- }
- /**
- * Gets a flag indicating Java validation is enabled.
- *
- * @return {@code true}, if Java validation is enabled; {@code false}, else.
- *
- * @see #setJavaValidationEnabled(boolean)
- *
- * @since 1.4
- */
- public final boolean isJavaValidationEnabled()
- {
- return this.javaValidationEnabled;
- }
- /**
- * Sets the flag indicating Java validation is enabled.
- *
- * @param value {@code true}, to enable Java validation; {@code false}, to disable Java validation.
- *
- * @see #isJavaValidationEnabled()
- *
- * @since 1.4
- */
- public final void setJavaValidationEnabled( final boolean value )
- {
- this.javaValidationEnabled = value;
- }
- /**
- * Gets a {@code Model} from a given {@code ModelContext}.
- *
- * @param context The context to get a {@code Model} from.
- *
- * @return The {@code Model} from {@code context}.
- *
- * @throws NullPointerException if {@code contexŧ} is {@code null}.
- * @throws BuildException if no model is found.
- * @throws ModelException if getting the model fails.
- *
- * @see #getModel()
- * @see #isModelObjectClasspathResolutionEnabled()
- * @see #isModelProcessingEnabled()
- */
- @Override
- public Model getModel( final ModelContext context ) throws BuildException, ModelException
- {
- if ( context == null )
- {
- throw new NullPointerException( "context" );
- }
- Model model = new Model();
- model.setIdentifier( this.getModel() );
- Modules modules = new Modules();
- ModelHelper.setModules( model, modules );
- Unmarshaller unmarshaller = null;
- for ( final ResourceType resource : this.getModuleResources() )
- {
- final URL[] urls = this.getResources( context, resource.getLocation() );
- if ( urls.length == 0 )
- {
- if ( resource.isOptional() )
- {
- this.logMessage( Level.WARNING, Messages.getMessage( "moduleResourceNotFound",
- resource.getLocation() ) );
- }
- else
- {
- throw new BuildException( Messages.getMessage( "moduleResourceNotFound", resource.getLocation() ),
- this.getLocation() );
- }
- }
- for ( int i = urls.length - 1; i >= 0; i-- )
- {
- InputStream in = null;
- boolean suppressExceptionOnClose = true;
- try
- {
- this.logMessage( Level.FINEST, Messages.getMessage( "reading", urls[i].toExternalForm() ) );
- final URLConnection con = urls[i].openConnection();
- con.setConnectTimeout( resource.getConnectTimeout() );
- con.setReadTimeout( resource.getReadTimeout() );
- con.connect();
- in = con.getInputStream();
- final Source source = new StreamSource( in, urls[i].toURI().toASCIIString() );
- if ( unmarshaller == null )
- {
- unmarshaller = context.createUnmarshaller( this.getModel() );
- if ( this.isModelResourceValidationEnabled() )
- {
- unmarshaller.setSchema( context.createSchema( this.getModel() ) );
- }
- }
- Object o = unmarshaller.unmarshal( source );
- if ( o instanceof JAXBElement<?> )
- {
- o = ( (JAXBElement<?>) o ).getValue();
- }
- if ( o instanceof Module )
- {
- modules.getModule().add( (Module) o );
- }
- else
- {
- this.log( Messages.getMessage( "unsupportedModuleResource", urls[i].toExternalForm() ),
- Project.MSG_WARN );
- }
- suppressExceptionOnClose = false;
- }
- catch ( final SocketTimeoutException e )
- {
- String message = Messages.getMessage( e );
- message = Messages.getMessage( "resourceTimeout", message != null ? " " + message : "" );
- if ( resource.isOptional() )
- {
- this.getProject().log( message, e, Project.MSG_WARN );
- }
- else
- {
- throw new BuildException( message, e, this.getLocation() );
- }
- }
- catch ( final IOException e )
- {
- String message = Messages.getMessage( e );
- message = Messages.getMessage( "resourceFailure", message != null ? " " + message : "" );
- if ( resource.isOptional() )
- {
- this.getProject().log( message, e, Project.MSG_WARN );
- }
- else
- {
- throw new BuildException( message, e, this.getLocation() );
- }
- }
- catch ( final URISyntaxException e )
- {
- throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
- }
- catch ( final JAXBException e )
- {
- String message = Messages.getMessage( e );
- if ( message == null )
- {
- message = Messages.getMessage( e.getLinkedException() );
- }
- throw new BuildException( message, e, this.getLocation() );
- }
- finally
- {
- try
- {
- if ( in != null )
- {
- in.close();
- }
- }
- catch ( final IOException e )
- {
- if ( suppressExceptionOnClose )
- {
- this.logMessage( Level.SEVERE, Messages.getMessage( e ), e );
- }
- else
- {
- throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
- }
- }
- }
- }
- }
- model = context.findModel( model );
- modules = ModelHelper.getModules( model );
- if ( modules != null && this.isModelObjectClasspathResolutionEnabled() )
- {
- final Module classpathModule =
- modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), context.getClassLoader() );
- if ( classpathModule != null && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null )
- {
- modules.getModule().add( classpathModule );
- }
- }
- if ( this.isModelProcessingEnabled() )
- {
- model = context.processModel( model );
- }
- return model;
- }
- /**
- * {@inheritDoc}
- */
- @Override
- public void preExecuteTask() throws BuildException
- {
- super.preExecuteTask();
- this.assertLocationsNotNull( this.getModuleResources() );
- }
- /**
- * {@inheritDoc}
- */
- @Override
- public ModelContext newModelContext( final ClassLoader classLoader ) throws ModelException
- {
- final ModelContext modelContext = super.newModelContext( classLoader );
- if ( this.getTransformerLocation() != null )
- {
- modelContext.setAttribute( DefaultModelProcessor.TRANSFORMER_LOCATION_ATTRIBUTE_NAME,
- this.getTransformerLocation() );
- }
- if ( this.getModuleLocation() != null )
- {
- modelContext.setAttribute( DefaultModelProvider.MODULE_LOCATION_ATTRIBUTE_NAME, this.getModuleLocation() );
- }
- modelContext.setAttribute( ToolsModelProvider.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME,
- this.isModelObjectClasspathResolutionEnabled() );
- modelContext.setAttribute( ToolsModelProcessor.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME,
- this.isModelObjectClasspathResolutionEnabled() );
- modelContext.setAttribute( DefaultModelProvider.VALIDATING_ATTRIBUTE_NAME,
- this.isModelResourceValidationEnabled() );
- modelContext.setAttribute( DefaultModelValidator.VALIDATE_JAVA_ATTRIBUTE_NAME, this.isJavaValidationEnabled() );
- for ( int i = 0, s0 = this.getModelContextAttributes().size(); i < s0; i++ )
- {
- final KeyValueType kv = this.getModelContextAttributes().get( i );
- final Object object = kv.getObject( this.getLocation() );
- if ( object != null )
- {
- modelContext.setAttribute( kv.getKey(), object );
- }
- else
- {
- modelContext.clearAttribute( kv.getKey() );
- }
- }
- return modelContext;
- }
- /**
- * {@inheritDoc}
- */
- @Override
- public JomcModelTask clone()
- {
- final JomcModelTask clone = (JomcModelTask) super.clone();
- if ( this.moduleResources != null )
- {
- clone.moduleResources = new HashSet<ModuleResourceType>( this.moduleResources.size() );
- for ( final ModuleResourceType e : this.moduleResources )
- {
- clone.moduleResources.add( e.clone() );
- }
- }
- return clone;
- }
- }