Question

Je suis en train de faire un plugin maven qui doit utiliser la réflexion. Je veux un projet pour exécuter le plug-in, et de lui donner le nom complet d'une classe dans le projet, et le plug-in se charge par la réflexion pour obtenir des informations de lui.

Il y a quelque chose d'étrange avec le classloader bien, parce qu'il ne peut pas trouver la classe lorsque j'utilise

Class.forName("package.MyClass");

Recherche , je ne peux pas comprendre tout à fait si le classloader de mon plug-in, lorsqu'il est exécuté dans un autre projet, a accès aux cours de ce projet.

Était-ce utile?

La solution

Je suis sûr qu'il ya une meilleure façon, mais voici comment je l'ai eu à travailler:

Ajoutez ce qui suit à la javadoc en haut de votre mojo:     exécution @requiresDependencyResolution

Ajout d'un paramètre MavenProject:

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

Ensuite, vous pouvez obtenir les dépendances à l'exécution, et faire votre propre classloader:

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());

Ensuite, vous pouvez charger votre classe en utilisant cette nouvelle classloader:

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

Autres conseils

Vous devriez envisager d'utiliser cette option pour ajouter les éléments de chemin de classe d'exécution au royaume de la classe actuelle. (Vous pouvez utiliser le pour récupérer le PluginDescriptor royaume de classe.

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

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

Cela a parfaitement fonctionné pour moi!

Dave a demandé, voici le moyen d'obtenir le <=>:

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

Je suis tombé sur cette question précise, aujourd'hui. Les suggestions ci-dessus ne fonctionnent pas pour moi, je pensais soumettre ma solution à la liste. J'ai utilisé la source de Mojo HibernateExporter qui peut être consulté à l'adresse: 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 ...
}

Assurez-vous également que vous utilisez la bonne classe de MavenProject. ajouter à votre 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>

Cela a fonctionné pour moi et maven3 pour obtenir des dépendances dans le plug-in classpath.

L'astuce consiste à utiliser @component pour injecter le PluginDescriptor. Sinon, il ne sera pas configuré correctement.

@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);
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top