МУРАВЕЙ. Переопределить свойства. Дополнительное исполнение в одной цели - PullRequest
1 голос
/ 05 марта 2010

Я собираюсь опубликовать вопрос, который я видел варианты в другом месте, но где я не совсем видел ответ, который я придумал. Впоследствии я опубликую свой ответ.

Для того чтобы модулировать мой сценарий сборки с помощью макросов, я хотел бы поместить в один и тот же макрос макрос и задачу обновления, и задачу, которую я хочу выполнить, если она не актуальна.
Как мне это сделать - с помощью тега script все в порядке - если единственным уникальным атрибутом, который передается, является путь, содержащий обратную косую черту, и мне нужно иметь возможность передавать различные значения тегу script при разных вызовах. Мне нужно избегать любых проблем, которые могут возникнуть со строковыми литералами, когда присутствует обратная косая черта. Используя уникальный атрибут, мне нужно обойти поведение неизменяемого свойства муравья и обойти шаблон муравья, который обычно использует 2 цели для обработки решений обработки обновлений и должен обходить обработку обратного слеша в JavaScript при помощи строковых литералов.

1 Ответ

2 голосов
/ 05 марта 2010

Обратите внимание, я работаю с муравьем 1.7.С локальной областью видимости в Ant 1.8 есть некоторые дополнительные опции, так что неизменность не такая уж сложная задача, но некоторые из этих других советов будут по-прежнему полезны.

Во-первых, в отношении вопроса о дополнительном выполнении задачи на основерезультаты обновления в макросе - это означает, что вам не нужно 2 цели.Для этого используйте тег условия.Тег заставит его выполнить второе условие только в случае сбоя первого условия.Тег позволяет использовать JavaScript для выполнения других задач муравья.Вот пример (@-теги обозначают атрибуты macrodef):

<condition property="whatever" value="false">
  <or>
    <uptodate>
      <srcfiles dir="@{srcdir}" includes="@{srcincludes}" excludes="@{srcexcludes}"/>
      <mapper><chainedmapper>
        <flattenmapper/><!-- use any mappers you need to match source to target files-->
        <globmapper from="*.jxw" to="@{targetdir}\*W.java"/>
      </chainedmapper></mapper>
    </uptodate>
    <!-- w/ java 1.6 or later, you get a rhino javascript interpreter included w/ java-->
    <scriptcondition language="javascript" value="true">
      self.setValue(true);
      echo = project.createTask("echo");
      myArg1="@{myArg1}";
      myArg2="@{myArg2}";
      // need to create a reference from a classpath refid
      myReference = new org.apache.tools.ant.types.Reference(project,"@{my.classpath.id.string}");
      // get a handle to the ant java task, which we will use to execute a java program
      javaTask = project.createTask("java");
      javaTask.setFork(true);
      javaTask.setFailonerror(true);
      javaTask.setClassname("com.mycompany.mypackage.MySpecialClass");
      javaTask.setClasspathRef(myReference);
      javaTask.createArg().setValue(myArg1);
      javaTask.createArg().setValue(myArg2);

      //output the command line to standard out, for reference
      echo.setMessage(javaTask.getCommandLine());
      echo.perform();
      javaTask.perform();
    </scriptcondition>
  </or>
</condition>

Теперь, если вы похожи на меня, вы можете захотеть выполнить некоторую обработку с атрибутами, которые являются вашими входными данными macrodef, и получить некоторые производные значения, которые могутбыть упомянутым в вашем скрипте macrodef.Если ваша обработка просто включает в себя конкатенацию атрибутов и строк, вы можете сделать это в блоке, где вы указали свои атрибуты, указав второй набор атрибутов со значением по умолчанию, который содержит шаги конкатенации.Однако, если вам нужно сделать что-то, что вы не можете подключить к атрибуту по умолчанию, вам нужно будет поместить его в свойство.Поскольку свойства являются неизменяемыми, вам нужно предпринять некоторые дополнительные шаги, чтобы дать вашей собственности уникальные имена.Tstamp пригодится, чтобы помочь с этим.Как правило, некоторая комбинация параметров, передаваемых вашему макросу, будет уникальной, но если эта уникальная комбинация включает в себя обратную косую черту, вы захотите получить вторичный уникальный идентификатор, используя тег tstamp, чтобы вы не столкнулись с проблемами обратной косой черты в своем JavaScript, когдаВы хотите использовать эти производные свойства.Вот как создать ваши уникальные свойства, на которые вы можете легко ссылаться в своем скрипте.

<macrodef name="public.macro.example">
  <attribute name="srcpath"/>
    <sequential>
      <tstamp prefix="@{srcpath}"><format pattern="ddhhmmssSSS" property="time"/></tstamp>
      <private.macro.example srcpath="@{srcpath}" propertyPrefix="prop${@{srcpath}.time}"/>
    </sequential>
</macrodef>

<macrodef name="private.macro.example">
  <attribute name="srcpath"/>
  <attribute name="prefix"/>
  <sequential>
    <pathconvert property="@{prefix}.src"/>
    <!-- now you can do special things with ${@{prefix}.src}, even in javascript -->
    <script language="javascript">
      self.setValue(true);
      echo = project.createTask("echo");
      myPrefix="@{prefix}";
      mySpecialPropertyKey=myPrefix+".src";
      //if your special property contains backslashes or other special js characters
      // you need to use project.getProperty instead of a string literal to get the value
      mySpecialPropertyVal=project.getProperty(mySpecialPropertyKey);
      // do something with this derived value in javascript
      echo.setMessage("my special property = "+mySpecialPropertyVal);
      echo.perform();
    </script>
  </sequential>
</macrodef>

Прежде чем я пришел к вышеупомянутому решению, я придумал хак-стиль решения для переопределения свойства ant с помощьюновое значениеХотя это может оказаться полезным для переопределения свойства, поскольку я делаю прямой вызов класса ant, существует риск, что это может не сработать в будущих версиях ant.Поскольку это похоже на взлом, мое намерение состоит в том, чтобы использовать подход 2 macrodef, перечисленный выше, а не этот подход, когда это возможно.Обратите внимание, что этот конкретный вариант не поддерживает символы обратной косой черты, потому что на атрибуты ссылаются непосредственно в строковом литерале JavaScript.Первоначально я использовал этот простой вариант для создания своего уникального префикса, что исключало необходимость применения подхода с 2 макроопределениями для обхода неизменности свойств.Однако вы можете адаптировать этот макроопределение для использования второго макроопределения и уникального префикса, чтобы получить «@ {значение}» в javascript с помощью команды project.getProperty.

<macrodef name="public.canova.setproperty">
  <attribute name="name"/>
  <attribute name="value"/>
  <sequential>
    <script language="javascript">
      project.setUserProperty("@{name}","@{value}");
    </script>
  <sequential>
</macrodef>

На первый взгляд, некоторые изэто может показаться немного сложным, но если вы правильно работаете с макросами и создаете макросы в стиле компонентов (т.е. не помещаете код спагетти в макрос), ваши скрипты ant должны стать короче, проще для понимания и проще в обслуживании, а такжеЖурналы будут легче следить.Совет - используйте javascript только тогда, когда это необходимо, и когда вы его используете, предпочтительно использовать его внутри макроса, чтобы он был инкапсулирован и скрыт от основной «логики» вашего скрипта ant, тем самым способствуя самодокументированию и читабельности.вашей основной "логики".Используйте комментарии, когда вещи не очевидны.

...