Pregunta

Tengo varios proyectos creados por maven, y quiero compartir algunas propiedades comunes entre ellos: versión de primavera, versión del controlador mysql, svn base url, etc., para poder actualizarlos una vez y se reflejará en todos los proyectos .

Pensé en tener un solo super pom con todas las propiedades, pero si cambio uno de los problemas, necesito incrementar su versión (y actualizar todos los poms heredados de él) o eliminarlo de todos los desarrolladores 'máquinas que no quiero hacer.

¿Puede especificar estos parámetros externamente al pom? Todavía quiero tener la definición de ubicación externa en un pom padre.

¿Fue útil?

Solución

Tenga en cuenta que la idea original que tengo aquí es algo que estoy haciendo, pero que podría haber encontrado una idea mucho mejor que también he enumerado a continuación. Quería mantener ambas ideas aquí para completarlas en caso de que la idea más nueva no funcione.


Creo que puede resolver este problema utilizando el pom padre, pero necesita tener un repositorio maven y una herramienta de compilación de CI.

Tengo varios proyectos que heredan todas las propiedades base de un POM padre. Usamos Java 1.5, por lo que la propiedad de construcción se configura allí. Todo es UTF-8. Todos los informes que deseo ejecutar, configuración de sonda, etc., se encuentran dentro del POM principal.

Suponiendo que su proyecto está en control de versiones y que tiene una herramienta de CI, cuando se registra, su herramienta de CI puede compilarse para el proyecto POM e implementar la INSTANTÁNEA en los repositorios de Maven. Si sus proyectos apuntan a la versión SNAPSHOT del POM principal, verificarán el repositorio para validar que tienen la última versión ... si no, descargan la última versión. Entonces, si actualiza el padre, todos los demás proyectos se actualizarán.

El truco, supongo, es lanzarlo con una INSTANTÁNEA. Diría que sus lanzamientos serán mucho menos frecuentes que sus cambios. Entonces, realiza una versión de su POM, luego actualiza sus POM que heredan de ellos y los registra en el control de versiones. Deje que los desarrolladores sepan que necesitan hacer una actualización e ir desde allí.

Podrías activar las compilaciones allí forzando a los nuevos POM al repositorio y luego hacer que todos los desarrolladores recojan los cambios automáticamente después de la compilación.


He eliminado la idea de palabras clave ÚLTIMO / LIBERACIÓN porque no funcionan para los POM principales. Solo funcionan para dependencias o complementos. El área del problema está en DefaultMavenProjectBuilder. Esencialmente tiene problemas para determinar qué repositorio buscar al padre para determinar cuál es la última versión o versión. Sin embargo, no estoy seguro de por qué esto es diferente para las dependencias o complementos.


Parece que estos serían menos dolorosos que tener que actualizar los POM en cada cambio al POM principal.

Otros consejos

Lo que puede hacer es usar el Complemento Properties Maven . Esto le permitirá definir sus propiedades en un archivo externo, y el complemento leerá este archivo.

Con esta configuración:

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

y si tiene, en su archivo de propiedades las siguientes líneas:

spring-version=1.0
mysql-version=4.0.0

entonces es lo mismo que si escribieras, en tu pom.xml, las siguientes líneas:

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

Usando este complemento, tendrá varios beneficios:

  • Establezca fácilmente una larga lista de propiedades
  • Modifique los valores de estas propiedades sin modificar el pom.xml padre.

Creo que el plugin properties-maven es el enfoque correcto a largo plazo, pero como respondiste a esa respuesta, no permite que se hereden las propiedades. Hay algunas instalaciones en maven-shared-io que le permiten descubrir recursos en el classpath del proyecto. He incluido un código a continuación que extiende el complemento de propiedades para encontrar archivos de propiedades en las dependencias del complemento.

La configuración declara una ruta a un archivo de propiedades, ya que el proyecto descriptor se declara en la configuración del complemento, es accesible para ClasspathResourceLocatorStrategy. La configuración se puede definir en un proyecto principal y será heredada por todos los proyectos secundarios (si hace esto, evite declarar cualquier archivo ya que no se descubrirán, solo configure la propiedad filePaths).

La siguiente configuración supone que hay otro proyecto jar llamado name.seller.rich:test-properties-descriptor:0.0.1 que tiene un archivo llamado external.properties empaquetado en el jar (es decir, se definió en src / main / resources).

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

El pom para el proyecto de complemento se ve así:

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

El mojo es una copia de ReadPropertiesMojo del complemento de propiedades, con un adicional '' filePaths '' propiedad para permitirle definir la ruta relativa al archivo de propiedades externo en el classpath, hace que la propiedad de los archivos sea opcional y agrega los métodos readPropertyFiles () y getLocation () para ubicar los archivos y fusionar cualquier FilePaths en la matriz de archivos antes de continuar . He comentado mis cambios para aclararlos.

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
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top