org.codehaus.mojo.natives.plugin.NativeJavahMojo Maven / Gradle / Ivy
package org.codehaus.mojo.natives.plugin;
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
*
* 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 java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.natives.NativeBuildException;
import org.codehaus.mojo.natives.javah.Javah;
import org.codehaus.mojo.natives.javah.JavahConfiguration;
import org.codehaus.mojo.natives.manager.JavahManager;
import org.codehaus.mojo.natives.manager.NoSuchNativeProviderException;
import org.codehaus.plexus.util.FileUtils;
/**
* Generate JNI include files based on a set of class names
* @goal javah
* @phase generate-sources
* @requiresDependencyResolution compile
*/
public class NativeJavahMojo
extends AbstractNativeMojo
{
/**
* Javah Provider.
* @parameter default-value="default"
* @required
* @since 1.0-alpha-2
*/
private String javahProvider;
/**
* @parameter
* @deprecated Use javahClassNames instead. Note starting 1.0-alpha-4, running javah in its own
* execution is no longer necessary since it is implicitly bound to all shared library custom lifecycle.
* @since 1.0-alpha-2
*/
private List classNames;
/**
* List of class names to generate native files. Additional JNI interface will automatically
* discovered from project's dependencies of jar type,
* when javahSearchJNIFromDependencies is true
* @parameter
* @since 1.0-alpha-4
*/
private List javahClassNames = new ArrayList( 0 );
/**
* Enable the search from project dependencies for JNI interfaces, in addition to javahClassNames
* @parameter default-value="false"
* @since 1.0-alpha-4
*/
private boolean javahSearchJNIFromDependencies;
/**
* Path to javah executable, if present, it will override the default one which bases on architecture type.
* See 'javahProvider' argument
* @parameter
* @since 1.0-alpha-2
*/
private File javahPath;
/**
* Where to place javah generated file
* @deprecated use javahOutputDirectory instead
* @parameter
* @since 1.0-alpha-2
*/
protected File outputDirectory;
/**
* Where to place javah generated file
* @parameter default-value="${project.build.directory}/native/javah"
* @required
* @since 1.0-alpha-2
*/
protected File javahOutputDirectory;
/**
* if configured will be combined with outputDirectory to pass into javah's -o option
* @parameter
* @since 1.0-alpha-4
*/
private String javahOutputFileName;
/**
* if configured will be combined with outputDirectory to pass into javah's -o option
* @parameter
* @deprecated Use javaOutputFileName instead
* @since 1.0-alpha-2
*/
private String outputFileName;
/**
* Enable javah verbose mode
* @parameter default-value="false"
* @since 1.0-alpha-2
*/
private boolean javahVerbose;
/**
* Internal: To look up javah implementation
* @component
* @readonly
* @since 1.0-alpha-2
*/
private JavahManager manager;
/**
* For unit test only
*/
private JavahConfiguration config;
public void execute()
throws MojoExecutionException
{
//until we remove the deprecated configuration
if ( this.outputDirectory != null )
{
this.javahOutputDirectory = this.outputDirectory;
}
if ( this.outputFileName != null )
{
this.javahOutputFileName = this.outputFileName;
}
if ( this.classNames != null )
{
this.javahClassNames.addAll( this.classNames );
}
this.discoverAdditionalJNIClassName();
if ( this.javahClassNames.size() == 0 )
{
return;
}
try
{
this.config = this.createProviderConfiguration();
this.getJavah().compile( config );
}
catch ( NativeBuildException e )
{
throw new MojoExecutionException( "Error running javah command", e );
}
this.project.addCompileSourceRoot( this.javahOutputDirectory.getAbsolutePath() );
}
private Javah getJavah()
throws MojoExecutionException
{
Javah javah;
try
{
javah = this.manager.getJavah( this.javahProvider );
}
catch ( NoSuchNativeProviderException pe )
{
throw new MojoExecutionException( pe.getMessage() );
}
return javah;
}
/**
* Get all jars in the pom excluding transitive, test, and provided scope dependencies.
* @return
*/
private List getJavahArtifacts()
{
List list = new ArrayList();
List artifacts = this.project.getCompileArtifacts();
if ( artifacts != null )
{
for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
{
Artifact artifact = (Artifact) iter.next();
//pick up only jar files
if ( !"jar".equals( artifact.getType() ) )
{
continue;
}
//exclude some other scopes
if ( Artifact.SCOPE_PROVIDED.equals( artifact.getScope() ) )
{
continue;
}
list.add( artifact );
}
}
return list;
}
/**
* Build classpaths from dependent jars including project output directory
* (i.e. classes directory )
* @return
*/
private String[] getJavahClassPath()
{
List artifacts = this.getJavahArtifacts();
String[] classPaths = new String[artifacts.size() + 1];
classPaths[0] = this.project.getBuild().getOutputDirectory();
Iterator iter = artifacts.iterator();
for ( int i = 1; i < classPaths.length; ++i )
{
Artifact artifact = (Artifact) iter.next();
classPaths[i] = artifact.getFile().getPath();
}
return classPaths;
}
/**
*
* Get applicable class names to be "javahed"
*
*/
private void discoverAdditionalJNIClassName()
throws MojoExecutionException
{
if ( !this.javahSearchJNIFromDependencies )
{
return;
}
//scan the immediate dependency list for jni classes
List artifacts = this.getJavahArtifacts();
for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
{
Artifact artifact = (Artifact) iter.next();
this.getLog().info( "Parsing " + artifact.getFile() + " for native classes." );
try
{
Enumeration zipEntries = new ZipFile( artifact.getFile() ).entries();
while ( zipEntries.hasMoreElements() )
{
ZipEntry zipEntry = (ZipEntry) zipEntries.nextElement();
if ( "class".equals( FileUtils.extension( zipEntry.getName() ) ) )
{
ClassParser parser = new ClassParser( artifact.getFile().getPath(), zipEntry.getName() );
JavaClass clazz = parser.parse();
Method[] methods = clazz.getMethods();
for ( int j = 0; j < methods.length; ++j )
{
if ( methods[j].isNative() )
{
javahClassNames.add( clazz.getClassName() );
this.getLog().info( "Found native class: " + clazz.getClassName() );
break;
}
}
}
}//endwhile
}
catch ( IOException ioe )
{
throw new MojoExecutionException( "Error searching for native class in " + artifact.getFile(), ioe );
}
}
}
private JavahConfiguration createProviderConfiguration()
throws MojoExecutionException
{
JavahConfiguration config = new JavahConfiguration();
config.setWorkingDirectory( this.workingDirectory );
config.setVerbose( this.javahVerbose );
config.setOutputDirectory( this.javahOutputDirectory );
config.setFileName( this.javahOutputFileName );
config.setClassPaths( this.getJavahClassPath() );
config.setClassNames( (String[]) javahClassNames.toArray( new String[javahClassNames.size()] ) );
config.setJavahPath( this.javahPath );
return config;
}
/**
* Internal only for test harness purpose
* @return
*/
protected JavahConfiguration getJavahConfiguration()
{
return this.config;
}
/**
* Internal for unit test only
*/
protected MavenProject getProject()
{
return this.project;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy