Как я могу предоставить пользовательскую логику в архетипе Maven?

Я заинтересован в создании архетипа Maven, и я думаю, что у меня большая часть основ. Однако одна вещь, за которую я застрял, - это то, что иногда я хочу использовать пользовательскую логику для заполнения шаблона. Например, если кто-то генерирует мой архетип и указывает artifactId как hello-world, я бы хотел сгенерировать класс HelloWorld, который просто выводит "Hello World!". на консоль. Если другой человек генерирует его с помощью artifactId = howdy-there, класс genned будет HowdyThere, и он распечатает "Howdy There!".

Я знаю, что под обложками механизм архетипа Maven использует механизм шаблонов Velocity, поэтому я прочитал эту статью о создании пользовательских директив. Кажется, это то, что я искал, поэтому я создал класс под названием HyphenatedToCamelCaseDirective, который расширяет org.apache.velocity.runtime.directive.Directive. В этом классе моя реализация getName() возвращает "hyphenatedCamelCase". В моем файле archetype-metadata.xml у меня есть следующее...

<requiredProperties>
    <requiredProperty key="userdirective">
        <defaultValue>com.jlarge.HyphenatedToCamelCaseDirective</defaultValue>
    </requiredProperty>
</requiredProperties>

Мой класс шаблонов выглядит следующим образом:

package ${package};

public class #hyphenatedToCamelCase('$artifactId') {

    // userdirective = $userdirective
    public static void main(String[] args) {
        System.out.println("#hyphenatedToCamelCase('$artifactId')"));
    }
} 

После того, как я установил свой архетип, а затем сделаю архетип: сгенерируем, указав artifactId = howdy-there и groupId = f1.f2, получившийся класс выглядит следующим образом:

package f1.f2;

public class #hyphenatedToCamelCase('howdy-there') {

    // userdirective = com.jlarge.HyphenatedToCamelCaseDirective    
    public static void main(String[] args) {
        System.out.println("#hyphenatedToCamelCase('howdy-there')"));
    }
}

Результат показывает, что даже несмотря на то, что userdirective устанавливается так, как я ожидал, он не оправдывает директивы #hyphenatedToCamelCase, как я надеялся. В классе директивы у меня есть метод рендеринга сообщения в System.out, но это сообщение не отображается в консоли, поэтому я полагаю, что метод никогда не выполнялся во время архетипа: сгенерируйте.

Я пропустил что-то простое здесь, или этот подход просто не подходит?

Ответ 1

Раздел необходимых свойств архетипа-метаданных xml используется для передачи дополнительных свойств в контекст скорости, не, предназначенный для передачи конфигурации двигателя скорости. Поэтому настройка свойства под названием userDirective приведет к тому, что переменная $userDirective будет доступна, а не добавит настраиваемую директиву к движку скорости.

Если вы видите исходный код, движок скорости, используемый плагином maven-archetype, не зависит от источника внешнего источника для его конфигурации. Код, который генерирует проект, опирается на реализацию проекта (VelocityComponent.

Это код, в котором инициализирован движок скорости:

public void initialize()
    throws InitializationException
{
    engine = new VelocityEngine();

    // avoid "unable to find resource 'VM_global_library.vm' in any resource loader."
    engine.setProperty( "velocimacro.library", "" );

    engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this );

    if ( properties != null )
    {
        for ( Enumeration e = properties.propertyNames(); e.hasMoreElements(); )
        {
            String key = e.nextElement().toString();

            String value = properties.getProperty( key );

            engine.setProperty( key, value );

            getLogger().debug( "Setting property: " + key + " => '" + value + "'." );
        }
    }

    try
    {
        engine.init();
    }
    catch ( Exception e )
    {
        throw new InitializationException( "Cannot start the velocity engine: ", e );
    }
}

Существует хакерский способ добавления вашей настраиваемой директивы. Свойства, которые вы видите выше, считываются из файла components.xml в plexus-velocity-1.1.8.jar. Откройте этот файл и добавьте свойство конфигурации

<component-set>
  <components>
    <component>
      <role>org.codehaus.plexus.velocity.VelocityComponent</role>
      <role-hint>default</role-hint>
      <implementation>org.codehaus.plexus.velocity.DefaultVelocityComponent</implementation>
      <configuration>
        <properties>
          <property>
            <name>resource.loader</name>
            <value>classpath,site</value>
          </property>
          ...
          <property>
            <name>userdirective</name>
            <value>com.jlarge.HyphenatedToCamelCaseDirective</value>
          </property>
        </properties>
      </configuration>
    </component>
  </components>
</component-set>

Затем добавьте свой настраиваемый файл класса директивы в эту банку и запустите файл archetype: generate.

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