2009-08-05 1 views
5

Ho un file delle proprietà, diciamo my-file.properties. In aggiunta a ciò, ho diversi file di configurazione per la mia applicazione in cui alcune informazioni devono essere compilate per quanto riguarda il contenuto del file my-file.properties.Simulazione del meccanismo di filtro Maven2 usando Ant

my-file.properties:

application.version=1.0 
application.build=42 
user.name=foo 
user.password=bar 

Così, nei miei file di configurazione, troverò qualche ${application.version}, ${user.name} che verrà sostituito dal valore assunto nel file delle proprietà ...

Quando costruisco la mia applicazione utilizzando Maven2, ho solo bisogno di specificare il file delle proprietà e di dire che i miei file di risorse sono filtrati (come in this answer a un altro problema). Tuttavia, ho bisogno di ottenere la stessa cosa usando solo Ant.

Ho visto che Ant offre uno filter task. Tuttavia, mi costringe a utilizzare il modello @[email protected] (ad esempio @[email protected] anziché #{user.name}) nei miei file di configurazione, che nel mio caso non è accettabile.

Come posso risolvere il mio problema?

risposta

20

Penso che expandproperties sia quello che stai cercando. Questo agisce proprio come Maven2's resource filters.


INPUT

Per esempio, se si dispone di src directory (uno dei molti file):

<link href="${css.files.remote}/css1.css"/> 

src/test.txt


PROCESSO

E nel mio file di compilazione ANT abbiamo questa:

<project default="default"> 
    <!-- The remote location of any CSS files --> 
    <property name="css.files.remote" value="/css/theCSSFiles" />  
    ... 
    <target name="ExpandPropertiesTest"> 

     <mkdir dir="./filtered"/> 

     <copy todir="./filtered"> 
     <filterchain> 
      <expandproperties/> 
     </filterchain>  

     <fileset dir="./src" /> 
     </copy> 
    </target> 
</project> 

build.xml


USCITA

* Quando si esegue il bersaglio ExpandPropertiesTest si vuole hai il seguente nel tuo filtrato directory: *

<link href="/css/theCSSFiles/css1.css"/> 

filtrato/test.txt

+0

Grazie! Era davvero quello che stavo cercando ... – romaintaz

+0

@romaintaz cosa sicura! Spero che semplifica un po 'il file di costruzione. So che ha fatto il mio. – leeand00

2

Ant conosce un concetto denominato Filterchains, che è utile qui. Usa il filtro ReplaceTokens e specifica beginoken e endtoken come vuoti (normalmente è '@'). Questo dovrebbe fare il trucco.

+1

Questa soluzione non sembra funzionare, almeno con i miei tentativi. begintoken e endtoken non possono essere vuoti. Non posso né impostare begintoken a "$ {" poiché è considerato un errore di sintassi ... – romaintaz

1

Un modo hooooooorible fare questo lavoro, ispirato dalla soluzione di Mnementh, è con il seguente codice:

<!-- Read the property file --> 
    <property file="my-file.properties"/> 
    <copy todir="${dist-files}" overwrite="true"> 
     <fileset dir="${src-files}"> 
      <include name="*.properties"/> 
     </fileset> 
     <filterchain> 
      <filterreader classname="org.apache.tools.ant.filters.ReplaceTokens"> 
       <!-- Define the begin and end tokens --> 
       <param type="tokenchar" name="begintoken" value="$"/> 
       <param type="tokenchar" name="endtoken" value="}"/> 
       <!-- Define one token per entry in the my-file.properties. Arggh --> 
       <param type="token" name="{application.version" value="${application.version}"/> 
       <param type="token" name="{user.name" value="${user.name}"/> 
       ... 
      </filterreader> 
     </filterchain> 
    </copy> 

Spiegazioni:

Sto usando il replaceTokens lettore a cercare per tutti $...} modello . Non riesco a cercare i modelli ${...}, poiché begminato è un char e non una stringa. Quindi, ho impostato l'elenco di token che iniziano con un {(ad esempio, vedo {user.name anziché user.name). Spero di avere "solo" circa 20 linee in my-file.properties, quindi ho bisogno di definire "solo" 20 token nel mio file Ant ...

Esiste una soluzione semplice e stupida per risolvere questo semplice e problema stupido ??

3

È possibile definire un custom FilterReader. In modo da avere un paio di scelte:

  1. estensione/copiare la classe org.apache.tools.ant.filters.ReplaceTokens e definire una Carta che fa riferimento a un altro file delle proprietà che contiene tutte le sostituzioni. Questo è ancora un po 'complicato in quanto devi definire tutte le sostituzioni.
  2. Estendere/copiare la classe org.apache.tools.ant.filters.ReplaceTokens con un'ulteriore elaborazione che sostituisce semplicemente il token con una versione con il contorno corretto. Ovviamente dovresti stare molto attento a dove usi questo tipo in quanto corrisponderà a qualsiasi cosa con il token di inizio e fine.

Così nel metodo read() di replaceTokens, sostituire:

final String replaceWith = (String) hash.get(key.toString()); 

con una chiamata a un metodo getReplacement():

... 
final String replaceWith = getReplacement(key.toString); 
... 

private String getReplacement(String key) { 
    //first check if we have a replacement defined 
    if(has.containsKey(key)) { 
     return (String)hash.get(key); 
    } 

    //now use our built in rule, use a StringBuilder if you want to be tidy 
    return "$" + key + "}"; 
} 

Per utilizzare questo, che ci si assicura la tua classe è confezionata e on Ant's path e modifica il tuo filtro:

<filterreader classname="my.custom.filters.ReplaceTokens"> 
    <!-- Define the begin and end tokens --> 
    <param type="tokenchar" name="begintoken" value="$"/> 
    <param type="tokenchar" name="endtoken" value="}"/> 
    <!--Can still define explicit tokens, any not 
    defined explicitly will be replaced by the generic rule --> 
</filterreader>