Подтвердить что ты не робот

Сканирование java classpath в плагине maven

То, что я пытаюсь сделать, это написать некоторый плагин Maven, который сканирует классы приложений, которые ищут реализацию определенного интерфейса (это могут быть классы с некоторой аннотацией) и основы для результата, генерирующего некоторый код. Я успешно реализовал плагин, запущенный на фазе генерации источников и написав исходный код в каталог сгенерированных источников.

Проблема заключается в сканировании пути к конкретным реализациям/классам интерфейса с некоторой аннотацией. Я использую библиотеку Reflections для сканирования классов следующим образом:

private Set<Class< ? extends MyInterface >> scan(final String packageName) {
  final Reflections reflections = new Reflections(packageName);  
  return reflections.getSubTypesOf(MyInterface.class);
}

К сожалению, этот метод возвращает пустой набор. Когда я печатаю свой classpath в классе, расширяющем org.apache.maven.plugin.AbstractMojo (тот, в котором я использую Reflections), я получаю следующий результат:

/home/pd5108/apache-maven-2.2.1/boot/classworlds-1.1.jar

Классы, которые я хочу найти с помощью Reflections, существуют в зависимых JAR, а также в модуле, в котором настроен плагин. Глядя на распечатку класса, кажется, что на данный момент (фаза генерации-источников) зависимости, определенные в maven, все еще не доступны на пути к классам - вероятно, они добавляются на следующих этапах. Это правда? Есть ли другой подход, который я могу использовать?

Вот как печатается путь к классам:

URL[] urls = ((URLClassLoader)sysClassLoader).getURLs();

for(int i=0; i< urls.length; i++) {
  System.out.println(urls[i].getFile());
}
4b9b3361

Ответ 1

Обязательные поля класса MOJO:

    /**
    * The project currently being built.
    *
    * @parameter expression="${project}"
    * @readonly
    * @required
    */
    private MavenProject project;

    /** @parameter expression="${localRepository}" */
    protected ArtifactRepository m_localRepository;

    /**@parameter default-value="${localRepository}" */
    private org.apache.maven.artifact.repository.ArtifactRepository
        localRepository;

    /** @parameter default-value="${project.remoteArtifactRepositories}" */
    private java.util.List remoteRepositories;

    /** @component */
    private org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;

    /** @component */
    private org.apache.maven.artifact.resolver.ArtifactResolver resolver;

Разрешение всех зависимостей JARs:

 final List<Dependency> dependencies = project.getDependencies();

    for (Dependency d : dependencies) {

        final Artifact artifact =
            artifactFactory.createArtifactWithClassifier(d.getGroupId(),
                d.getArtifactId(), d.getVersion(), d.getType(),
                d.getClassifier());

        try {
            resolver.resolve(artifact, remoteRepositories,
                    localRepository );
        } catch (ArtifactResolutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ArtifactNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        File artifactFile = artifact.getFile();
        System.out.println(artifactFile.getAbsolutePath());
    }

И теперь нам нужно отсканировать эти JAR с помощью API отражения, ищущего соответствующие классы. На данный момент я думаю, что другого пути нет, так как я работаю в generate-sources фазе, а значения артефакта для следующих фаз еще не вычисляются.

Ответ 2

Существуют зависимости артефактов, определенные в разделе <dependencies> и зависимостях плагина, определенных в <plugin><dependencies>.

Зависимости плагинов добавляются в путь к классам, пока я не уверен в зависимостях артефакта. Вы пытались добавить свои зависимостей плагина под <plugin><dependencies>?

Ответ 3

Возможно, вам будет проще/безопаснее/проще просто настроить конфигурацию плагина для классов, на которых вы хотите сгенерировать код. Тогда вы просто добавите его к помпе, и все готово. Не требуется никакого отражения, и это наверняка ускорит работу плагина.