Как можно избежать указания полного имени класса в командной строке при доставке одного jar-файла и использовании отражения? - PullRequest
3 голосов
/ 11 января 2012

У меня есть кодовая база, которую я хочу создать несколько доставляемых jar-файлов, каждый из которых должен запускаться из командной строки и который обращается к некоторым функциям кодовой базы. При запуске некоторые из параметров командной строки - это другие классы внутри jar, которые затем создаются отражением. Это хорошо работает, но я должен указать очень длинный полный путь к классу, даже если классы находятся в файле jar.

Я использую муравей для компиляции, а затем запускаю серию каталогов. Из минимального примера файла build.xml:

<property name="build" location="build"/>
<property name="jars" location="${build}/jars"/>
<property name="classes" location="${build}/classes"/>
<property name="src" location="src/dom/place/proj"/>

<target name="utility">
 <javac 
    includeantruntime="false" 
    srcdir="${src}/utility" destdir="${classes}" 
    classpathref="classpath" />
 <jar 
    destfile="${jars}/utility.jar" 
    basedir="${classes}" 
    includes="**/utility/**" />
</target>

<target name="tokenizers" depends="utility">
 <javac 
    includeantruntime="false" 
    srcdir="${src}/tokenizers" 
    destdir="${classes}" 
    classpathref="classpath" />
 <jar 
    destfile="${jars}/tokenizers.jar" 
    basedir="${classes}" 
    includes="**/tokenizers/**" />
</target>

Позже я создаю один JAR-файл, который включает в себя все необходимые классы и запускает команду, например:

<target name="tokenize-file-jar">
 <jar destfile="${dist}/TokenizeFile.jar">
  <zipgroupfileset dir="${jars}">
    <include name="utility.jar"/>
    <include name="tokenizers.jar"/>
  </zipgroupfileset>
  <manifest>
    <attribute name="Main-Class" value="dom.place.proj.tokenizers.TokenizeFile"/>
  </manifest>     
 </jar>    
</target>

Это все работает, и, глядя в файл jar, все классы есть.

prompt > unzip -l TokenizeFile.jar 
Archive:  TokenizeFile.jar
Length     Date   Time    Name
--------    ----   ----    ----
        0  01-11-12 11:07   META-INF/
      286  01-11-12 11:07   META-INF/MANIFEST.MF
        0  01-11-12 10:16   dom/
        0  01-11-12 10:16   dom/place/
        0  01-11-12 10:16   dom/place/proj/
        0  01-11-12 10:16   dom/place/proj/tokenizers/
     1737  01-11-12 11:07   dom/place/proj/tokenizers/FileTokenizer.class
     1411  01-11-12 11:07   dom/place/proj/tokenizers/PorterTokenizer.class
     1754  01-11-12 11:07   dom/place/proj/tokenizers/TokenizeFile.class
      992  01-11-12 11:07   dom/place/proj/tokenizers/Tokenizer.class
        0  01-11-12 10:16   dom/place/proj/utility/
     1106  01-11-12 11:07   dom/place/proj/utility/BoundedExecutor.class
     3128  01-11-12 11:07   dom/place/proj/utility/Converter.class
     1107  01-11-12 11:07   dom/place/proj/utility/ExceptionHandler.class

Теперь, чтобы запустить код, я делаю:

java -jar TokenizeFile.jar test.txt dom.place.proj.tokenizers.FileTokenizer dom.place.proj.tokenizers.PorterTokenizer

и это работает. Ура! Но я бы предпочел, чтобы мой клиент не указывал полное имя для каждого класса в командной строке - это небольшой пример, и может быть много элементов. Что я могу изменить в своем коде или в процессе сборки, чтобы разрешить это вместо этого:

java -jar TokenizeFile.jar test.txt FileTokenizer PorterTokenizer

Спасибо за вашу помощь. Я очень давно перехожу с C ++ / make и очень люблю ant и Java.

1 Ответ

5 голосов
/ 11 января 2012

Короткий и простой ответ: это невозможно; Имена классов однозначны только с учетом их пакета.

Один из способов сделать вещи проще для вызывающих абонентов - сделать так, чтобы ваше приложение добавляло "dom.place.proj.tokenizers." к каждому аргументу класса, который они предоставляют - так что ваш более короткий предпочтительный пример будет вести себя идентично первому.

Однако, с большой простотой приходит уменьшенная сила; пользователь больше не сможет определять свой собственный класс и передавать его, так как пакеты не будут совпадать. (В некоторой степени вы могли бы обойти это, только добавив пакет по умолчанию, если имя класса не содержит точку (.), но чем больше особых случаев вы добавите, тем сложнее будет это понять ...)


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

Поэтому я рекомендую оставить вещи такими, какие они есть, и, в основном, привыкнуть к первой версии командной строки. Даже если бы вам пришлось решить проблему в этом конкретном случае, есть много других сторонних и Java-приложений и инструментов, которые требуют, чтобы классы были указаны в командной строке, и все они требуют полного имени класса. тоже.

Извините, если это не похоже на ответ, но я считаю, что это лучший способ действий в этой ситуации.

...