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

org.jomc.tools.ClassFileProcessor Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
/*
 *   Copyright (C) Christian Schulte , 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: ClassFileProcessor.java 5043 2015-05-27 07:03:39Z schulte $
 *
 */
package org.jomc.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.text.MessageFormat;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.util.JAXBResult;
import javax.xml.bind.util.JAXBSource;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.validation.Schema;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Unknown;
import org.jomc.model.Dependencies;
import org.jomc.model.Dependency;
import org.jomc.model.Implementation;
import org.jomc.model.Implementations;
import org.jomc.model.Message;
import org.jomc.model.Messages;
import org.jomc.model.ModelObject;
import org.jomc.model.ModelObjectException;
import org.jomc.model.Module;
import org.jomc.model.ObjectFactory;
import org.jomc.model.Properties;
import org.jomc.model.Property;
import org.jomc.model.Specification;
import org.jomc.model.SpecificationReference;
import org.jomc.model.Specifications;
import org.jomc.modlet.ModelContext;
import org.jomc.modlet.ModelException;
import org.jomc.modlet.ModelValidationReport;
import org.jomc.util.ParseException;
import org.jomc.util.TokenMgrError;
import org.jomc.util.VersionParser;

/**
 * Processes class files.
 *
 * 

* Use Cases:

    *
  • {@link #commitModelObjects(org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #commitModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #commitModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #commitModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #validateModelObjects(org.jomc.modlet.ModelContext) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext) }
  • *
  • {@link #validateModelObjects(org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) }
  • *
  • {@link #transformModelObjects(org.jomc.modlet.ModelContext, java.io.File, java.util.List) }
  • *
  • {@link #transformModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }
  • *
  • {@link #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }
  • *
  • {@link #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) }
  • *

* * @author Christian Schulte * @version $JOMC: ClassFileProcessor.java 5043 2015-05-27 07:03:39Z schulte $ * * @see #getModules() */ public class ClassFileProcessor extends JomcTool { /** * Empty byte array. */ private static final byte[] NO_BYTES = { }; /** * Creates a new {@code ClassFileProcessor} instance. */ public ClassFileProcessor() { super(); } /** * Creates a new {@code ClassFileProcessor} instance taking a {@code ClassFileProcessor} instance to initialize the * instance with. * * @param tool The instance to initialize the new instance with. * * @throws NullPointerException if {@code tool} is {@code null}. * @throws IOException if copying {@code tool} fails. */ public ClassFileProcessor( final ClassFileProcessor tool ) throws IOException { super( tool ); } /** * Commits model objects of the modules of the instance to class files. * * @param context The model context to use for committing the model objects. * @param classesDirectory The directory holding the class files. * * @throws NullPointerException if {@code context} or {@code classesDirectory} is {@code null}. * @throws IOException if committing model objects fails. * * @see #commitModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) */ public final void commitModelObjects( final ModelContext context, final File classesDirectory ) throws IOException { if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { if ( this.getModules() != null ) { final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); this.commitModelObjects( this.getModules().getSpecifications(), this.getModules().getImplementations(), m, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Commits model objects of a given module of the modules of the instance to class files. * * @param module The module to process. * @param context The model context to use for committing the model objects. * @param classesDirectory The directory holding the class files. * * @throws NullPointerException if {@code module}, {@code context} or {@code classesDirectory} is {@code null}. * @throws IOException if committing model objects fails. * * @see #commitModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) * @see #commitModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) */ public final void commitModelObjects( final Module module, final ModelContext context, final File classesDirectory ) throws IOException { if ( module == null ) { throw new NullPointerException( "module" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) { final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); this.commitModelObjects( module.getSpecifications(), module.getImplementations(), m, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Commits model objects of a given specification of the modules of the instance to class files. * * @param specification The specification to process. * @param context The model context to use for committing the model objects. * @param classesDirectory The directory holding the class files. * * @throws NullPointerException if {@code specification}, {@code context} or {@code classesDirectory} is * {@code null}. * @throws IOException if committing model objects fails. * * @see #commitModelObjects(org.jomc.model.Specification, javax.xml.bind.Marshaller, org.apache.bcel.classfile.JavaClass) */ public final void commitModelObjects( final Specification specification, final ModelContext context, final File classesDirectory ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); this.commitModelObjects( specification, m, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Commits model objects of a given implementation of the modules of the instance to class files. * * @param implementation The implementation to process. * @param context The model context to use for committing the model objects. * @param classesDirectory The directory holding the class files. * * @throws NullPointerException if {@code implementation}, {@code context} or {@code classesDirectory} is * {@code null}. * @throws IOException if committing model objects fails. * * @see #commitModelObjects(org.jomc.model.Implementation, javax.xml.bind.Marshaller, org.apache.bcel.classfile.JavaClass) */ public final void commitModelObjects( final Implementation implementation, final ModelContext context, final File classesDirectory ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); m.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); this.commitModelObjects( implementation, m, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Commits model objects of a given specification of the modules of the instance to a given class file. * * @param specification The specification to process. * @param marshaller The marshaller to use for committing the model objects. * @param javaClass The java class to commit to. * * @throws NullPointerException if {@code specification}, {@code marshaller} or {@code javaClass} is {@code null}. * @throws IOException if committing model objects fails. */ public void commitModelObjects( final Specification specification, final Marshaller marshaller, final JavaClass javaClass ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( marshaller == null ) { throw new NullPointerException( "marshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { this.setClassfileAttribute( javaClass, Specification.class.getName(), this.encodeModelObject( marshaller, new ObjectFactory().createSpecification( specification ) ) ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } } /** * Commits model objects of a given implementation of the modules of the instance to a given class file. * * @param implementation The implementation to process. * @param marshaller The marshaller to use for committing the model objects. * @param javaClass The java class to commit to. * * @throws NullPointerException if {@code implementation}, {@code marshaller} or {@code javaClass} is {@code null}. * @throws IOException if committing model objects fails. */ public void commitModelObjects( final Implementation implementation, final Marshaller marshaller, final JavaClass javaClass ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( marshaller == null ) { throw new NullPointerException( "marshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { final ObjectFactory of = new ObjectFactory(); Dependencies dependencies = this.getModules().getDependencies( implementation.getIdentifier() ); if ( dependencies == null ) { dependencies = new Dependencies(); } Properties properties = this.getModules().getProperties( implementation.getIdentifier() ); if ( properties == null ) { properties = new Properties(); } Messages messages = this.getModules().getMessages( implementation.getIdentifier() ); if ( messages == null ) { messages = new Messages(); } Specifications specifications = this.getModules().getSpecifications( implementation.getIdentifier() ); if ( specifications == null ) { specifications = new Specifications(); } for ( int i = 0, s0 = specifications.getReference().size(); i < s0; i++ ) { final SpecificationReference r = specifications.getReference().get( i ); if ( specifications.getSpecification( r.getIdentifier() ) == null && this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "unresolvedSpecification", r.getIdentifier(), implementation.getIdentifier() ), null ); } } for ( int i = 0, s0 = dependencies.getDependency().size(); i < s0; i++ ) { final Dependency d = dependencies.getDependency().get( i ); final Specification s = this.getModules().getSpecification( d.getIdentifier() ); if ( s != null ) { if ( specifications.getSpecification( s.getIdentifier() ) == null ) { specifications.getSpecification().add( s ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "unresolvedDependencySpecification", d.getIdentifier(), d.getName(), implementation.getIdentifier() ), null ); } } this.setClassfileAttribute( javaClass, Dependencies.class.getName(), this.encodeModelObject( marshaller, of.createDependencies( dependencies ) ) ); this.setClassfileAttribute( javaClass, Properties.class.getName(), this.encodeModelObject( marshaller, of.createProperties( properties ) ) ); this.setClassfileAttribute( javaClass, Messages.class.getName(), this.encodeModelObject( marshaller, of.createMessages( messages ) ) ); this.setClassfileAttribute( javaClass, Specifications.class.getName(), this.encodeModelObject( marshaller, of.createSpecifications( specifications ) ) ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } } /** * Validates model objects of class files of the modules of the instance. * * @param context The model context to use for validating model objects. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code context} is {@code null}. * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext) */ public final ModelValidationReport validateModelObjects( final ModelContext context ) throws IOException { if ( context == null ) { throw new NullPointerException( "context" ); } try { ModelValidationReport report = null; if ( this.getModules() != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( this.getModules().getSpecifications(), this.getModules().getImplementations(), u, context ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given module of the modules of the instance. * * @param module The module to process. * @param context The model context to use for validating model objects. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code module} or {@code context} is {@code null}. * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext) * @see #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext) */ public final ModelValidationReport validateModelObjects( final Module module, final ModelContext context ) throws IOException { if ( module == null ) { throw new NullPointerException( "module" ); } if ( context == null ) { throw new NullPointerException( "context" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( module.getSpecifications(), module.getImplementations(), u, context ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given specification of the modules of the instance. * * @param specification The specification to process. * @param context The model context to use for validating model objects. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code specification} or {@code context} is {@code null}. * * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Specification, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) */ public final ModelValidationReport validateModelObjects( final Specification specification, final ModelContext context ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( context == null ) { throw new NullPointerException( "context" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( specification, u, context ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given implementation of the modules of the instance. * * @param implementation The implementation to process. * @param context The model context to use for validating model objects. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code implementation} or {@code context} is {@code null}. * * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Implementation, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) */ public final ModelValidationReport validateModelObjects( final Implementation implementation, final ModelContext context ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( context == null ) { throw new NullPointerException( "context" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( implementation, u, context ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of the modules of the instance. * * @param context The model context to use for validating model objects. * @param classesDirectory The directory holding the class files. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code context} or {@code classesDirectory} is {@code null}. * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File) */ public final ModelValidationReport validateModelObjects( final ModelContext context, final File classesDirectory ) throws IOException { if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { ModelValidationReport report = null; if ( this.getModules() != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( this.getModules().getSpecifications(), this.getModules().getImplementations(), u, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given module of the modules of the instance. * * @param module The module to process. * @param context The model context to use for validating model objects. * @param classesDirectory The directory holding the class files. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code module}, {@code context} or {@code classesDirectory} is {@code null}. * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File) * @see #validateModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File) */ public final ModelValidationReport validateModelObjects( final Module module, final ModelContext context, final File classesDirectory ) throws IOException { if ( module == null ) { throw new NullPointerException( "module" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( module.getSpecifications(), module.getImplementations(), u, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given specification of the modules of the instance. * * @param specification The specification to process. * @param context The model context to use for validating model objects. * @param classesDirectory The directory holding the class files. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code specification}, {@code context} or {@code classesDirectory} is * {@code null}. * * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Specification, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) */ public final ModelValidationReport validateModelObjects( final Specification specification, final ModelContext context, final File classesDirectory ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( specification, u, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of class files of a given implementation of the modules of the instance. * * @param implementation The implementation to process. * @param context The model context to use for validating model objects. * @param classesDirectory The directory holding the class files. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code implementation}, {@code context} or {@code classesDirectory} is * {@code null}. * * @throws IOException if validating model objects fails. * * @see #validateModelObjects(org.jomc.model.Implementation, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass) */ public final ModelValidationReport validateModelObjects( final Implementation implementation, final ModelContext context, final File classesDirectory ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); u.setSchema( context.createSchema( this.getModel().getIdentifier() ) ); report = this.validateModelObjects( implementation, u, classesDirectory ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } return report; } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Validates model objects of a given specification of the modules of the instance. * * @param specification The specification to process. * @param unmarshaller The unmarshaller to use for validating model objects. * @param javaClass The java class to validate. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code specification}, {@code unmarshaller} or {@code javaClass} is {@code null}. * @throws IOException if validating model objects fails. */ public ModelValidationReport validateModelObjects( final Specification specification, final Unmarshaller unmarshaller, final JavaClass javaClass ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( unmarshaller == null ) { throw new NullPointerException( "unmarshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { report = new ModelValidationReport(); Specification decoded = null; final byte[] bytes = this.getClassfileAttribute( javaClass, Specification.class.getName() ); if ( bytes != null ) { decoded = this.decodeModelObject( unmarshaller, bytes, Specification.class ); } if ( decoded != null ) { if ( decoded.getMultiplicity() != specification.getMultiplicity() ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_MULTIPLICITY", Level.SEVERE, getMessage( "illegalMultiplicity", specification.getIdentifier(), specification.getMultiplicity().value(), decoded.getMultiplicity().value() ), new ObjectFactory().createSpecification( specification ) ) ); } if ( decoded.getScope() == null ? specification.getScope() != null : !decoded.getScope().equals( specification.getScope() ) ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_SCOPE", Level.SEVERE, getMessage( "illegalScope", specification.getIdentifier(), specification.getScope() == null ? "Multiton" : specification.getScope(), decoded.getScope() == null ? "Multiton" : decoded.getScope() ), new ObjectFactory().createSpecification( specification ) ) ); } if ( decoded.getClazz() == null ? specification.getClazz() != null : !decoded.getClazz().equals( specification.getClazz() ) ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_CLASS", Level.SEVERE, getMessage( "illegalSpecificationClass", decoded.getIdentifier(), specification.getClazz(), decoded.getClazz() ), new ObjectFactory().createSpecification( specification ) ) ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "cannotValidateSpecification", specification.getIdentifier(), Specification.class.getName() ), null ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } return report; } /** * Validates model objects of a given implementation of the modules of the instance. * * @param implementation The implementation to process. * @param unmarshaller The unmarshaller to use for validating model objects. * @param javaClass The java class to validate. * * @return The report of the validation or {@code null}, if no model objects are found. * * @throws NullPointerException if {@code implementation}, {@code unmarshaller} or {@code javaClass} is {@code null}. * @throws IOException if validating model objects fails. */ public ModelValidationReport validateModelObjects( final Implementation implementation, final Unmarshaller unmarshaller, final JavaClass javaClass ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( unmarshaller == null ) { throw new NullPointerException( "unmarshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } try { ModelValidationReport report = null; if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { report = new ModelValidationReport(); Dependencies dependencies = this.getModules().getDependencies( implementation.getIdentifier() ); if ( dependencies == null ) { dependencies = new Dependencies(); } Properties properties = this.getModules().getProperties( implementation.getIdentifier() ); if ( properties == null ) { properties = new Properties(); } Messages messages = this.getModules().getMessages( implementation.getIdentifier() ); if ( messages == null ) { messages = new Messages(); } Specifications specifications = this.getModules().getSpecifications( implementation.getIdentifier() ); if ( specifications == null ) { specifications = new Specifications(); } Dependencies decodedDependencies = null; byte[] bytes = this.getClassfileAttribute( javaClass, Dependencies.class.getName() ); if ( bytes != null ) { decodedDependencies = this.decodeModelObject( unmarshaller, bytes, Dependencies.class ); } Properties decodedProperties = null; bytes = this.getClassfileAttribute( javaClass, Properties.class.getName() ); if ( bytes != null ) { decodedProperties = this.decodeModelObject( unmarshaller, bytes, Properties.class ); } Messages decodedMessages = null; bytes = this.getClassfileAttribute( javaClass, Messages.class.getName() ); if ( bytes != null ) { decodedMessages = this.decodeModelObject( unmarshaller, bytes, Messages.class ); } Specifications decodedSpecifications = null; bytes = this.getClassfileAttribute( javaClass, Specifications.class.getName() ); if ( bytes != null ) { decodedSpecifications = this.decodeModelObject( unmarshaller, bytes, Specifications.class ); } if ( decodedDependencies != null ) { for ( int i = 0, s0 = decodedDependencies.getDependency().size(); i < s0; i++ ) { final Dependency decodedDependency = decodedDependencies.getDependency().get( i ); final Dependency dependency = dependencies.getDependency( decodedDependency.getName() ); final Specification s = this.getModules().getSpecification( decodedDependency.getIdentifier() ); if ( dependency == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_IMPLEMENTATION_DEPENDENCY", Level.SEVERE, getMessage( "missingDependency", implementation.getIdentifier(), decodedDependency.getName() ), new ObjectFactory().createImplementation( implementation ) ) ); } else if ( decodedDependency.getImplementationName() != null && dependency.getImplementationName() == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_DEPENDENCY_IMPLEMENTATION_NAME", Level.SEVERE, getMessage( "missingDependencyImplementationName", implementation.getIdentifier(), decodedDependency.getName() ), new ObjectFactory().createImplementation( implementation ) ) ); } if ( s != null && s.getVersion() != null && decodedDependency.getVersion() != null && VersionParser.compare( decodedDependency.getVersion(), s.getVersion() ) > 0 ) { final Module moduleOfSpecification = this.getModules().getModuleOfSpecification( s.getIdentifier() ); final Module moduleOfImplementation = this.getModules().getModuleOfImplementation( implementation.getIdentifier() ); report.getDetails().add( new ModelValidationReport.Detail( "CLASS_INCOMPATIBLE_IMPLEMENTATION_DEPENDENCY", Level.SEVERE, getMessage( "incompatibleDependency", javaClass.getClassName(), moduleOfImplementation == null ? "<>" : moduleOfImplementation.getName(), s.getIdentifier(), moduleOfSpecification == null ? "<>" : moduleOfSpecification.getName(), decodedDependency.getVersion(), s.getVersion() ), new ObjectFactory().createImplementation( implementation ) ) ); } } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), Dependencies.class.getName() ), null ); } if ( decodedProperties != null ) { for ( int i = 0, s0 = decodedProperties.getProperty().size(); i < s0; i++ ) { final Property decodedProperty = decodedProperties.getProperty().get( i ); final Property property = properties.getProperty( decodedProperty.getName() ); if ( property == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_IMPLEMENTATION_PROPERTY", Level.SEVERE, getMessage( "missingProperty", implementation.getIdentifier(), decodedProperty.getName() ), new ObjectFactory().createImplementation( implementation ) ) ); } else if ( decodedProperty.getType() == null ? property.getType() != null : !decodedProperty.getType().equals( property.getType() ) ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_IMPLEMENTATION_PROPERTY", Level.SEVERE, getMessage( "illegalPropertyType", implementation.getIdentifier(), decodedProperty.getName(), property.getType() == null ? "<>" : property.getType(), decodedProperty.getType() == null ? "<>" : decodedProperty.getType() ), new ObjectFactory().createImplementation( implementation ) ) ); } } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), Properties.class.getName() ), null ); } if ( decodedMessages != null ) { for ( int i = 0, s0 = decodedMessages.getMessage().size(); i < s0; i++ ) { final Message decodedMessage = decodedMessages.getMessage().get( i ); final Message message = messages.getMessage( decodedMessage.getName() ); if ( message == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_IMPLEMENTATION_MESSAGE", Level.SEVERE, getMessage( "missingMessage", implementation.getIdentifier(), decodedMessage.getName() ), new ObjectFactory().createImplementation( implementation ) ) ); } } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), Messages.class.getName() ), null ); } if ( decodedSpecifications != null ) { for ( int i = 0, s0 = decodedSpecifications.getSpecification().size(); i < s0; i++ ) { final Specification decodedSpecification = decodedSpecifications.getSpecification().get( i ); final Specification specification = this.getModules().getSpecification( decodedSpecification.getIdentifier() ); if ( specification == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_SPECIFICATION", Level.SEVERE, getMessage( "missingSpecification", implementation.getIdentifier(), decodedSpecification.getIdentifier() ), new ObjectFactory().createImplementation( implementation ) ) ); } else { if ( decodedSpecification.getMultiplicity() != specification.getMultiplicity() ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_MULTIPLICITY", Level.SEVERE, getMessage( "illegalMultiplicity", specification.getIdentifier(), specification.getMultiplicity().value(), decodedSpecification.getMultiplicity().value() ), new ObjectFactory().createImplementation( implementation ) ) ); } if ( decodedSpecification.getScope() == null ? specification.getScope() != null : !decodedSpecification.getScope().equals( specification.getScope() ) ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_SCOPE", Level.SEVERE, getMessage( "illegalScope", decodedSpecification.getIdentifier(), specification.getScope() == null ? "Multiton" : specification.getScope(), decodedSpecification.getScope() == null ? "Multiton" : decodedSpecification.getScope() ), new ObjectFactory().createImplementation( implementation ) ) ); } if ( decodedSpecification.getClazz() == null ? specification.getClazz() != null : !decodedSpecification.getClazz().equals( specification.getClazz() ) ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_ILLEGAL_SPECIFICATION_CLASS", Level.SEVERE, getMessage( "illegalSpecificationClass", decodedSpecification.getIdentifier(), specification.getClazz(), decodedSpecification.getClazz() ), new ObjectFactory().createImplementation( implementation ) ) ); } } } for ( int i = 0, s0 = decodedSpecifications.getReference().size(); i < s0; i++ ) { final SpecificationReference decodedReference = decodedSpecifications.getReference().get( i ); final Specification specification = specifications.getSpecification( decodedReference.getIdentifier() ); if ( specification == null ) { report.getDetails().add( new ModelValidationReport.Detail( "CLASS_MISSING_SPECIFICATION", Level.SEVERE, getMessage( "missingSpecification", implementation.getIdentifier(), decodedReference.getIdentifier() ), new ObjectFactory().createImplementation( implementation ) ) ); } else if ( decodedReference.getVersion() != null && specification.getVersion() != null && VersionParser.compare( decodedReference.getVersion(), specification.getVersion() ) != 0 ) { final Module moduleOfSpecification = this.getModules().getModuleOfSpecification( decodedReference.getIdentifier() ); final Module moduleOfImplementation = this.getModules().getModuleOfImplementation( implementation.getIdentifier() ); report.getDetails().add( new ModelValidationReport.Detail( "CLASS_INCOMPATIBLE_IMPLEMENTATION", Level.SEVERE, getMessage( "incompatibleImplementation", javaClass.getClassName(), moduleOfImplementation == null ? "<>" : moduleOfImplementation.getName(), specification.getIdentifier(), moduleOfSpecification == null ? "<>" : moduleOfSpecification.getName(), decodedReference.getVersion(), specification.getVersion() ), new ObjectFactory().createImplementation( implementation ) ) ); } } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "cannotValidateImplementation", implementation.getIdentifier(), Specifications.class.getName() ), null ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } return report; } catch ( final ParseException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } catch ( final TokenMgrError e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Transforms model objects of class files of the modules of the instance. * * @param context The model context to use for transforming model objects. * @param classesDirectory The directory holding the class files. * @param transformers The transformers to use for transforming model objects. * * @throws NullPointerException if {@code context}, {@code classesDirectory} or {@code transformers} is * {@code null}. * @throws IOException if transforming model objects fails. * * @see #transformModelObjects(org.jomc.model.Module, org.jomc.modlet.ModelContext, java.io.File, java.util.List) */ public final void transformModelObjects( final ModelContext context, final File classesDirectory, final List transformers ) throws IOException { if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } try { if ( this.getModules() != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); final Schema s = context.createSchema( this.getModel().getIdentifier() ); u.setSchema( s ); m.setSchema( s ); this.transformModelObjects( this.getModules().getSpecifications(), this.getModules().getImplementations(), u, m, classesDirectory, transformers ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Transforms model objects of class files of a given module of the modules of the instance. * * @param module The module to process. * @param context The model context to use for transforming model objects. * @param classesDirectory The directory holding the class files. * @param transformers The transformers to use for transforming the model objects. * * @throws NullPointerException if {@code module}, {@code context}, {@code classesDirectory} or {@code transformers} * is {@code null}. * @throws IOException if transforming model objects fails. * * @see #transformModelObjects(org.jomc.model.Specification, org.jomc.modlet.ModelContext, java.io.File, java.util.List) * @see #transformModelObjects(org.jomc.model.Implementation, org.jomc.modlet.ModelContext, java.io.File, java.util.List) */ public final void transformModelObjects( final Module module, final ModelContext context, final File classesDirectory, final List transformers ) throws IOException { if ( module == null ) { throw new NullPointerException( "module" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } try { if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); final Schema s = context.createSchema( this.getModel().getIdentifier() ); u.setSchema( s ); m.setSchema( s ); this.transformModelObjects( module.getSpecifications(), module.getImplementations(), u, m, classesDirectory, transformers ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Transforms model objects of class files of a given specification of the modules of the instance. * * @param specification The specification to process. * @param context The model context to use for transforming model objects. * @param classesDirectory The directory holding the class files. * @param transformers The transformers to use for transforming the model objects. * * @throws NullPointerException if {@code specification}, {@code context}, {@code classesDirectory} or * {@code transformers} is {@code null}. * @throws IOException if transforming model objects fails. * * @see #transformModelObjects(org.jomc.model.Specification, javax.xml.bind.Marshaller, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass, java.util.List) */ public final void transformModelObjects( final Specification specification, final ModelContext context, final File classesDirectory, final List transformers ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } try { if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); final Schema s = context.createSchema( this.getModel().getIdentifier() ); u.setSchema( s ); m.setSchema( s ); this.transformModelObjects( specification, m, u, classesDirectory, transformers ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Transforms model objects of class files of a given implementation of the modules of the instance. * * @param implementation The implementation to process. * @param context The model context to use for transforming model objects. * @param classesDirectory The directory holding the class files. * @param transformers The transformers to use for transforming the model objects. * * @throws NullPointerException if {@code implementation}, {@code context}, {@code classesDirectory} or * {@code transformers} is {@code null}. * @throws IOException if transforming model objects fails. * * @see #transformModelObjects(org.jomc.model.Implementation, javax.xml.bind.Marshaller, javax.xml.bind.Unmarshaller, org.apache.bcel.classfile.JavaClass, java.util.List) */ public final void transformModelObjects( final Implementation implementation, final ModelContext context, final File classesDirectory, final List transformers ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( context == null ) { throw new NullPointerException( "context" ); } if ( classesDirectory == null ) { throw new NullPointerException( "classesDirectory" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } try { if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { final Unmarshaller u = context.createUnmarshaller( this.getModel().getIdentifier() ); final Marshaller m = context.createMarshaller( this.getModel().getIdentifier() ); final Schema s = context.createSchema( this.getModel().getIdentifier() ); u.setSchema( s ); m.setSchema( s ); this.transformModelObjects( implementation, m, u, classesDirectory, transformers ); } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } } catch ( final ModelException e ) { // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( getMessage( e ) ).initCause( e ); } } /** * Transforms model objects of a given specification of the modules of the instance. * * @param specification The specification to process. * @param marshaller The marshaller to use for transforming model objects. * @param unmarshaller The unmarshaller to use for transforming model objects. * @param javaClass The java class to transform model objects of. * @param transformers The transformers to use for transforming the model objects. * * @throws NullPointerException if {@code specification}, {@code marshaller}, {@code unmarshaller}, * {@code javaClass} or {@code transformers} is {@code null}. * @throws IOException if transforming model objects fails. */ public void transformModelObjects( final Specification specification, final Marshaller marshaller, final Unmarshaller unmarshaller, final JavaClass javaClass, final List transformers ) throws IOException { if ( specification == null ) { throw new NullPointerException( "specification" ); } if ( marshaller == null ) { throw new NullPointerException( "marshaller" ); } if ( unmarshaller == null ) { throw new NullPointerException( "unmarshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } try { if ( this.getModules() != null && this.getModules().getSpecification( specification.getIdentifier() ) != null ) { Specification decodedSpecification = null; final ObjectFactory objectFactory = new ObjectFactory(); final byte[] bytes = this.getClassfileAttribute( javaClass, Specification.class.getName() ); if ( bytes != null ) { decodedSpecification = this.decodeModelObject( unmarshaller, bytes, Specification.class ); } if ( decodedSpecification != null ) { for ( int i = 0, l = transformers.size(); i < l; i++ ) { final JAXBSource source = new JAXBSource( marshaller, objectFactory.createSpecification( decodedSpecification ) ); final JAXBResult result = new JAXBResult( unmarshaller ); transformers.get( i ).transform( source, result ); if ( result.getResult() instanceof JAXBElement && ( (JAXBElement) result.getResult() ).getValue() instanceof Specification ) { decodedSpecification = (Specification) ( (JAXBElement) result.getResult() ).getValue(); } else { throw new IOException( getMessage( "illegalSpecificationTransformationResult", specification.getIdentifier() ) ); } } this.setClassfileAttribute( javaClass, Specification.class.getName(), this.encodeModelObject( marshaller, objectFactory.createSpecification( decodedSpecification ) ) ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null ); } } catch ( final JAXBException e ) { String message = getMessage( e ); if ( message == null && e.getLinkedException() != null ) { message = getMessage( e.getLinkedException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } catch ( final TransformerException e ) { String message = getMessage( e ); if ( message == null && e.getException() != null ) { message = getMessage( e.getException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } } /** * Transforms model objects of a given implementation of the modules of the instance. * * @param implementation The implementation to process. * @param marshaller The marshaller to use for transforming model objects. * @param unmarshaller The unmarshaller to use for transforming model objects. * @param javaClass The java class to transform model object of. * @param transformers The transformers to use for transforming the model objects. * * @throws NullPointerException if {@code implementation}, {@code marshaller}, {@code unmarshaller}, * {@code javaClass} or {@code transformers} is {@code null}. * @throws IOException if transforming model objects fails. */ public void transformModelObjects( final Implementation implementation, final Marshaller marshaller, final Unmarshaller unmarshaller, final JavaClass javaClass, final List transformers ) throws IOException { if ( implementation == null ) { throw new NullPointerException( "implementation" ); } if ( marshaller == null ) { throw new NullPointerException( "marshaller" ); } if ( unmarshaller == null ) { throw new NullPointerException( "unmarshaller" ); } if ( javaClass == null ) { throw new NullPointerException( "javaClass" ); } if ( transformers == null ) { throw new NullPointerException( "transformers" ); } try { if ( this.getModules() != null && this.getModules().getImplementation( implementation.getIdentifier() ) != null ) { Dependencies decodedDependencies = null; byte[] bytes = this.getClassfileAttribute( javaClass, Dependencies.class.getName() ); if ( bytes != null ) { decodedDependencies = this.decodeModelObject( unmarshaller, bytes, Dependencies.class ); } Messages decodedMessages = null; bytes = this.getClassfileAttribute( javaClass, Messages.class.getName() ); if ( bytes != null ) { decodedMessages = this.decodeModelObject( unmarshaller, bytes, Messages.class ); } Properties decodedProperties = null; bytes = this.getClassfileAttribute( javaClass, Properties.class.getName() ); if ( bytes != null ) { decodedProperties = this.decodeModelObject( unmarshaller, bytes, Properties.class ); } Specifications decodedSpecifications = null; bytes = this.getClassfileAttribute( javaClass, Specifications.class.getName() ); if ( bytes != null ) { decodedSpecifications = this.decodeModelObject( unmarshaller, bytes, Specifications.class ); } final ObjectFactory of = new ObjectFactory(); for ( int i = 0, l = transformers.size(); i < l; i++ ) { final Transformer transformer = transformers.get( i ); if ( decodedDependencies != null ) { final JAXBSource source = new JAXBSource( marshaller, of.createDependencies( decodedDependencies ) ); final JAXBResult result = new JAXBResult( unmarshaller ); transformer.transform( source, result ); if ( result.getResult() instanceof JAXBElement && ( (JAXBElement) result.getResult() ).getValue() instanceof Dependencies ) { decodedDependencies = (Dependencies) ( (JAXBElement) result.getResult() ).getValue(); } else { throw new IOException( getMessage( "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); } } if ( decodedMessages != null ) { final JAXBSource source = new JAXBSource( marshaller, of.createMessages( decodedMessages ) ); final JAXBResult result = new JAXBResult( unmarshaller ); transformer.transform( source, result ); if ( result.getResult() instanceof JAXBElement && ( (JAXBElement) result.getResult() ).getValue() instanceof Messages ) { decodedMessages = (Messages) ( (JAXBElement) result.getResult() ).getValue(); } else { throw new IOException( getMessage( "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); } } if ( decodedProperties != null ) { final JAXBSource source = new JAXBSource( marshaller, of.createProperties( decodedProperties ) ); final JAXBResult result = new JAXBResult( unmarshaller ); transformer.transform( source, result ); if ( result.getResult() instanceof JAXBElement && ( (JAXBElement) result.getResult() ).getValue() instanceof Properties ) { decodedProperties = (Properties) ( (JAXBElement) result.getResult() ).getValue(); } else { throw new IOException( getMessage( "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); } } if ( decodedSpecifications != null ) { final JAXBSource source = new JAXBSource( marshaller, of.createSpecifications( decodedSpecifications ) ); final JAXBResult result = new JAXBResult( unmarshaller ); transformer.transform( source, result ); if ( result.getResult() instanceof JAXBElement && ( (JAXBElement) result.getResult() ).getValue() instanceof Specifications ) { decodedSpecifications = (Specifications) ( (JAXBElement) result.getResult() ).getValue(); } else { throw new IOException( getMessage( "illegalImplementationTransformationResult", implementation.getIdentifier() ) ); } } } if ( decodedDependencies != null ) { this.setClassfileAttribute( javaClass, Dependencies.class.getName(), this.encodeModelObject( marshaller, of.createDependencies( decodedDependencies ) ) ); } if ( decodedMessages != null ) { this.setClassfileAttribute( javaClass, Messages.class.getName(), this.encodeModelObject( marshaller, of.createMessages( decodedMessages ) ) ); } if ( decodedProperties != null ) { this.setClassfileAttribute( javaClass, Properties.class.getName(), this.encodeModelObject( marshaller, of.createProperties( decodedProperties ) ) ); } if ( decodedSpecifications != null ) { this.setClassfileAttribute( javaClass, Specifications.class.getName(), this.encodeModelObject( marshaller, of.createSpecifications( decodedSpecifications ) ) ); } } else if ( this.isLoggable( Level.WARNING ) ) { this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null ); } } catch ( final JAXBException e ) { String message = getMessage( e ); if ( message == null && e.getLinkedException() != null ) { message = getMessage( e.getLinkedException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } catch ( final TransformerException e ) { String message = getMessage( e ); if ( message == null && e.getException() != null ) { message = getMessage( e.getException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } } /** * Gets an attribute from a java class. * * @param clazz The java class to get an attribute from. * @param attributeName The name of the attribute to get. * * @return The value of attribute {@code attributeName} of {@code clazz} or {@code null}, if no such attribute * exists. * * @throws NullPointerException if {@code clazz} or {@code attributeName} is {@code null}. * @throws IOException if getting the attribute fails. * * @see JavaClass#getAttributes() */ public byte[] getClassfileAttribute( final JavaClass clazz, final String attributeName ) throws IOException { if ( clazz == null ) { throw new NullPointerException( "clazz" ); } if ( attributeName == null ) { throw new NullPointerException( "attributeName" ); } final Attribute[] attributes = clazz.getAttributes(); for ( int i = attributes.length - 1; i >= 0; i-- ) { final Constant constant = clazz.getConstantPool().getConstant( attributes[i].getNameIndex() ); if ( constant instanceof ConstantUtf8 && attributeName.equals( ( (ConstantUtf8) constant ).getBytes() ) ) { final Unknown unknown = (Unknown) attributes[i]; return unknown.getBytes(); } } return null; } /** * Adds or updates an attribute in a java class. * * @param clazz The class to update an attribute of. * @param attributeName The name of the attribute to update. * @param data The new data of the attribute to update the {@code clazz} with. * * @throws NullPointerException if {@code clazz} or {@code attributeName} is {@code null}. * @throws IOException if updating the class file fails. * * @see JavaClass#getAttributes() */ public void setClassfileAttribute( final JavaClass clazz, final String attributeName, final byte[] data ) throws IOException { if ( clazz == null ) { throw new NullPointerException( "clazz" ); } if ( attributeName == null ) { throw new NullPointerException( "attributeName" ); } final byte[] attributeData = data != null ? data : NO_BYTES; /* * The JavaTM Virtual Machine Specification - Second Edition - Chapter 4.1 * * A Java virtual machine implementation is required to silently ignore any * or all attributes in the attributes table of a ClassFile structure that * it does not recognize. Attributes not defined in this specification are * not allowed to affect the semantics of the class file, but only to * provide additional descriptive information (§4.7.1). */ Attribute[] attributes = clazz.getAttributes(); int attributeIndex = -1; int nameIndex = -1; for ( int i = attributes.length - 1; i >= 0; i-- ) { final Constant constant = clazz.getConstantPool().getConstant( attributes[i].getNameIndex() ); if ( constant instanceof ConstantUtf8 && attributeName.equals( ( (ConstantUtf8) constant ).getBytes() ) ) { attributeIndex = i; nameIndex = attributes[i].getNameIndex(); } } if ( nameIndex == -1 ) { final Constant[] pool = clazz.getConstantPool().getConstantPool(); final Constant[] tmp = new Constant[ pool.length + 1 ]; System.arraycopy( pool, 0, tmp, 0, pool.length ); tmp[pool.length] = new ConstantUtf8( attributeName ); nameIndex = pool.length; clazz.setConstantPool( new ConstantPool( tmp ) ); } final Unknown unknown = new Unknown( nameIndex, attributeData.length, attributeData, clazz.getConstantPool() ); if ( attributeIndex == -1 ) { final Attribute[] tmp = new Attribute[ attributes.length + 1 ]; System.arraycopy( attributes, 0, tmp, 0, attributes.length ); tmp[attributes.length] = unknown; attributes = tmp; } else { attributes[attributeIndex] = unknown; } clazz.setAttributes( attributes ); } /** * Encodes a model object to a byte array. * * @param marshaller The marshaller to use for encoding the object. * @param modelObject The model object to encode. * * @return GZIP compressed XML document of {@code modelObject}. * * @throws NullPointerException if {@code marshaller} or {@code modelObject} is {@code null}. * @throws IOException if encoding {@code modelObject} fails. * * @see #decodeModelObject(javax.xml.bind.Unmarshaller, byte[], java.lang.Class) */ public byte[] encodeModelObject( final Marshaller marshaller, final JAXBElement modelObject ) throws IOException { if ( marshaller == null ) { throw new NullPointerException( "marshaller" ); } if ( modelObject == null ) { throw new NullPointerException( "modelObject" ); } try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final GZIPOutputStream out = new GZIPOutputStream( baos ); marshaller.marshal( modelObject, out ); out.close(); return baos.toByteArray(); } catch ( final JAXBException e ) { String message = getMessage( e ); if ( message == null && e.getLinkedException() != null ) { message = getMessage( e.getLinkedException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } } /** * Decodes a model object from a byte array. * * @param unmarshaller The unmarshaller to use for decoding the object. * @param bytes The encoded model object to decode. * @param type The class of the type of the encoded model object. * @param The type of the encoded model object. * * @return Model object decoded from {@code bytes}. * * @throws NullPointerException if {@code unmarshaller}, {@code bytes} or {@code type} is {@code null}. * @throws IOException if decoding {@code bytes} fails. * * @see #encodeModelObject(javax.xml.bind.Marshaller, javax.xml.bind.JAXBElement) */ public T decodeModelObject( final Unmarshaller unmarshaller, final byte[] bytes, final Class type ) throws IOException { if ( unmarshaller == null ) { throw new NullPointerException( "unmarshaller" ); } if ( bytes == null ) { throw new NullPointerException( "bytes" ); } if ( type == null ) { throw new NullPointerException( "type" ); } try { final ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); final GZIPInputStream in = new GZIPInputStream( bais ); final JAXBElement element = (JAXBElement) unmarshaller.unmarshal( in ); in.close(); return element.getValue(); } catch ( final JAXBException e ) { String message = getMessage( e ); if ( message == null && e.getLinkedException() != null ) { message = getMessage( e.getLinkedException() ); } // JDK: As of JDK 6, "new IOException( message, cause )". throw (IOException) new IOException( message ).initCause( e ); } } private void commitModelObjects( final Specifications specifications, final Implementations implementations, final Marshaller marshaller, final File classesDirectory ) throws IOException, ModelObjectException { if ( specifications != null ) { for ( int i = specifications.getSpecification().size() - 1; i >= 0; i-- ) { this.commitModelObjects( specifications.getSpecification().get( i ), marshaller, classesDirectory ); } } if ( implementations != null ) { for ( int i = implementations.getImplementation().size() - 1; i >= 0; i-- ) { this.commitModelObjects( implementations.getImplementation().get( i ), marshaller, classesDirectory ); } } } private void commitModelObjects( final Specification specification, final Marshaller marshaller, final File classesDirectory ) throws IOException, ModelObjectException { if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) { final String classLocation = specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !( classFile.canRead() && classFile.canWrite() ) ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "committing", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); this.commitModelObjects( specification, marshaller, javaClass ); this.writeJavaClass( javaClass, classFile ); } } private void commitModelObjects( final Implementation implementation, final Marshaller marshaller, final File classesDirectory ) throws IOException, ModelObjectException { if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) { final String classLocation = implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !( classFile.canRead() && classFile.canWrite() ) ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "committing", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); this.commitModelObjects( implementation, marshaller, javaClass ); this.writeJavaClass( javaClass, classFile ); } } private ModelValidationReport validateModelObjects( final Specifications specifications, final Implementations implementations, final Unmarshaller unmarshaller, final File classesDirectory ) throws IOException, ModelObjectException { final ModelValidationReport report = new ModelValidationReport(); if ( specifications != null ) { for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) { final ModelValidationReport current = this.validateModelObjects( specifications.getSpecification().get( i ), unmarshaller, classesDirectory ); report.getDetails().addAll( current.getDetails() ); } } if ( implementations != null ) { for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) { final ModelValidationReport current = this.validateModelObjects( implementations.getImplementation().get( i ), unmarshaller, classesDirectory ); report.getDetails().addAll( current.getDetails() ); } } return report; } private ModelValidationReport validateModelObjects( final Specification specification, final Unmarshaller unmarshaller, final File classesDirectory ) throws IOException, ModelObjectException { final ModelValidationReport report = new ModelValidationReport(); if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) { final String classLocation = specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !classFile.canRead() ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "validating", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); report.getDetails().addAll( this.validateModelObjects( specification, unmarshaller, javaClass ).getDetails() ); } return report; } private ModelValidationReport validateModelObjects( final Implementation implementation, final Unmarshaller unmarshaller, final File classesDirectory ) throws IOException, ModelObjectException { final ModelValidationReport report = new ModelValidationReport(); if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) { final String classLocation = implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !classFile.canRead() ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "validating", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); report.getDetails().addAll( this.validateModelObjects( implementation, unmarshaller, javaClass ).getDetails() ); } return report; } private ModelValidationReport validateModelObjects( final Specifications specifications, final Implementations implementations, final Unmarshaller unmarshaller, final ModelContext context ) throws IOException, ModelException { final ModelValidationReport report = new ModelValidationReport(); if ( specifications != null ) { for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) { final ModelValidationReport current = this.validateModelObjects( specifications.getSpecification().get( i ), unmarshaller, context ); report.getDetails().addAll( current.getDetails() ); } } if ( implementations != null ) { for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) { final ModelValidationReport current = this.validateModelObjects( implementations.getImplementation().get( i ), unmarshaller, context ); report.getDetails().addAll( current.getDetails() ); } } return report; } private ModelValidationReport validateModelObjects( final Specification specification, final Unmarshaller unmarshaller, final ModelContext context ) throws IOException, ModelException { final ModelValidationReport report = new ModelValidationReport(); if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) { final String classLocation = specification.getJavaTypeName().getClassName().replace( '.', '/' ) + ".class"; final URL classUrl = context.findResource( classLocation ); if ( classUrl == null ) { throw new IOException( getMessage( "resourceNotFound", classLocation ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "validatingSpecification", specification.getIdentifier() ), null ); } InputStream in = null; JavaClass javaClass = null; boolean suppressExceptionOnClose = true; try { in = classUrl.openStream(); javaClass = new ClassParser( in, classUrl.toExternalForm() ).parse(); suppressExceptionOnClose = false; } finally { try { if ( in != null ) { in.close(); } } catch ( final IOException e ) { if ( suppressExceptionOnClose ) { this.log( Level.SEVERE, getMessage( e ), e ); } else { throw e; } } } report.getDetails().addAll( this.validateModelObjects( specification, unmarshaller, javaClass ).getDetails() ); } return report; } private ModelValidationReport validateModelObjects( final Implementation implementation, final Unmarshaller unmarshaller, final ModelContext context ) throws IOException, ModelException { final ModelValidationReport report = new ModelValidationReport(); if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) { final String classLocation = implementation.getJavaTypeName().getClassName().replace( '.', '/' ) + ".class"; final URL classUrl = context.findResource( classLocation ); if ( classUrl == null ) { throw new IOException( getMessage( "resourceNotFound", classLocation ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "validatingImplementation", implementation.getIdentifier() ), null ); } InputStream in = null; JavaClass javaClass = null; boolean suppressExceptionOnClose = true; try { in = classUrl.openStream(); javaClass = new ClassParser( in, classUrl.toExternalForm() ).parse(); suppressExceptionOnClose = false; } finally { try { if ( in != null ) { in.close(); } } catch ( final IOException e ) { if ( suppressExceptionOnClose ) { this.log( Level.SEVERE, getMessage( e ), e ); } else { throw e; } } } report.getDetails().addAll( this.validateModelObjects( implementation, unmarshaller, javaClass ).getDetails() ); } return report; } private void transformModelObjects( final Specifications specifications, final Implementations implementations, final Unmarshaller unmarshaller, final Marshaller marshaller, final File classesDirectory, final List transformers ) throws IOException, ModelObjectException { if ( specifications != null ) { for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ ) { this.transformModelObjects( specifications.getSpecification().get( i ), marshaller, unmarshaller, classesDirectory, transformers ); } } if ( implementations != null ) { for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ ) { this.transformModelObjects( implementations.getImplementation().get( i ), marshaller, unmarshaller, classesDirectory, transformers ); } } } private void transformModelObjects( final Specification specification, final Marshaller marshaller, final Unmarshaller unmarshaller, final File classesDirectory, final List transformers ) throws IOException, ModelObjectException { if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null ) { final String classLocation = specification.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !( classFile.canRead() && classFile.canWrite() ) ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "transforming", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); this.transformModelObjects( specification, marshaller, unmarshaller, javaClass, transformers ); this.writeJavaClass( javaClass, classFile ); } } private void transformModelObjects( final Implementation implementation, final Marshaller marshaller, final Unmarshaller unmarshaller, final File classesDirectory, final List transformers ) throws IOException, ModelObjectException { if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null ) { final String classLocation = implementation.getJavaTypeName().getClassName().replace( '.', File.separatorChar ) + ".class"; final File classFile = new File( classesDirectory, classLocation ); if ( !classesDirectory.isDirectory() ) { throw new IOException( getMessage( "directoryNotFound", classesDirectory.getAbsolutePath() ) ); } if ( !classFile.isFile() ) { throw new IOException( getMessage( "fileNotFound", classFile.getAbsolutePath() ) ); } if ( !( classFile.canRead() && classFile.canWrite() ) ) { throw new IOException( getMessage( "fileAccessDenied", classFile.getAbsolutePath() ) ); } if ( this.isLoggable( Level.INFO ) ) { this.log( Level.INFO, getMessage( "transforming", classFile.getAbsolutePath() ), null ); } final JavaClass javaClass = this.readJavaClass( classFile ); this.transformModelObjects( implementation, marshaller, unmarshaller, javaClass, transformers ); this.writeJavaClass( javaClass, classFile ); } } private JavaClass readJavaClass( final File classFile ) throws IOException { FileInputStream in = null; FileChannel fileChannel = null; FileLock fileLock = null; boolean suppressExceptionOnClose = true; try { in = new FileInputStream( classFile ); fileChannel = in.getChannel(); fileLock = fileChannel.lock( 0, classFile.length(), true ); final JavaClass javaClass = new ClassParser( in, classFile.getAbsolutePath() ).parse(); suppressExceptionOnClose = false; return javaClass; } finally { this.releaseAndClose( fileLock, fileChannel, in, suppressExceptionOnClose ); } } private void writeJavaClass( final JavaClass javaClass, final File classFile ) throws IOException { RandomAccessFile randomAccessFile = null; FileChannel fileChannel = null; FileLock fileLock = null; boolean suppressExceptionOnClose = true; final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); javaClass.dump( byteStream ); byteStream.close(); final byte[] bytes = byteStream.toByteArray(); try { randomAccessFile = new RandomAccessFile( classFile, "rw" ); fileChannel = randomAccessFile.getChannel(); fileLock = fileChannel.lock(); fileChannel.truncate( bytes.length ); fileChannel.position( 0L ); fileChannel.write( ByteBuffer.wrap( bytes ) ); fileChannel.force( true ); suppressExceptionOnClose = false; } finally { this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose ); } } private void releaseAndClose( final FileLock fileLock, final FileChannel fileChannel, final Closeable closeable, final boolean suppressExceptions ) throws IOException { try { if ( fileLock != null ) { fileLock.release(); } } catch ( final IOException e ) { if ( suppressExceptions ) { this.log( Level.SEVERE, null, e ); } else { throw e; } } finally { try { if ( fileChannel != null ) { fileChannel.close(); } } catch ( final IOException e ) { if ( suppressExceptions ) { this.log( Level.SEVERE, null, e ); } else { throw e; } } finally { try { if ( closeable != null ) { closeable.close(); } } catch ( final IOException e ) { if ( suppressExceptions ) { this.log( Level.SEVERE, null, e ); } else { throw e; } } } } } private static String getMessage( final String key, final Object... arguments ) { return MessageFormat.format( ResourceBundle.getBundle( ClassFileProcessor.class.getName().replace( '.', '/' ) ).getString( key ), arguments ); } private static String getMessage( final Throwable t ) { return t != null ? t.getMessage() != null && t.getMessage().trim().length() > 0 ? t.getMessage() : getMessage( t.getCause() ) : null; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy