package org.codehaus.modello; /* * Copyright (c) 2004, Codehaus.org * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import org.codehaus.modello.verifier.VerifierException; import org.codehaus.plexus.compiler.Compiler; import org.codehaus.plexus.compiler.CompilerConfiguration; import org.codehaus.plexus.compiler.CompilerError; import org.codehaus.plexus.compiler.CompilerException; import org.codehaus.plexus.compiler.CompilerMessage; import org.codehaus.plexus.compiler.CompilerResult; import org.codehaus.plexus.compiler.javac.JavacCompiler; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; /** * Base class for unit-tests of Modello plugins that generate java code. * * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> * @see #compileGeneratedSources() compileGeneratedSources() method to compile generated sources * @see #verifyCompiledGeneratedSources(String) verifyCompiledGeneratedSources(String) method to run a Verifier * class against compiled generated code * @see org.codehaus.modello.verifier.Verifier Verifier base class for verifiers */ public abstract class AbstractModelloJavaGeneratorTest extends AbstractModelloGeneratorTest { private List<File> dependencies = new ArrayList<File>(); private List<URL> urls = new ArrayList<URL>(); private List<String> classPathElements = new ArrayList<String>(); protected AbstractModelloJavaGeneratorTest( String name ) { super( name ); } protected void setUp() throws Exception { super.setUp(); FileUtils.deleteDirectory( getOutputClasses() ); assertTrue( getOutputClasses().mkdirs() ); } protected File getOutputDirectory() { return new File( super.getOutputDirectory(), "sources" ); } protected File getOutputClasses() { return new File( super.getOutputDirectory(), "classes" ); } protected void addDependency( String groupId, String artifactId ) { File dependencyFile = getDependencyFile( groupId, artifactId ); dependencies.add( dependencyFile ); addClassPathFile( dependencyFile ); } protected File getDependencyFile( String groupId, String artifactId ) { // NOTE: dependency version is managed by project POM and not selectable by test String libsDir = System.getProperty( "tests.lib.dir", "target/test-libs" ); File dependencyFile = new File( libsDir, artifactId + ".jar" ); assertTrue( "Can't find dependency: " + dependencyFile.getAbsolutePath(), dependencyFile.isFile() ); return dependencyFile; } public List<File> getClasspath() { return dependencies; } protected String getModelloVersion() throws IOException { Properties properties = new Properties( System.getProperties() ); if ( properties.getProperty( "version" ) == null ) { InputStream is = getResourceAsStream( "/META-INF/maven/org.codehaus.modello/modello-test/pom.properties" ); if ( is != null ) { properties.load( is ); } } return properties.getProperty( "version" ); } protected void compileGeneratedSources() throws IOException, CompilerException { compileGeneratedSources( getName() ); } protected void compileGeneratedSources( boolean useJava5 ) throws IOException, CompilerException { compileGeneratedSources( getName(), useJava5 ); } protected void compileGeneratedSources( String verifierId ) throws IOException, CompilerException { compileGeneratedSources( verifierId, true ); } @SuppressWarnings("unchecked") protected void compileGeneratedSources( String verifierId, boolean useJava5 ) throws IOException, CompilerException { File generatedSources = getOutputDirectory(); File destinationDirectory = getOutputClasses(); addDependency( "junit", "junit" ); addDependency( "org.codehaus.plexus", "plexus-utils" ); addDependency( "org.codehaus.modello", "modello-test" ); String[] classPathElements = new String[dependencies.size() + 2]; classPathElements[0] = getTestPath( "target/classes" ); classPathElements[1] = getTestPath( "target/test-classes" ); for ( int i = 0; i < dependencies.size(); i++ ) { classPathElements[i + 2] = ( (File) dependencies.get( i ) ).getAbsolutePath(); } File verifierDirectory = getTestFile( "src/test/verifiers/" + verifierId ); String[] sourceDirectories; if ( verifierDirectory.canRead() ) { sourceDirectories = new String[]{ verifierDirectory.getAbsolutePath(), generatedSources.getAbsolutePath() }; } else { sourceDirectories = new String[]{ generatedSources.getAbsolutePath() }; } Compiler compiler = new JavacCompiler(); CompilerConfiguration configuration = new CompilerConfiguration(); configuration.setClasspathEntries( Arrays.asList( classPathElements ) ); configuration.setSourceLocations( Arrays.asList( sourceDirectories ) ); configuration.setOutputLocation( destinationDirectory.getAbsolutePath() ); configuration.setDebug( true ); if ( useJava5 ) { configuration.setSourceVersion( "1.5" ); configuration.setTargetVersion( "1.5" ); } else { configuration.setSourceVersion( "1.4" ); configuration.setTargetVersion( "1.4" ); } CompilerResult result = compiler.performCompile( configuration ); List<CompilerMessage> messages = result.getCompilerMessages(); for ( CompilerMessage message : messages ) { System.out.println( message.getFile() + "[" + message.getStartLine() + "," + message.getStartColumn() + "]: " + message.getMessage() ); } List<CompilerMessage> errors = new ArrayList<CompilerMessage>( 0 ); for ( CompilerMessage compilerMessage : result.getCompilerMessages() ) { if ( compilerMessage.isError() ) { errors.add( compilerMessage ); } } assertEquals( "There was compilation errors: " + errors, 0, errors.size() ); } /** * Run a verifier class in a classloader context where compiled generated sources are available * * @param verifierClassName the class name of the verifier class * @throws MalformedURLException */ protected void verifyCompiledGeneratedSources( String verifierClassName ) throws MalformedURLException { addClassPathFile( getOutputClasses() ); addClassPathFile( getTestFile( "target/classes" ) ); addClassPathFile( getTestFile( "target/test-classes" ) ); ClassLoader oldCCL = Thread.currentThread().getContextClassLoader(); URLClassLoader classLoader = URLClassLoader.newInstance( urls.toArray( new URL[urls.size()] ), null ); Thread.currentThread().setContextClassLoader( classLoader ); try { Class<?> clazz = classLoader.loadClass( verifierClassName ); Method verify = clazz.getMethod( "verify", new Class[0] ); try { verify.invoke( clazz.newInstance(), new Object[0] ); } catch ( InvocationTargetException ex ) { throw ex.getCause(); } } catch ( Throwable throwable ) { throw new VerifierException( "Error verifying modello tests: " + throwable.getMessage(), throwable ); } finally { Thread.currentThread().setContextClassLoader( oldCCL ); } } protected void addClassPathFile( File file ) { assertTrue( "File doesn't exists: " + file.getAbsolutePath(), file.exists() ); try { urls.add( file.toURI().toURL() ); } catch ( MalformedURLException e ) { throw new RuntimeException( e ); } classPathElements.add( file.getAbsolutePath() ); } protected void printClasspath( URLClassLoader classLoader ) { URL[] urls = classLoader.getURLs(); for ( URL url : urls ) { System.out.println( url ); } } protected void assertGeneratedFileExists( String filename ) { File file = new File( getOutputDirectory(), filename ); assertTrue( "Missing generated file: " + file.getAbsolutePath(), file.canRead() ); assertTrue( "The generated file is empty.", file.length() > 0 ); } /** * Check if a Java 5 feature test should be skipped, since it is not supported by current test environment. * * @return <code>true</code> if Java 5 is not available, then feature test should be skipped by caller */ protected boolean skipJava5FeatureTest() { String javaVersion = System.getProperty( "java.specification.version", "1.5" ); if ( "1.5".compareTo( javaVersion ) > 0 ) { System.out.println( "Skipped Java 5 feature test, not supported by current test environment (" + javaVersion + ")" ); return true; } return false; } protected List<String> getClassPathElements() { return classPathElements; } }