Domanda

Ho diversi progetti realizzati da Maven e voglio condividere alcune proprietà comuni tra loro - versione primavera, versione driver mysql, svn base url, ecc. - così posso aggiornarli una volta e si rifletterà su tutti i progetti .

Ho pensato di avere un singolo super pom con tutte le proprietà, ma se cambio uno dei problemi devo aumentare la sua versione (e aggiornare tutti i pom ereditati da esso) o eliminarlo da tutti gli sviluppatori "macchine che non voglio fare.

È possibile specificare questi parametri esternamente al pom? Voglio ancora avere la definizione della posizione esterna in un pom principale.

È stato utile?

Soluzione

Nota che l'idea originale che ho qui è qualcosa che sto facendo, ma che avrei potuto trovare un'idea molto migliore che ho anche elencato di seguito. Volevo mantenere entrambe le idee qui per completezza nel caso in cui l'idea più recente non funzioni.


Penso che tu possa risolvere questo problema usando il pom padre, ma devi avere un repository maven e uno strumento di compilazione CI.

Ho diversi progetti che ereditano tutti le proprietà di base da un POM padre. Usiamo Java 1.5, in modo che la proprietà build sia impostata lì. Tutto è UTF-8. Tutti i rapporti che desidero eseguire, la configurazione del sonar, ecc., Sono contenuti nel POM principale.

Supponendo che il tuo progetto sia in controllo di versione e hai uno strumento CI, quando effettui il check-in, il tuo strumento CI può compilare nel progetto POM e distribuire SNAPSHOT nei repository principali. Se i tuoi progetti puntano alla versione SNAPSHOT del POM principale, controlleranno il repository per verificare che abbiano l'ultima versione ... se non scaricano l'ultima versione. Quindi, se aggiorni il genitore, tutti gli altri progetti verranno aggiornati.

Il trucco, suppongo, sta rilasciando con un SNAPSHOT. Direi che le tue uscite arriveranno molto meno frequentemente delle tue modifiche. Quindi esegui una versione del tuo POM, quindi aggiorni i tuoi POM che ereditano da loro e li controllano nel controllo della versione. Fai sapere agli sviluppatori che devono fare un aggiornamento e andare da lì.

Potresti semplicemente attivare build lì forzando i nuovi POM nel repository e quindi fare in modo che tutti gli sviluppatori raccolgano automaticamente le modifiche al momento della compilazione.


Ho rimosso l'idea delle parole chiave ULTIME / STAMPA perché non funzionano per i POM principali. Funzionano solo per dipendenze o plugin. L'area del problema è in DefaultMavenProjectBuilder. Fondamentalmente ha difficoltà a determinare quale repository cercare il genitore per determinare quale sia la versione più recente o di rilascio. Non sono sicuro del perché questo sia diverso per dipendenze o plugin.


Sembra che questi sarebbero meno dolorosi che dover aggiornare i POM su ogni modifica al POM principale.

Altri suggerimenti

Quello che puoi fare è usare il Proprietà Maven plugin . Questo ti permetterà di definire le tue proprietà in un file esterno e il plugin leggerà questo file.

Con questa configurazione:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>properties-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
            <executions>
                <execution>
                    <phase>initialize</phase>
                    <goals>
                        <goal>read-project-properties</goal>
                    </goals>
                    <configuration>
                        <files>
                            <file>my-file.properties</file>
                        </files>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

e se hai, nel tuo file delle proprietà le seguenti righe:

spring-version=1.0
mysql-version=4.0.0

allora è la stessa cosa che se avessi scritto, nel tuo pom.xml, le seguenti righe:

<properties>
    <spring-version>1.0</spring-version>
    <mysql-version>4.0.0</mysql-version>
</properties>

Usando questo plugin, avrai diversi vantaggi:

  • Imposta facilmente un lungo elenco di proprietà
  • Modifica i valori di queste proprietà senza modificare il pom.xml padre.

Penso che il proprietà-maven-plugin sia l'approccio giusto a lungo termine, ma dato che hai risposto a quella risposta non permette alle proprietà di essere ereditate. Ci sono alcune strutture in Maven-Shared-Io che ti permettono di scoprire risorse sul percorso di classe del progetto. Di seguito ho incluso un codice che estende il plug-in delle proprietà per trovare i file delle proprietà nelle dipendenze del plug-in.

