Не удается загрузить ресурсы в обработчике аннотации (не на пути к классам)

У меня есть обработчик аннотации, который должен генерировать перечисление с ключами, определяемыми методами getter интерфейса.

Интерфейс находится в

MyProject/SRC/Основной/Java/my.package.MyInterfaces.java.

Я хочу проверить файлы свойств, которые находятся в MyProject/src/main/resources/META-INF/resource-bundle/, если они содержат ключи, определенные в сгенерированном перечислении.

Моя проблема в том, что файлы свойств недоступны через загрузчик классов процессора или через Filer.getResource(...).

  • Как я могу сделать путь источника или класса этого проекта доступным для процессора, чтобы я мог загружать файлы свойств?

  • Теперь у меня есть только ресурсы в банке, где доступен процессор. Я попытался определить -classpath и/или -sourcepath через eclipse Project/Properties/Java компилятор/Обработка аннотации/Параметры процессора, но это не сработало.

Кто-нибудь сталкивался с такой проблемой, и может ли кто-нибудь дать мне понять, как я могу сделать ресурсы доступными для процессора?

У меня есть структура maven, но я не использую maven из-за старых зависимостей внутри приложения. Так что maven теперь не вариант для меня.

Eclipse 3.6 Helios Кажется, что StandardLocation.SOURCE_PATH и StandardLocation.CLASS_PATH не реализованы в Filer # getResource(), поэтому запись созданных исходных файлов или файлов классов в SOURCE_PATH или CLASS_PATH представляется невозможной, также доступ к любым файлам на SOURCE_PATH и CLASS_PATH *

Спасибо.

Ответ 1

Моя проблема в том, что файлы свойств недоступны через загрузчик классов процессора или через Filer.getResource(...).

Я не уверен, что понимаю вашу проблему. Но, возможно, что-то здесь поможет.

Как я могу сделать путь источника или classpath этого проекта доступным для процессора, чтобы я мог загружать файлы свойств?

Вам нужно добавить src/main/resources в качестве "исходной папки" в Eclipse. Сначала выберите Configure Build Path в Eclipse в вашем проекте Java. Затем выберите вкладку Source и нажмите Add Folder. Вы должны выбрать папку src/main/resources и нажать Ok. Теперь вы должны увидеть src/main/resources в списке "Исходные папки".

Если вы заглянете в свой каталог target/classes, вы должны увидеть все файлы из каталога ресурсов, который позволяет вам знать, что они были скопированы в путь к классам правильно.

# files in the src main resources
> ls src/main/resources/x/y/z
jgroups_udp.xml
# should compile into target/classes
> ls target/classes/x/y/z
jgroups_udp.xml org
# and should show up in the jar
> -tvf target/project.jar 
   0 Thu Nov 03 18:50:00 EDT 2016 META-INF/
 135 Thu Nov 03 18:49:58 EDT 2016 META-INF/MANIFEST.MF
 ...
3036 Thu Nov 03 18:49:36 EDT 2016 x/y/z/jgroups_udp.xml

Затем в вашем коде вы можете ссылаться на файл, выполнив следующее. Это загрузит файл из верхней части пути к классам. Если он находится в поддиректории, то вы приводите:

InputStream stream =
    getClass().getClassLoader().getResourceAsStream("x/y/z/jgroups_udp.xml");

Btw, если вы использовали maven, вы добавили бы что-то вроде следующего: pom.xml:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>

Ответ 2

В качестве обходного пути вы можете попытаться добавить путь к классам, который вам нужно использовать с помощью аргумента командной строки -Xboothclasspath/a: path,/a добавит значение в путь к пути класса загрузки. Вам нужно будет добавить это как параметр командной строки для фактического запуска обработки аннотации, поэтому в Eclipse это будет: Щелкните правой кнопкой мыши проект, выберите свойства, Компилятор Java, Обработку аннотации, нажмите "Создать" в таблице и добавьте ключ -Xbootclasspath/a и путь для добавления в качестве значения. Боюсь, я не пробовал это для обработки аннотаций, но стоит попробовать!

Ответ 3

Проблема заключается в том, что ClassLoader связан с текущим потоком (Thread.currentThread().getContextClassLoader()) не является URLClassLoader при вызове Processor#process. Похоже, что это загрузчик классов с ограниченным доступом, который не позволяет загружать ресурсы. Это происходит с javac, компилятором eclipse, компилятором maven и т.д.

К счастью, ваш класс процессора будет иметь соответствующий ClassLoader, связанный с ним (то есть getClass().getClassLoader()).

Проблема заключается в том, что большинство утилит ожидают, что корректный ClassLoader будет связан с потоком (особенно это касается ServiceLoader и ResourceBundles).

Таким образом, есть обходной путь. Когда ваш Процессор выполняется, вы можете привязать ClassLoader к текущему потоку:

@Override
public boolean process(
        Set<? extends TypeElement> annotations,
        RoundEnvironment roundEnv) {

    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
    //...
}