package org.codehaus.mojo.hibernate3.configuration;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.util.ReflectHelper;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.model.Build;
import org.apache.maven.artifact.Artifact;
import org.jboss.util.file.ArchiveBrowser;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javax.persistence.Embeddable;
import javax.persistence.PersistenceException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.File;
import javassist.bytecode.ClassFile;
import javassist.bytecode.AnnotationsAttribute;
public class AnnotationComponentConfiguration
extends AbstractComponentConfiguration
{
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface ComponentConfiguration ---------------------
public String getName()
{
return "annotationconfiguration";
}
// -------------------------- OTHER METHODS --------------------------
protected Configuration createConfiguration()
{
// retrievethe Build object
Build build = getExporterMojo().getProject().getBuild();
// now create an empty arraylist that is going to hold our entities
List<String> entities = new ArrayList<String>();
try
{
if ( getExporterMojo().getComponentProperty( "scan-classes", false ) )
{
scanForClasses( new File( build.getOutputDirectory() ), entities );
scanForClasses( new File( build.getTestOutputDirectory() ), entities );
}
if ( getExporterMojo().getComponentProperty( "scan-jars", false ) )
{
@SuppressWarnings( "unchecked" )
List<Artifact> runtimeArtifacts = getExporterMojo().getProject().getRuntimeArtifacts();
for ( Artifact a : runtimeArtifacts )
{
File artifactFile = a.getFile();
if ( !artifactFile.isDirectory() )
{
getExporterMojo().getLog().debug( "[URL] " + artifactFile.toURI().toURL().toString() );
scanForClasses( artifactFile, entities );
}
}
@SuppressWarnings( "unchecked" )
List<Artifact> testArtifacts = getExporterMojo().getProject().getTestArtifacts();
for ( Artifact a : testArtifacts )
{
File artifactFile = a.getFile();
if ( !artifactFile.isDirectory() )
{
getExporterMojo().getLog().debug( "[URL] " + artifactFile.toURI().toURL().toString() );
scanForClasses( artifactFile, entities );
}
}
}
}
catch ( MalformedURLException e )
{
getExporterMojo().getLog().error( e.getMessage(), e );
return null;
}
// now create the configuration object
AnnotationConfiguration configuration = new AnnotationConfiguration();
addNamedAnnotatedClasses( configuration, entities );
return configuration;
}
private void scanForClasses( File directory, List<String> entities )
throws MalformedURLException
{
if ( directory.list() != null )
{
getExporterMojo().getLog().debug( "[scanForClasses] " + directory );
URL jar = directory.toURI().toURL();
Iterator<?> it;
try
{
it = ArchiveBrowser.getBrowser( jar, new ArchiveBrowser.Filter()
{
public boolean accept( String filename )
{
return filename.endsWith( ".class" );
}
} );
}
catch ( RuntimeException e )
{
throw new RuntimeException( "error trying to scan <jar-file>: " + jar.toString(), e );
}
// need to look into every entry in the archive to see if anybody has tags
// defined.
while ( it.hasNext() )
{
InputStream stream = (InputStream) it.next();
DataInputStream dstream = new DataInputStream( stream );
ClassFile cf = null;
try
{
try
{
cf = new ClassFile( dstream );
}
finally
{
dstream.close();
stream.close();
}
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
AnnotationsAttribute visible =
(AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
if ( visible != null )
{
boolean isEntity = visible.getAnnotation( Entity.class.getName() ) != null;
if ( isEntity )
{
getExporterMojo().getLog().info( "found EJB3 Entity bean: " + cf.getName() );
entities.add( cf.getName() );
}
boolean isEmbeddable = visible.getAnnotation( Embeddable.class.getName() ) != null;
if ( isEmbeddable )
{
getExporterMojo().getLog().info( "found EJB3 @Embeddable: " + cf.getName() );
entities.add( cf.getName() );
}
boolean isEmbeddableSuperclass = visible.getAnnotation( MappedSuperclass.class.getName() ) != null;
if ( isEmbeddableSuperclass )
{
getExporterMojo().getLog().info( "found EJB3 @MappedSuperclass: " + cf.getName() );
entities.add( cf.getName() );
}
}
}
}
}
private void addNamedAnnotatedClasses( AnnotationConfiguration cfg, Collection<String> classNames )
{
for ( String name : classNames )
{
try
{
Class<?> clazz = classForName( name );
cfg.addAnnotatedClass( clazz );
}
catch ( ClassNotFoundException cnfe )
{
Package pkg;
try
{
pkg = classForName( name + ".package-info" ).getPackage();
}
catch ( ClassNotFoundException e )
{
pkg = null;
}
if ( pkg == null )
{
throw new PersistenceException( name + " class or package not found", cnfe );
}
else
{
cfg.addPackage( name );
}
}
}
}
private Class<?> classForName( String className )
throws ClassNotFoundException
{
return ReflectHelper.classForName( className, this.getClass() );
}
protected void validateParameters()
throws MojoExecutionException
{
super.validateParameters();
if ( getConfigurationFile() == null && !getExporterMojo().getComponentProperty( "scan-classes", false ) &&
!getExporterMojo().getComponentProperty( "scan-jars", false ) )
{
throw new MojoExecutionException( "No hibernate.cfg.xml configuration provided. " +
"Annotated classes/packages is only configurable via hibernate.cfg.xml" );
}
}
}