La configurazione dichiara un percorso a un file delle proprietà, poiché il progetto descrittore è dichiarato nella configurazione del plugin, è accessibile a ClasspathResourceLocatorStrategy. La configurazione può essere definita in un progetto principale e verrà ereditata da tutti i progetti figlio (in tal caso evitare di dichiarare i file in quanto non verranno scoperti, impostare solo la proprietà filePaths).

La configurazione seguente presuppone che ci sia un altro progetto jar chiamato name.seller.rich:test-properties-descriptor:0.0.1 che ha un file chiamato external.properties impacchettato nel jar (cioè è stato definito in src / main / risorse).

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-ext-maven-plugin</artifactId>
  <version>0.0.1</version>
  <executions>
    <execution>
      <id>read-properties</id>
      <phase>initialize</phase>
      <goals>
        <goal>read-project-properties</goal>
      </goals>
    </execution>
  </executions>                              
  <configuration>
    <filePaths>
      <filePath>external.properties</filePath>
    </filePaths>
  </configuration> 
  <dependencies>
    <!-- declare any jars that host the required properties files here -->
    <dependency>
      <groupId>name.seller.rich</groupId>
      <artifactId>test-properties-descriptor</artifactId>
      <version>0.0.1</version>
    </dependency>
  </dependencies>
</plugin>

Il pom per il progetto del plugin è simile al seguente:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-ext-maven-plugin</artifactId>
  <packaging>maven-plugin</packaging>
  <version>0.0.1</version>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>properties-maven-plugin</artifactId>
      <version>1.0-alpha-1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.shared</groupId>
      <artifactId>maven-shared-io</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
</project>

Il mojo è una copia del ReadPropertiesMojo del plug-in delle proprietà, con un ulteriore "filePaths" proprietà per consentire di definire il percorso relativo al file delle proprietà esterne nel percorso di classe, rende facoltativa la proprietà dei file e aggiunge i metodi readPropertyFiles () e getLocation () per individuare i file e unire qualsiasi filePath nell'array di file prima di continuare . Ho commentato le mie modifiche per renderle più chiare.

package org.codehaus.mojo.xml;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file 
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 * KIND, either express or implied.  See the License for the 
 * specific language governing permissions and limitations 
 * under the License.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.io.location.ClasspathResourceLocatorStrategy;
import org.apache.maven.shared.io.location.FileLocatorStrategy;
import org.apache.maven.shared.io.location.Location;
import org.apache.maven.shared.io.location.Locator;
import org.apache.maven.shared.io.location.LocatorStrategy;
import org.apache.maven.shared.io.location.URLLocatorStrategy;
import org.codehaus.plexus.util.cli.CommandLineUtils;

/**
 * The read-project-properties goal reads property files and stores the
 * properties as project properties. It serves as an alternate to specifying
 * properties in pom.xml.
 * 
 * @author <a href="mailto:zarars@gmail.com">Zarar Siddiqi</a>
 * @author <a href="mailto:Krystian.Nowak@gmail.com">Krystian Nowak</a>
 * @version $Id: ReadPropertiesMojo.java 8861 2009-01-21 15:35:38Z pgier $
 * @goal read-project-properties
 */
public class ReadPropertiesMojo extends AbstractMojo {
    /**
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * The properties files that will be used when reading properties.
     * RS: made optional to avoid issue for inherited plugins
     * @parameter
     */
    private File[] files;

    //Begin: RS addition
    /**
     * Optional paths to properties files to be used.
     * 
     * @parameter
     */
    private String[] filePaths;
    //End: RS addition

    /**
     * If the plugin should be quiet if any of the files was not found
     * 
     * @parameter default-value="false"
     */
    private boolean quiet;

    public void execute() throws MojoExecutionException {
        //Begin: RS addition
        readPropertyFiles();
        //End: RS addition

        Properties projectProperties = new Properties();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];

            if (file.exists()) {
                try {
                    getLog().debug("Loading property file: " + file);

                    FileInputStream stream = new FileInputStream(file);
                    projectProperties = project.getProperties();

                    try {
                        projectProperties.load(stream);
                    } finally {
                        if (stream != null) {
                            stream.close();
                        }
                    }
                } catch (IOException e) {
                    throw new MojoExecutionException(
                            "Error reading properties file "
                                    + file.getAbsolutePath(), e);
                }
            } else {
                if (quiet) {
                    getLog().warn(
                            "Ignoring missing properties file: "
                                    + file.getAbsolutePath());
                } else {
                    throw new MojoExecutionException(
                            "Properties file not found: "
                                    + file.getAbsolutePath());
                }
            }
        }

        boolean useEnvVariables = false;
        for (Enumeration n = projectProperties.propertyNames(); n
                .hasMoreElements();) {
            String k = (String) n.nextElement();
            String p = (String) projectProperties.get(k);
            if (p.indexOf("${env.") != -1) {
                useEnvVariables = true;
                break;
            }
        }
        Properties environment = null;
        if (useEnvVariables) {
            try {
                environment = CommandLineUtils.getSystemEnvVars();
            } catch (IOException e) {
                throw new MojoExecutionException(
                        "Error getting system envorinment variables: ", e);
            }
        }
        for (Enumeration n = projectProperties.propertyNames(); n
                .hasMoreElements();) {
            String k = (String) n.nextElement();
            projectProperties.setProperty(k, getPropertyValue(k,
                    projectProperties, environment));
        }
    }

    //Begin: RS addition
    /**
     * Obtain the file from the local project or the classpath
     * 
     * @throws MojoExecutionException
     */
    private void readPropertyFiles() throws MojoExecutionException {
        if (filePaths != null && filePaths.length > 0) {
            File[] allFiles;

            int offset = 0;
            if (files != null && files.length != 0) {
                allFiles = new File[files.length + filePaths.length];
                System.arraycopy(files, 0, allFiles, 0, files.length);
                offset = files.length;
            } else {
                allFiles = new File[filePaths.length];
            }

            for (int i = 0; i < filePaths.length; i++) {
                Location location = getLocation(filePaths[i], project);

                try {
                    allFiles[offset + i] = location.getFile();
                } catch (IOException e) {
                    throw new MojoExecutionException(
                            "unable to open properties file", e);
                }
            }

            // replace the original array with the merged results
            files = allFiles;
        } else if (files == null || files.length == 0) {
            throw new MojoExecutionException(
                    "no files or filePaths defined, one or both must be specified");
        }
    }
    //End: RS addition

    /**
     * Retrieves a property value, replacing values like ${token} using the
     * Properties to look them up. Shamelessly adapted from:
     * http://maven.apache.
     * org/plugins/maven-war-plugin/xref/org/apache/maven/plugin
     * /war/PropertyUtils.html
     * 
     * It will leave unresolved properties alone, trying for System properties,
     * and environment variables and implements reparsing (in the case that the
     * value of a property contains a key), and will not loop endlessly on a
     * pair like test = ${test}
     * 
     * @param k
     *            property key
     * @param p
     *            project properties
     * @param environment
     *            environment variables
     * @return resolved property value
     */
    private String getPropertyValue(String k, Properties p,
            Properties environment) {
        String v = p.getProperty(k);
        String ret = "";
        int idx, idx2;

        while ((idx = v.indexOf("${")) >= 0) {
            // append prefix to result
            ret += v.substring(0, idx);

            // strip prefix from original
            v = v.substring(idx + 2);

            idx2 = v.indexOf("}");

            // if no matching } then bail
            if (idx2 < 0) {
                break;
            }

            // strip out the key and resolve it
            // resolve the key/value for the ${statement}
            String nk = v.substring(0, idx2);
            v = v.substring(idx2 + 1);
            String nv = p.getProperty(nk);

            // try global environment
            if (nv == null) {
                nv = System.getProperty(nk);
            }

            // try environment variable
            if (nv == null && nk.startsWith("env.") && environment != null) {
                nv = environment.getProperty(nk.substring(4));
            }

            // if the key cannot be resolved,
            // leave it alone ( and don't parse again )
            // else prefix the original string with the
            // resolved property ( so it can be parsed further )
            // taking recursion into account.
            if (nv == null || nv.equals(nk)) {
                ret += "${" + nk + "}";
            } else {
                v = nv + v;
            }
        }
        return ret + v;
    }

    //Begin: RS addition
    /**
     * Use various strategies to discover the file.
     */
    public Location getLocation(String path, MavenProject project) {
        LocatorStrategy classpathStrategy = new ClasspathResourceLocatorStrategy();

        List strategies = new ArrayList();
        strategies.add(classpathStrategy);
        strategies.add(new FileLocatorStrategy());
        strategies.add(new URLLocatorStrategy());

        List refStrategies = new ArrayList();
        refStrategies.add(classpathStrategy);

        Locator locator = new Locator();

        locator.setStrategies(strategies);

        Location location = locator.resolve(path);
        return location;
    }
    //End: RS addition
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top