Pergunta

Eu tenho vários projetos construídos pelo perito, e eu quero compartilhar algumas propriedades comuns entre eles - Versão primavera, versão do driver mysql, o URL base de svn, etc - para que eu possa atualizá-los uma vez e ele será refletido em todos os projetos .

Eu pensei de ter um único super-pom com todas as propriedades, mas se eu mudar um dos necessidade problema que a qualquer incremento de sua versão (e para atualizar todos os poms herdar a partir dele) ou para excluí-lo de todos os desenvolvedores 'máquinas que eu não quero fazer.

É possível especificar esses parâmetros externamente ao pom? Eu ainda quero ter a definição local externo em um pom pai.

Foi útil?

Solução

Note-se que a ideia original que tenho aqui é algo que eu estou fazendo, mas que pode ter encontrado uma idéia muito melhor que eu também tenha listado abaixo. Eu queria manter ambas as idéias aqui para ser completo no caso do mais recente ideia faz não trabalho.


Eu acho que você pode resolver este problema utilizando o pom pai, mas você precisa ter um repositório maven e uma ferramenta de CI compilação.

Eu tenho vários projetos que todas as propriedades de base herdam de uma POM pai. Usamos Java 1.5, de modo que a propriedade de construção é a configuração lá. Tudo é UTF-8. Todos os relatórios que deseja executar, configuração Sonar, etc, está dentro do POM pai.

Assumindo que o seu projeto está em controle de versão e você tem uma ferramenta de CI, quando você check-in, a sua ferramenta de CI pode construir o projeto POM e implantar o instantâneo para os repos Maven. Se seus projetos apontar para a versão instantâneo do POM pai, eles vão verificar o repositório para validar que eles têm a versão mais recente ... se não fizerem o download da versão mais recente. Então, se você atualizar o pai, todos os outros projectos serão atualizados.

O truque, suponho está lançando com um instantâneo. Eu diria que seus lançamentos vão vir com muito menos frequência do que as suas alterações. Então você executar um lançamento de seu POM, em seguida, atualizar seus POMs que herdam-los e vê-los no controle de versão. Deixe os devs sabem que eles precisam fazer uma atualização e de lá ir.

Você poderia apenas gatilho constrói lá forçando os novos POMs para o repositório e, em seguida, ter todos os devs pegar as mudanças automagicamente em cima de construção.


Eu removi ideia a mais recente / RELEASE palavras-chave, porque eles não funcionam para POMs pais. Eles só funcionam para dependências ou plugins. A área de problema está no DefaultMavenProjectBuilder. Essencialmente ele tem problemas para determinar qual repositório de olhar para o pai para determinar o que o mais recente ou versão é. Não sei por que isso é diferente de dependências ou plugins embora.


Parece que estes seriam menos doloroso do que ter que atualizar os POMs sobre todas as alterações ao POM pai.

Outras dicas

O que você pode fazer é usar o Propriedades Maven plug-in . Isso permitirá que você definir suas propriedades em um arquivo externo, e o plugin irá ler este arquivo.

Com esta configuração:

<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 tiver, no seu arquivo de propriedades as seguintes linhas:

spring-version=1.0
mysql-version=4.0.0

então é a mesma coisa que se você escreveu, em seu pom.xml, as seguintes linhas:

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

Usando este plugin, você terá vários benefícios:

  • Definir facilmente uma longa lista de propriedades
  • Modificar os valores destas propriedades, sem modificar o POM-mãe.

Eu acho que a propriedades de maven-plugin é o direito abordagem de longo prazo, mas como você respondeu a essa resposta não permite que as propriedades a ser herdada. Existem algumas instalações em maven-shared-io que lhe permitem descobrir recursos no classpath do projeto. Eu incluí alguns código abaixo que se estende as propriedades do plugin para encontrar arquivos de propriedades nas dependências do plugin.

A configuração declara um caminho para um arquivo de propriedades, porque o projeto descritor é declarado na configuração do plugin, é acessível ao ClasspathResourceLocatorStrategy. A configuração pode ser definida em um projeto pai, e será herdada por todos os projetos filho (se você fizer isso evitar declarar todos os arquivos como eles não vão ser descobertas, apenas definir a propriedade filepaths).

A configuração abaixo assume que há um outro projecto frasco chamado name.seller.rich:test-properties-descriptor:0.0.1 que tem um ficheiro chamado external.properties embalados dentro do frasco (ou seja, ele foi definido em src / main / recursos).

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

O pom para os olhares do projeto plug-in como este:

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

O mojo é uma cópia das propriedades ReadPropertiesMojo do plug-in, com um "filepaths" adicionais propriedade para que você possa definir o caminho relativo para o arquivo de propriedades externo no classpath, faz o opcional arquivos de propriedade, e adiciona os readPropertyFiles ( métodos) e getLocation () para localizar os arquivos e mesclar quaisquer filepaths na matriz de arquivos antes de continuar. Eu comentou as minhas alterações para torná-los mais claros.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top