2009-05-16 9 views
13

Estoy tratando de hacer un plugin maven que necesite usar el reflejo. Quiero un proyecto para ejecutar el complemento y darle el nombre completo de una clase en el proyecto, y el complemento lo cargará por reflexión para obtener información de él.El complemento Maven no puede cargar la clase

Hay algo extraño con el cargador de clase, sin embargo, porque no puede encontrar la clase cuando uso

Class.forName("package.MyClass"); 

Buscando here, yo no puedo averiguar si cargador de clases de mi plugin, cuando se está ejecutando en una proyecto diferente, tiene acceso a las clases de ese proyecto.

Respuesta

11

Estoy seguro de que hay una mejor manera, pero aquí es cómo llegué a trabajar:

Añadir lo siguiente a la javadoc en la parte superior de su mojo: @requiresDependencyResolution tiempo de ejecución

Añadir un MavenProject parámetro:

/** 
* @parameter expression="${project}" 
* @required 
* @readonly 
*/ 
private MavenProject project; 

entonces se puede obtener las dependencias en tiempo de ejecución, y hacer su propio cargador de clases:

List runtimeClasspathElements = project.getRuntimeClasspathElements(); 
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()]; 
for (int i = 0; i < runtimeClasspathElements.size(); i++) { 
    String element = (String) runtimeClasspathElements.get(i); 
    runtimeUrls[i] = new File(element).toURI().toURL(); 
} 
URLClassLoader newLoader = new URLClassLoader(runtimeUrls, 
    Thread.currentThread().getContextClassLoader()); 

A continuación, puede cargar su clase utilizando este nuevo cargador de clases:

Class bundle = newLoader.loadClass("package.MyClass"); 
11

Usted debe considerar el uso de esta opción para agregar los elementos de la ruta de clase en tiempo de ejecución en el ámbito clase actual. (Puede utilizar el PluginDescriptor para recuperar el reino de clase

List<String> runtimeClasspathElements = project.getRuntimeClasspathElements(); 
ClassRealm realm = descriptor.getClassRealm(); 

for (String element : runtimeClasspathElements) 
{ 
    File elementFile = new File(element); 
    realm.addURL(elementFile.toURI().toURL()); 
} 

Esto funcionó perfectamente para mí

Como pidió a Dave, aquí está la manera de obtener el PluginDescriptor:.!

/** 
* The plugin descriptor 
* 
* @parameter default-value="${descriptor}" 
*/ 
private PluginDescriptor descriptor; 
+0

¿cómo se obtiene un control para PluginDescriptor desde el método de ejecución de MyMojo? – Upgradingdave

+1

Hola Dave, ajusté mi respuesta, espero que te ayude. (No necesita un setter, ya que esto se establece mediante reflexiones afair). – codevour

+0

Muchas gracias, no pude encontrar eso en los documentos en ninguna parte. – Upgradingdave

1

I encontré este problema exacto hoy. Las sugerencias anteriores no me funcionaron, pensé en enviar mi solución a la lista. Utilicé la fuente de mojo de HibernateExporter, que se puede ver en: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.mojo/hibernate3-maven-plugin/2.2/org/codehaus/mojo/hibernate3/HibernateExporterMojo.java?av=f

/** 
* @parameter expression="${project}" 
* @required 
* @readonly 
*/ 
private MavenProject project; 

private ClassLoader getClassLoader() throws MojoExecutionException 
{ 
    try 
    { 
    List<String> classpathElements = project.getCompileClasspathElements(); 
    classpathElements.add(project.getBuild().getOutputDirectory()); 
    classpathElements.add(project.getBuild().getTestOutputDirectory()); 
    URL urls[] = new URL[classpathElements.size()]; 

    for (int i = 0; i < classpathElements.size(); ++i) 
    { 
     urls[i] = new File((String) classpathElements.get(i)).toURI().toURL(); 
    } 
    return new URLClassLoader(urls, getClass().getClassLoader()); 
    } 
    catch (Exception e)//gotta catch em all 
    { 
    throw new MojoExecutionException("Couldn't create a classloader.", e); 
    } 
} 

public void execute() throws MojoExecutionException 
{ 
    ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 
    Thread.currentThread().setContextClassLoader(getClassLoader()); 

    //... your code here ... 
} 

También asegúrese de estar utilizando la clase MavenProject correcta. agregue esto a su pom

<dependency> 
    <groupId>org.apache.maven</groupId> 
    <artifactId>maven-core</artifactId> 
    <version>3.0.3</version> 
</dependency> 

<dependency> 
    <groupId>org.apache.maven</groupId> 
    <artifactId>maven-plugin-api</artifactId> 
    <version>3.0.3</version> 
</dependency> 
1

Esto funcionó para mí y maven3 para obtener dependencias en el classpath del plugin.

El truco es usar @Component para inyectar el PluginDescriptor. De lo contrario, no se configurará correctamente.

@Component 
private MavenProject project; 
@Component 
private PluginDescriptor descriptor; 

private void addDependenciesToClasspath(String artifactId) { 
    for (Artifact artifact : project.getDependencyArtifacts()) { 
     if (artifact.getArtifactId().equals(artifactId)) { 
      try { 
       final URL url = artifact.getFile().toURI().toURL(); 
       final ClassRealm realm = descriptor.getClassRealm(); 
       realm.addURL(url); 
      } 
      catch (MalformedURLException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } 
} 
Cuestiones relacionadas