AbstractModletCommand.java
/*
* Copyright (C) 2009 Christian Schulte <cs@schulte.it>
* 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: AbstractModletCommand.java 5303 2016-08-30 02:31:20Z schulte $
*
*/
package org.jomc.cli.commands;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import org.apache.commons.cli.CommandLine;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jomc.model.ModelObject;
import org.jomc.modlet.DefaultModelContext;
import org.jomc.modlet.DefaultModletProvider;
import org.jomc.modlet.ModelContext;
import org.jomc.modlet.ModelContextFactory;
import org.jomc.modlet.ModelException;
import org.jomc.modlet.ModelValidationReport;
import org.jomc.modlet.Modlet;
import org.jomc.modlet.ModletObject;
import org.jomc.modlet.ModletProcessor;
import org.jomc.modlet.ModletProvider;
import org.jomc.modlet.ModletValidator;
import org.jomc.modlet.Modlets;
import org.jomc.modlet.ObjectFactory;
import org.jomc.modlet.Schema;
import org.jomc.modlet.Schemas;
import org.jomc.modlet.Service;
import org.jomc.modlet.ServiceFactory;
import org.jomc.modlet.Services;
/**
* {@code ModelContext} based command implementation.
*
* @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
*/
public abstract class AbstractModletCommand extends AbstractCommand
{
/**
* Constant to prefix relative resource names with.
*/
private static final String ABSOLUTE_RESOURCE_NAME_PREFIX =
"/" + AbstractModletCommand.class.getPackage().getName().replace( '.', '/' ) + "/";
/**
* Creates a new {@code AbstractModletCommand} instance.
*/
public AbstractModletCommand()
{
super();
}
@Override
public org.apache.commons.cli.Options getOptions()
{
final org.apache.commons.cli.Options options = super.getOptions();
options.addOption( Options.CLASSPATH_OPTION );
options.addOption( Options.DOCUMENTS_OPTION );
options.addOption( Options.MODEL_CONTEXT_FACTORY_CLASSNAME_OPTION );
options.addOption( Options.MODEL_OPTION );
options.addOption( Options.MODLET_SCHEMA_SYSTEM_ID_OPTION );
options.addOption( Options.MODLET_LOCATION_OPTION );
options.addOption( Options.PROVIDER_LOCATION_OPTION );
options.addOption( Options.PLATFORM_PROVIDER_LOCATION_OPTION );
options.addOption( Options.NO_MODLET_RESOURCE_VALIDATION_OPTION );
return options;
}
/**
* Creates a new {@code Transformer} from a given {@code Source}.
*
* @param source The source to initialize the transformer with.
*
* @return A {@code Transformer} backed by {@code source}.
*
* @throws NullPointerException if {@code source} is {@code null}.
* @throws CommandExecutionException if creating a transformer fails.
*/
protected Transformer createTransformer( final Source source ) throws CommandExecutionException
{
if ( source == null )
{
throw new NullPointerException( "source" );
}
final ErrorListener errorListener = new ErrorListener()
{
public void warning( final TransformerException exception ) throws TransformerException
{
log( Level.WARNING, null, exception );
}
public void error( final TransformerException exception ) throws TransformerException
{
throw exception;
}
public void fatalError( final TransformerException exception ) throws TransformerException
{
throw exception;
}
};
try
{
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setErrorListener( errorListener );
final Transformer transformer = transformerFactory.newTransformer( source );
transformer.setErrorListener( errorListener );
for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() )
{
transformer.setParameter( e.getKey().toString(), e.getValue() );
}
return transformer;
}
catch ( final TransformerConfigurationException e )
{
throw new CommandExecutionException( Messages.getMessage( e ), e );
}
}
/**
* Creates a new {@code ModelContext} for a given {@code CommandLine} and {@code ClassLoader}.
*
* @param commandLine The {@code CommandLine} to create a new {@code ModelContext} with.
* @param classLoader The {@code ClassLoader} to create a new {@code ModelContext} with.
*
* @return A new {@code ModelContext} for {@code classLoader} setup using {@code commandLine}.
*
* @throws NullPointerException if {@code commandLine} is {@code null}.
* @throws CommandExecutionException if creating an new {@code ModelContext} fails.
*/
protected ModelContext createModelContext( final CommandLine commandLine, final ClassLoader classLoader )
throws CommandExecutionException
{
if ( commandLine == null )
{
throw new NullPointerException( "commandLine" );
}
final ModelContextFactory modelContextFactory =
commandLine.hasOption( Options.MODEL_CONTEXT_FACTORY_CLASSNAME_OPTION.getOpt() )
? ModelContextFactory.newInstance( commandLine.getOptionValue(
Options.MODEL_CONTEXT_FACTORY_CLASSNAME_OPTION.getOpt() ) )
: ModelContextFactory.newInstance();
final ModelContext modelContext = modelContextFactory.newModelContext( classLoader );
modelContext.setExecutorService( this.getExecutorService( commandLine ) );
if ( commandLine.hasOption( Options.MODLET_SCHEMA_SYSTEM_ID_OPTION.getOpt() ) )
{
modelContext.setModletSchemaSystemId(
commandLine.getOptionValue( Options.MODLET_SCHEMA_SYSTEM_ID_OPTION.getOpt() ) );
}
modelContext.setLogLevel( this.getLogLevel() );
modelContext.getListeners().add( new ModelContext.Listener()
{
@Override
public void onLog( final Level level, final String message, final Throwable t )
{
super.onLog( level, message, t );
log( level, message, t );
}
} );
if ( commandLine.hasOption( Options.PROVIDER_LOCATION_OPTION.getOpt() ) )
{
modelContext.setAttribute( DefaultModelContext.PROVIDER_LOCATION_ATTRIBUTE_NAME,
commandLine.getOptionValue( Options.PROVIDER_LOCATION_OPTION.getOpt() ) );
}
if ( commandLine.hasOption( Options.PLATFORM_PROVIDER_LOCATION_OPTION.getOpt() ) )
{
modelContext.setAttribute(
DefaultModelContext.PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME,
commandLine.getOptionValue( Options.PLATFORM_PROVIDER_LOCATION_OPTION.getOpt() ) );
}
if ( commandLine.hasOption( Options.MODLET_LOCATION_OPTION.getOpt() ) )
{
modelContext.setAttribute( DefaultModletProvider.MODLET_LOCATION_ATTRIBUTE_NAME,
commandLine.getOptionValue( Options.MODLET_LOCATION_OPTION.getOpt() ) );
}
modelContext.setAttribute( DefaultModletProvider.VALIDATING_ATTRIBUTE_NAME,
!commandLine.hasOption( Options.NO_MODLET_RESOURCE_VALIDATION_OPTION.getOpt() ) );
return modelContext;
}
/**
* Gets the identifier of the model to process.
*
* @param commandLine The command line to get the identifier of the model to process from.
*
* @return The identifier of the model to process.
*
* @throws NullPointerException if {@code commandLine} is {@code null}.
*/
protected String getModel( final CommandLine commandLine )
{
if ( commandLine == null )
{
throw new NullPointerException( "commandLine" );
}
return commandLine.hasOption( Options.MODEL_OPTION.getOpt() )
? commandLine.getOptionValue( Options.MODEL_OPTION.getOpt() )
: ModelObject.MODEL_PUBLIC_ID;
}
/**
* Logs a validation report.
*
* @param validationReport The report to log.
* @param marshaller The marshaller to use for logging the report.
*
* @throws CommandExecutionException if logging a report detail element fails.
*/
protected void log( final ModelValidationReport validationReport, final Marshaller marshaller )
throws CommandExecutionException
{
Object jaxbFormattedOutput;
try
{
jaxbFormattedOutput = marshaller.getProperty( Marshaller.JAXB_FORMATTED_OUTPUT );
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
}
catch ( final PropertyException e )
{
this.log( Level.INFO, Messages.getMessage( e ), e );
jaxbFormattedOutput = null;
}
try
{
for ( final ModelValidationReport.Detail d : validationReport.getDetails() )
{
if ( this.isLoggable( d.getLevel() ) )
{
this.log( d.getLevel(), "o " + d.getMessage(), null );
if ( d.getElement() != null && this.getLogLevel().intValue() < Level.INFO.intValue() )
{
final StringWriter stringWriter = new StringWriter();
marshaller.marshal( d.getElement(), stringWriter );
this.log( d.getLevel(), stringWriter.toString(), null );
}
}
}
}
catch ( final JAXBException e )
{
String message = Messages.getMessage( e );
if ( message == null )
{
message = Messages.getMessage( e.getLinkedException() );
}
throw new CommandExecutionException( message, e );
}
finally
{
try
{
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, jaxbFormattedOutput );
}
catch ( final PropertyException e )
{
this.log( Level.INFO, Messages.getMessage( e ), e );
}
}
}
/**
* Gets the document files specified by a given command line.
*
* @param commandLine The command line specifying the document files to get.
*
* @return The document files specified by {@code commandLine}.
*
* @throws CommandExecutionException if getting the document files fails.
*/
protected Set<File> getDocumentFiles( final CommandLine commandLine ) throws CommandExecutionException
{
try
{
final Set<File> files = new HashSet<File>( 128 );
if ( commandLine.hasOption( Options.DOCUMENTS_OPTION.getOpt() ) )
{
final String[] elements = commandLine.getOptionValues( Options.DOCUMENTS_OPTION.getOpt() );
if ( elements != null )
{
for ( final String e : elements )
{
if ( e.startsWith( "@" ) )
{
final File file = new File( e.substring( 1 ) );
BufferedReader reader = null;
try
{
reader = new BufferedReader( new FileReader( file ) );
for ( String line = reader.readLine(); line != null; line = reader.readLine() )
{
line = line.trim();
if ( !line.startsWith( "#" ) )
{
final File f = new File( line );
if ( f.exists() )
{
if ( this.isLoggable( Level.FINER ) )
{
this.log( Level.FINER,
Messages.getMessage( "documentFileInfo",
f.getAbsolutePath() ),
null );
}
files.add( f );
}
else if ( this.isLoggable( Level.WARNING ) )
{
this.log( Level.WARNING,
Messages.getMessage( "documentFileNotFoundWarning",
f.getAbsolutePath() ),
null );
}
}
}
reader.close();
reader = null;
}
finally
{
try
{
if ( reader != null )
{
reader.close();
}
}
catch ( final IOException ex )
{
this.log( Level.SEVERE, Messages.getMessage( ex ), ex );
}
}
}
else
{
final File file = new File( e );
if ( file.exists() )
{
if ( this.isLoggable( Level.FINER ) )
{
this.log( Level.FINER,
Messages.getMessage( "documentFileInfo", file.getAbsolutePath() ),
null );
}
files.add( file );
}
else if ( this.isLoggable( Level.WARNING ) )
{
this.log( Level.WARNING,
Messages.getMessage( "documentFileNotFoundWarning", file.getAbsolutePath() ),
null );
}
}
}
}
}
return files;
}
catch ( final IOException e )
{
throw new CommandExecutionException( Messages.getMessage( e ), e );
}
}
/**
* Class loader backed by a command line.
*
* @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
* @version $JOMC: AbstractModletCommand.java 5303 2016-08-30 02:31:20Z schulte $
*/
public class CommandLineClassLoader extends URLClassLoader
{
/**
* {@code Modlets} excluded by the instance.
*/
private final Modlets excludedModlets = new Modlets();
/**
* Set of provider resource locations to filter.
*/
private final Set<String> providerResourceLocations = new HashSet<String>( 128 );
/**
* Set of modlet resource locations to filter.
*/
private final Set<String> modletResourceLocations = new HashSet<String>( 128 );
/**
* Set of temporary resources.
*/
private final Set<File> temporaryResources = new HashSet<File>( 128 );
/**
* Creates a new {@code CommandLineClassLoader} taking a command line backing the class loader.
*
* @param commandLine The command line backing the class loader.
*
* @throws NullPointerException if {@code commandLine} is {@code null}.
* @throws CommandExecutionException if processing {@code commandLine} fails.
*/
public CommandLineClassLoader( final CommandLine commandLine ) throws CommandExecutionException
{
super( new URL[ 0 ] );
try
{
if ( commandLine.hasOption( Options.CLASSPATH_OPTION.getOpt() ) )
{
final Set<URI> uris = new HashSet<URI>( 128 );
final String[] elements = commandLine.getOptionValues( Options.CLASSPATH_OPTION.getOpt() );
if ( elements != null )
{
for ( final String e : elements )
{
if ( e.startsWith( "@" ) )
{
final File file = new File( e.substring( 1 ) );
BufferedReader reader = null;
try
{
reader = new BufferedReader( new FileReader( file ) );
for ( String line = reader.readLine(); line != null; line = reader.readLine() )
{
line = line.trim();
if ( !line.startsWith( "#" ) )
{
final File f = new File( line );
if ( f.exists() )
{
uris.add( f.toURI() );
}
else if ( isLoggable( Level.WARNING ) )
{
log( Level.WARNING,
Messages.getMessage( "classpathElementNotFoundWarning",
f.getAbsolutePath() ),
null );
}
}
}
reader.close();
reader = null;
}
finally
{
try
{
if ( reader != null )
{
reader.close();
}
}
catch ( final IOException ex )
{
log( Level.SEVERE, Messages.getMessage( ex ), ex );
}
}
}
else
{
final File file = new File( e );
if ( file.exists() )
{
uris.add( file.toURI() );
}
else if ( isLoggable( Level.WARNING ) )
{
log( Level.WARNING,
Messages.getMessage( "classpathElementNotFoundWarning",
file.getAbsolutePath() ),
null );
}
}
}
}
for ( final URI uri : uris )
{
if ( isLoggable( Level.FINEST ) )
{
log( Level.FINEST,
Messages.getMessage( "classpathElementInfo", uri.toASCIIString() ),
null );
}
this.addURL( uri.toURL() );
}
// Assumes the default modlet location matches the location of resources of the applications'
// dependencies.
this.modletResourceLocations.add( DefaultModletProvider.getDefaultModletLocation() );
// Assumes the default provider location matches the location of resources of the applications'
// dependencies.
final String providerLocationPrefix = DefaultModelContext.getDefaultProviderLocation() + "/";
this.providerResourceLocations.add( providerLocationPrefix + ModletProcessor.class.getName() );
this.providerResourceLocations.add( providerLocationPrefix + ModletProvider.class.getName() );
this.providerResourceLocations.add( providerLocationPrefix + ModletValidator.class.getName() );
this.providerResourceLocations.add( providerLocationPrefix + ServiceFactory.class.getName() );
}
}
catch ( final IOException e )
{
throw new CommandExecutionException( Messages.getMessage( e ), e );
}
}
/**
* Gets the {@code Modlets} excluded by the instance.
*
* @return The {@code Modlets} excluded by the instance.
*/
public Modlets getExcludedModlets()
{
return this.excludedModlets;
}
/**
* Finds a resource with a given name.
*
* @param name The name of the resource to search.
*
* @return An {@code URL} object for reading the resource or {@code null}, if no resource matching {@code name} is
* found.
*/
@Override
public URL findResource( final String name ) //JDK: As of JDK 23 throws IOException
{
try
{
URL resource = super.findResource( name );
if ( resource != null )
{
if ( this.providerResourceLocations.contains( name ) )
{
resource = this.filterProviders( resource );
}
else if ( this.modletResourceLocations.contains( name ) )
{
resource = this.filterModlets( resource );
}
}
return resource;
}
catch ( final IOException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
return null;
}
catch ( final JAXBException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
return null;
}
catch ( final ModelException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
return null;
}
}
/**
* Finds all resources matching a given name.
*
* @param name The name of the resources to search.
*
* @return An enumeration of {@code URL} objects of resources matching name.
*
* @throws IOException if getting resources fails.
*/
@Override
public Enumeration<URL> findResources( final String name ) throws IOException
{
try
{
Enumeration<URL> resources = super.findResources( name );
if ( this.providerResourceLocations.contains( name )
|| this.modletResourceLocations.contains( name ) )
{
final List<URI> filtered = new LinkedList<URI>();
while ( resources.hasMoreElements() )
{
final URL resource = resources.nextElement();
if ( this.providerResourceLocations.contains( name ) )
{
filtered.add( this.filterProviders( resource ).toURI() );
}
else if ( this.modletResourceLocations.contains( name ) )
{
filtered.add( this.filterModlets( resource ).toURI() );
}
}
final Iterator<URI> it = filtered.iterator();
resources = new Enumeration<URL>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public URL nextElement()
{
try
{
return it.next().toURL();
}
catch ( final MalformedURLException e )
{
throw new AssertionError( e );
}
}
};
}
return resources;
}
catch ( final URISyntaxException e )
{
// JDK: As of JDK 6, new IOException( message, e );
throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e );
}
catch ( final JAXBException e )
{
String message = Messages.getMessage( e );
if ( message == null && e.getLinkedException() != null )
{
message = Messages.getMessage( e.getLinkedException() );
}
// JDK: As of JDK 6, new IOException( message, e );
throw (IOException) new IOException( message ).initCause( e );
}
catch ( final ModelException e )
{
// JDK: As of JDK 6, new IOException( message, e );
throw (IOException) new IOException( Messages.getMessage( e ) ).initCause( e );
}
}
/**
* Closes the class loader.
*
* @throws IOException if closing the class loader fails.
*/
@Override
@IgnoreJRERequirement
public void close() throws IOException
{
for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); )
{
final File temporaryResource = it.next();
if ( temporaryResource.exists() && temporaryResource.delete() )
{
it.remove();
}
}
if ( Closeable.class.isAssignableFrom( CommandLineClassLoader.class ) )
{
super.close();
}
}
/**
* Removes temporary resources.
*
* @throws Throwable if finalization fails.
*/
@Override
protected void finalize() throws Throwable
{
for ( final Iterator<File> it = this.temporaryResources.iterator(); it.hasNext(); )
{
final File temporaryResource = it.next();
if ( temporaryResource.exists() && !temporaryResource.delete() )
{
temporaryResource.deleteOnExit();
}
it.remove();
}
super.finalize();
}
private URL filterProviders( final URL resource ) throws IOException
{
InputStream in = null;
BufferedReader reader = null;
OutputStream out = null;
BufferedWriter writer = null;
final Set<String> providerExcludes = this.getProviderExcludes();
final List<String> lines = new LinkedList<String>();
try
{
URL filteredResource = resource;
boolean filtered = false;
in = resource.openStream();
reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
for ( String line = reader.readLine(); line != null; line = reader.readLine() )
{
if ( !providerExcludes.contains( line.trim() ) )
{
lines.add( line );
}
else
{
filtered = true;
log( Level.FINE,
Messages.getMessage( "providerExclusionInfo", resource.toExternalForm(), line ),
null );
}
}
reader.close();
reader = null;
in = null;
if ( filtered )
{
final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" );
this.temporaryResources.add( tmpResource );
out = new FileOutputStream( tmpResource );
writer = new BufferedWriter( new OutputStreamWriter( out, "UTF-8" ) );
for ( final String line : lines )
{
writer.write( line );
writer.newLine();
}
writer.close();
writer = null;
out = null;
filteredResource = tmpResource.toURI().toURL();
}
return filteredResource;
}
finally
{
try
{
if ( reader != null )
{
reader.close();
}
}
catch ( final IOException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
}
finally
{
try
{
if ( in != null )
{
in.close();
}
}
catch ( final IOException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
}
finally
{
try
{
if ( writer != null )
{
writer.close();
}
}
catch ( final IOException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
}
finally
{
try
{
if ( out != null )
{
out.close();
}
}
catch ( final IOException e )
{
log( Level.SEVERE, Messages.getMessage( e ), e );
}
}
}
}
}
}
private URL filterModlets( final URL resource ) throws ModelException, IOException, JAXBException
{
URL filteredResource = resource;
final Set<String> excludedModletNames = this.getModletExcludes();
final ModelContext modelContext = ModelContextFactory.newInstance().newModelContext();
Object o = modelContext.createUnmarshaller( ModletObject.MODEL_PUBLIC_ID ).unmarshal( resource );
if ( o instanceof JAXBElement<?> )
{
o = ( (JAXBElement<?>) o ).getValue();
}
Modlets modlets = null;
boolean filtered = false;
if ( o instanceof Modlets )
{
modlets = (Modlets) o;
}
else if ( o instanceof Modlet )
{
modlets = new Modlets();
modlets.getModlet().add( (Modlet) o );
}
if ( modlets != null )
{
for ( final Iterator<Modlet> it = modlets.getModlet().iterator(); it.hasNext(); )
{
final Modlet m = it.next();
if ( excludedModletNames.contains( m.getName() ) )
{
it.remove();
filtered = true;
synchronized ( this )
{
this.getExcludedModlets().getModlet().add( m );
}
log( Level.FINE,
Messages.getMessage( "modletExclusionInfo", resource.toExternalForm(), m.getName() ),
null );
continue;
}
if ( this.filterModlet( m, resource.toExternalForm() ) )
{
filtered = true;
}
}
if ( filtered )
{
final File tmpResource = File.createTempFile( this.getClass().getName(), ".rsrc" );
this.temporaryResources.add( tmpResource );
modelContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID ).
marshal( new ObjectFactory().createModlets( modlets ), tmpResource );
filteredResource = tmpResource.toURI().toURL();
}
}
return filteredResource;
}
private boolean filterModlet( final Modlet modlet, final String resourceInfo ) throws IOException
{
boolean filteredSchemas = false;
boolean filteredServices = false;
final Set<String> excludedSchemas = this.getSchemaExcludes();
final Set<String> excludedServices = this.getServiceExcludes();
if ( modlet.getSchemas() != null )
{
final Schemas schemas = new Schemas();
for ( final Schema s : modlet.getSchemas().getSchema() )
{
if ( !excludedSchemas.contains( s.getPublicId() ) )
{
schemas.getSchema().add( s );
}
else
{
log( Level.FINE,
Messages.getMessage( "schemaExclusionInfo", resourceInfo, s.getContextId() ),
null );
filteredSchemas = true;
}
}
if ( filteredSchemas )
{
modlet.setSchemas( schemas );
}
}
if ( modlet.getServices() != null )
{
final Services services = new Services();
for ( final Service s : modlet.getServices().getService() )
{
if ( !excludedServices.contains( s.getClazz() ) )
{
services.getService().add( s );
}
else
{
log( Level.FINE,
Messages.getMessage( "serviceExclusionInfo", resourceInfo, s.getClazz() ),
null );
filteredServices = true;
}
}
if ( filteredServices )
{
modlet.setServices( services );
}
}
return filteredSchemas || filteredServices;
}
/**
* Gets a set of modlet names to filter.
*
* @return An unmodifiable set of modlet names to filter.
*
* @throws IOException if reading configuration resources fails.
*/
private Set<String> getModletExcludes() throws IOException
{
return this.readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultModletExcludes" );
}
/**
* Gets a set of provider names to filter.
*
* @return An unmodifiable set of provider names to filter.
*
* @throws IOException if reading configuration resources fails.
*/
private Set<String> getProviderExcludes() throws IOException
{
return this.readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultProviderExcludes" );
}
/**
* Gets a set of service class names to filter.
*
* @return An unmodifiable set of service class names to filter.
*
* @throws IOException if reading configuration resources fails.
*/
private Set<String> getServiceExcludes() throws IOException
{
return this.readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultServiceExcludes" );
}
/**
* Gets a set of schema public identifiers excluded by default.
*
* @return An unmodifiable set of schema public identifiers excluded by default.
*
* @throws IOException if reading configuration resources fails.
*/
private Set<String> getSchemaExcludes() throws IOException
{
return this.readDefaultExcludes( ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultSchemaExcludes" );
}
private Set<String> readDefaultExcludes( final String location ) throws IOException
{
InputStream in = null;
BufferedReader reader = null;
final Set<String> defaultExcludes = new HashSet<String>();
try
{
in = CommandLineClassLoader.class.getResourceAsStream( location );
assert in != null : "Expected resource '" + location + "' not found.";
reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
for ( String line = reader.readLine(); line != null; line = reader.readLine() )
{
final String normalized = line.trim();
if ( normalized.length() > 0 && !normalized.contains( "#" ) )
{
defaultExcludes.add( normalized );
}
}
reader.close();
reader = null;
in = null;
return Collections.unmodifiableSet( defaultExcludes );
}
finally
{
try
{
if ( reader != null )
{
reader.close();
}
}
catch ( final IOException e )
{
// Suppressed.
}
finally
{
try
{
if ( in != null )
{
in.close();
}
}
catch ( final IOException e )
{
// Suppressed.
}
}
}
}
}
}