Maven plugin can't load class

前端 未结 4 1795
悲&欢浪女
悲&欢浪女 2020-12-29 07:23

I\'m trying to make a maven plugin that needs to use reflection. I want a project to run the plugin, and give it the full name of a class in the project, and the plugin will

相关标签:
4条回答
  • 2020-12-29 07:46

    I ran across this exact issue, today. The above suggestions didn't work for me, thought I would submit my solution to the list. I used the HibernateExporter mojo source which can be viewed at: 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 ...
    }
    

    Also make sure you are using the right MavenProject class. add this to your 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>
    
    0 讨论(0)
  • 2020-12-29 07:49

    You should consider using this to add the runtime class path elements to the current class realm. (You can use the PluginDescriptor to retrieve the class realm.

    List<String> runtimeClasspathElements = project.getRuntimeClasspathElements();
    ClassRealm realm = descriptor.getClassRealm();
    
    for (String element : runtimeClasspathElements)
    {
        File elementFile = new File(element);
        realm.addURL(elementFile.toURI().toURL());
    }
    

    This worked perfectly for me!

    As Dave asked, here is the way to get the PluginDescriptor:

    /**
     * The plugin descriptor
     * 
     * @parameter default-value="${descriptor}"
     */
    private PluginDescriptor descriptor;
    
    0 讨论(0)
  • 2020-12-29 07:52

    I'm sure there's a better way, but here's how I got it to work:

    Add the following to the javadoc at the top of your mojo: @requiresDependencyResolution runtime

    Add a MavenProject parameter:

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

    Then you can get the dependencies at runtime, and make your own 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());
    

    Then you can load your class using this new classloader:

    Class bundle = newLoader.loadClass("package.MyClass");
    
    0 讨论(0)
  • 2020-12-29 07:55

    This worked for me and maven3 to get dependencies into the plugin classpath.

    The trick is to use @Component to inject the PluginDescriptor. Otherwise it will not be set up correctly.

    @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);
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题