2013-05-22 11 views
12

Sono interessato a creare un archetipo di Maven e penso di avere la maggior parte delle nozioni di base. Tuttavia, una cosa su cui sono bloccato è che a volte voglio usare la logica personalizzata per riempire un modello. Ad esempio, se qualcuno genera il mio archetipo e specifica l'artefatto come hello-world, mi piacerebbe generare una classe denominata HelloWorld che stampi semplicemente "Hello World!" alla console. Se un'altra persona la genera con artefatto, vuol dire che là, la classe scelta sarebbe HowdyThere e stamperebbe "Howdy There!".Come posso fornire una logica personalizzata in un archetipo Maven?

So che sotto le copertine, il meccanismo dell'archetipo di Maven sfrutta il Velocity Template Engine, quindi ho letto questo articolo su creating custom directives. Questo sembrava essere quello che stavo cercando, così ho creato una classe chiamata HyphenatedToCamelCaseDirective che estende org.apache.velocity.runtime.directive.Directive. In questa classe, la mia implementazione getName() restituisce "hyphenatedCamelCase". Nel mio file archetipo-metadata.xml, ho il seguente ...

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

mia classe template si presenta così ...

package ${package}; 

public class #hyphenatedToCamelCase('$artifactId') { 

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

Dopo aver installato il mio archetipo e poi fare un archetipo: generare specificando artifactId = Salve-là e groupId = f1.f2, la classe risultante si presenta così ...

package f1.f2; 

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

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

il risultato mostra che, anche se si sta userdirective impostato il modo in cui mi aspettavo che, non èevagliando le direttive #hyphenatedToCamelCase come speravo. Nella classe direttiva, ho il metodo render che registra un messaggio su System.out, ma quel messaggio non appare nella console, così da indurmi a credere che il metodo non sia mai stato eseguito durante l'archetipo: generate.

Mi manca qualcosa di semplice qui, o questo approccio non è la strada da percorrere?

risposta

2

La sezione delle proprietà richieste dell'archetype-metatadata xml viene utilizzata per passare proprietà aggiuntive al contesto di velocità, è non significato per il passaggio della configurazione del motore di velocità. Pertanto, l'impostazione di una proprietà denominata userDirective renderà disponibile la variabile $ userDirective e non aggiungerà una direttiva personalizzata al motore di velocità.

Se viene visualizzato il codice sorgente, il motore di velocità utilizzato dal plugin maven-archetype non dipende da alcuna origine di proprietà esterna per la sua configurazione. Il codice che generates the project si basa su un'implementazione autorizzata (dal contenitore del plesso) di VelocityComponent.

Questo è il codice in cui viene inizializzato il motore di velocità:

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); 
    } 
} 

C'è un modo hacky di aggiungere la vostra direttiva personalizzato. Le proprietà che vedi sopra sono lette dal file components.xml in plexus-velocity-1.1.8.jar. Quindi apri questo file e aggiungi la tua proprietà di configurazione

<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> 

Quindi aggiungi il tuo file di classe direttiva personalizzato a questo jar ed esegui archetype: generate.

Come vedi questo è molto fraglie e dovrai trovare un modo per distribuire questo barattolo di velocità del plesso hackerato. A seconda di cosa si prevede di utilizzare questo archetipo potrebbe valerne la pena.