Плагин Maven не может загрузить класс - PullRequest
14 голосов
/ 16 мая 2009

Я пытаюсь сделать плагин maven, который должен использовать отражение. Я хочу, чтобы проект запустил плагин и дал ему полное имя класса в проекте, и плагин загрузит его по отражению, чтобы получить от него информацию.

В загрузчике классов есть что-то странное, потому что он не может найти класс, когда я использую

Class.forName("package.MyClass");

Глядя здесь , я не могу понять, имеет ли загрузчик классов моего плагина, когда он запускается в другом проекте, доступ к классам этого проекта.

Ответы [ 4 ]

16 голосов
/ 19 мая 2009

Я уверен, что есть лучший способ, но вот как я заставил его работать:

Добавьте следующее в Javadoc в верхней части вашего mojo: @requiresDependencyResolution runtime

Добавить параметр MavenProject:

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

Затем вы можете получить зависимости во время выполнения и создать свой собственный загрузчик классов:

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

Затем вы можете загрузить свой класс, используя этот новый загрузчик классов:

Class bundle = newLoader.loadClass("package.MyClass");
11 голосов
/ 07 февраля 2011

Вы должны рассмотреть возможность использования этого для добавления элементов пути класса времени выполнения в текущую область класса. (Вы можете использовать PluginDescriptor для извлечения области классов.

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

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

Это отлично сработало для меня!

Как спросил Дейв, вот способ получить PluginDescriptor:

/**
 * The plugin descriptor
 * 
 * @parameter default-value="${descriptor}"
 */
private PluginDescriptor descriptor;
4 голосов
/ 04 ноября 2012

Сегодня я столкнулся с этой проблемой. Вышеуказанные предложения не работают для меня, думал, что я отправлю свое решение в список. Я использовал источник mojo HibernateExporter, который можно посмотреть по адресу: 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 ...
}

Также убедитесь, что вы используете правильный класс MavenProject. добавь это к своей поме

<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 голос
/ 19 марта 2015

Это сработало для меня и maven3, чтобы получить зависимости в classpath плагина.

Хитрость заключается в использовании @Component для внедрения PluginDescriptor. В противном случае он не будет настроен правильно.

@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);
            }
        }
    }
}
...