This is an automated email from the ASF dual-hosted git repository. hboutemy pushed a commit to annotated tag maven-filtering-1.0-alpha-1 in repository https://gitbox.apache.org/repos/asf/maven-filtering.git
commit 38161027604e0f886cb273e210424c2b2990122f Author: Oliver Lamy <[email protected]> AuthorDate: Thu Jan 24 00:28:33 2008 +0000 [MNG-3374] Create a common component for files filtering start some jobs for this issue git-svn-id: https://svn.apache.org/repos/asf/maven/sandbox/trunk/shared/maven-filtering@614750 13f79535-47bb-0310-9956-ffa450edef68 --- .classpath | 21 +++ .project | 13 ++ .settings/org.eclipse.jdt.core.prefs | 5 + pom.xml | 76 ++++++++ .../maven/shared/filtering/CompositeMap.java | 140 +++++++++++++++ .../shared/filtering/DefaultMavenFileFilter.java | 153 ++++++++++++++++ .../maven/shared/filtering/MavenFileFilter.java | 79 ++++++++ .../shared/filtering/MavenFilteringException.java | 63 +++++++ .../maven/shared/filtering/PropertyUtils.java | 199 +++++++++++++++++++++ .../shared/filtering/ReflectionProperties.java | 87 +++++++++ .../shared/filtering/TestReflectionProperties.java | 121 +++++++++++++ src/test/resources/pom.xml | 72 ++++++++ src/test/units-files/reflection-test.properties | 22 +++ 13 files changed, 1051 insertions(+) diff --git a/.classpath b/.classpath new file mode 100755 index 0000000..c10b3b7 --- /dev/null +++ b/.classpath @@ -0,0 +1,21 @@ +<classpath> + <classpathentry kind="src" path="src/main/java"/> + <classpathentry kind="src" path="src/test/java" output="target/test-classes"/> + <classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/> + <classpathentry kind="src" path="target/maven-shared-archive-resources" excluding="**/*.java"/> + <classpathentry kind="output" path="target/classes"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-project/2.0.6/maven-project-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-settings/2.0.6/maven-settings-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-model/2.0.6/maven-model-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/codehaus/plexus/plexus-utils/1.4.9/plexus-utils-1.4.9.jar"/> + <classpathentry kind="var" path="M2_REPO/org/codehaus/plexus/plexus-container-default/1.0-alpha-9-stable-1/plexus-container-default-1.0-alpha-9-stable-1.jar"/> + <classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar" sourcepath="M2_REPO/junit/junit/3.8.1/junit-3.8.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/classworlds/classworlds/1.1-alpha-2/classworlds-1.1-alpha-2.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-profile/2.0.6/maven-profile-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-artifact-manager/2.0.6/maven-artifact-manager-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-repository-metadata/2.0.6/maven-repository-metadata-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-artifact/2.0.6/maven-artifact-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-plugin-registry/2.0.6/maven-plugin-registry-2.0.6.jar"/> +</classpath> \ No newline at end of file diff --git a/.project b/.project new file mode 100755 index 0000000..26aa53c --- /dev/null +++ b/.project @@ -0,0 +1,13 @@ +<projectDescription> + <name>maven-filtering</name> + <comment>Maven shared components</comment> + <projects/> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> \ No newline at end of file diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 0000000..4f8e077 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Sun Jan 20 22:27:40 CET 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.4 +org.eclipse.jdt.core.compiler.compliance=1.4 diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..a5eff30 --- /dev/null +++ b/pom.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<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"> + + <parent> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-shared-components</artifactId> + <version>8</version> + </parent> + + <prerequisites> + <maven>2.0.6</maven> + </prerequisites> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-filtering</artifactId> + <packaging>jar</packaging> + <version>1.0-alpha-1-SNAPSHOT</version> + + <name>Maven Files Filtering</name> + + <scm> + <connection>scm:svn:https://svn.apache.org/repos/asf/maven/sandbox/trunk/shared/maven-interpolation</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/sandbox/trunk/shared/maven-interpolation</developerConnection> + <url>http://svn.apache.org/viewcvs.cgi/maven/sandbox/trunk/shared/maven-interpolation</url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>1.3.4</version> + <executions> + <execution> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0.6</version> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>1.4.9</version> + </dependency> + </dependencies> + +</project> diff --git a/src/main/java/org/apache/maven/shared/filtering/CompositeMap.java b/src/main/java/org/apache/maven/shared/filtering/CompositeMap.java new file mode 100755 index 0000000..c29a86c --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/CompositeMap.java @@ -0,0 +1,140 @@ +package org.apache.maven.shared.filtering; + +/* + * 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.IOException; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A Map composed with some others (optional adding SystemProperties and envvar) + * The get Method look in the Map list to return the corresponding value + * @author <a href="mailto:[email protected]">olamy</a> + * @since 15 janv. 08 + * @version $Id$ + */ +public class CompositeMap + extends AbstractMap +{ + + private List /*Map*/maps; + + private boolean systemPropertiesFirst; + + /** + * Ca + * @param maps + * @throws IOException if getting envvars failed + */ + public CompositeMap( List /* Map */maps ) + { + this( maps, false, false ); + } + + /** + * @param maps an orderer {@link List} of {@link Map} + * @param useSystemProperties using or not the System Properties + * @param systemPropertiesFirst if with get( key ) the systemProperties must wins (the internal ordered {@link List} + * will have in first the System Properties) + */ + public CompositeMap( List /*Map*/maps, boolean useSystemProperties, boolean systemPropertiesFirst ) + { + this.systemPropertiesFirst = systemPropertiesFirst; + if ( systemPropertiesFirst && !useSystemProperties ) + { + throw new IllegalArgumentException( "systemPropertiesFirst can't be true if useSystemProperties is false" ); + } + this.maps = new ArrayList(); + if ( useSystemProperties && !systemPropertiesFirst ) + { + if ( maps != null ) + { + this.maps.addAll( maps ); + } + this.maps.add( System.getProperties() ); + } + else if ( useSystemProperties && systemPropertiesFirst ) + { + this.maps.add( System.getProperties() ); + if ( maps != null ) + { + this.maps.addAll( maps ); + } + } + else + { + if ( maps != null ) + { + this.maps.addAll( maps ); + } + } + } + + public Object get( Object key ) + { + if ( this.maps != null ) + { + for ( Iterator iterator = this.maps.iterator(); iterator.hasNext(); ) + { + Map map = (Map) iterator.next(); + Object value = map.get( key ); + if ( value != null ) + { + return value; + } + } + } + return null; + } + + /** + * @see java.util.AbstractMap#entrySet() + */ + public Set entrySet() + { + throw new UnsupportedOperationException( "Cannot enumerate properties in a composite map" ); + } + + public List getMaps() + { + return maps; + } + + public void addMap( Map map ) + { + // see constructors internal Map can't be null + this.maps.add( map ); + } + + public boolean isSystemPropertiesFirst() + { + return systemPropertiesFirst; + } + + public void setSystemPropertiesFirst( boolean systemPropertiesFirst ) + { + this.systemPropertiesFirst = systemPropertiesFirst; + } + +} diff --git a/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java new file mode 100755 index 0000000..b6551dc --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java @@ -0,0 +1,153 @@ +/* + * 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. + */ +package org.apache.maven.shared.filtering; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.InterpolationFilterReader; + +/** + * @author <a href="mailto:[email protected]">olamy</a> + * @since 22 janv. 08 + * @version $Id$ + * + * @plexus.component role="org.apache.maven.shared.filtering.MavenFileFilter" role-hint="default" + */ +public class DefaultMavenFileFilter + implements MavenFileFilter +{ + + /** + * @see org.apache.maven.shared.filtering.MavenFileFilter#copyFile(java.io.File, java.io.File, boolean, org.apache.maven.project.MavenProject, java.util.List) + */ + public void copyFile( File from, File to, boolean filtering, MavenProject mavenProject, List filters, + boolean escapedBackslashesInFilePath, String encoding ) + throws MavenFilteringException + { + List filterWrappers = getDefaultFilterWrappers( mavenProject, filters, escapedBackslashesInFilePath ); + copyFile( from, to, filtering, filterWrappers, encoding ); + } + + /** + * @see org.apache.maven.shared.filtering.MavenFileFilter#copyFile(java.io.File, java.io.File, boolean, java.util.List) + */ + public void copyFile( File from, File to, boolean filtering, List filterWrappers, String encoding ) + throws MavenFilteringException + { + + try + { + if ( filtering ) + { + FileUtils.FilterWrapper[] wrappers = (FileUtils.FilterWrapper[]) filterWrappers + .toArray( new FileUtils.FilterWrapper[filterWrappers.size()] ); + FileUtils.copyFile( from, to, encoding, wrappers ); + } + else + { + FileUtils.copyFile( from, to, encoding, new FileUtils.FilterWrapper[0] ); + } + } + catch ( IOException e ) + { + throw new MavenFilteringException( e.getMessage(), e ); + } + + } + + /** + * @see org.apache.maven.shared.filtering.MavenFileFilter#getDefaultFilterWrappers(org.apache.maven.project.MavenProject, java.util.List) + */ + public List getDefaultFilterWrappers( final MavenProject mavenProject, List filters, final boolean escapedBackslashesInFilePath ) + throws MavenFilteringException + { + + final Properties filterProperties = new Properties(); + + // System properties + filterProperties.putAll( System.getProperties() ); + + // Project properties + filterProperties.putAll( mavenProject.getProperties() ); + + // Take a copy of filterProperties to ensure that evaluated filterTokens are not propagated + // to subsequent filter files. NB this replicates current behaviour and seems to make sense. + final Properties baseProps = new Properties(); + baseProps.putAll( filterProperties ); + + if ( filters != null ) + { + for ( Iterator i = filters.iterator(); i.hasNext(); ) + { + String filtersfile = (String) i.next(); + try + { + + Properties properties = PropertyUtils.loadPropertyFile( new File( filtersfile ), baseProps ); + filterProperties.putAll( properties ); + } + catch ( IOException e ) + { + throw new MavenFilteringException( "Error loading property file '" + filtersfile + "'", e ); + } + } + } + + List defaultFilterWrappers = new ArrayList(3); + + // support ${token} + FileUtils.FilterWrapper one = new FileUtils.FilterWrapper() { + public Reader getReader(Reader reader) { + return new InterpolationFilterReader(reader, filterProperties, "${", "}"); + } + }; + defaultFilterWrappers.add( one ); + + // support @token@ + FileUtils.FilterWrapper second = new FileUtils.FilterWrapper() { + public Reader getReader(Reader reader) { + return new InterpolationFilterReader(reader, filterProperties, "@", "@"); + } + }; + defaultFilterWrappers.add( second ); + // support ${token} with mavenProject reflection + FileUtils.FilterWrapper third = new FileUtils.FilterWrapper() + { + public Reader getReader( Reader reader ) + { + ReflectionProperties reflectionProperties = new ReflectionProperties( mavenProject, + escapedBackslashesInFilePath ); + return new InterpolationFilterReader( reader, reflectionProperties, "${", "}" ); + } + }; + defaultFilterWrappers.add( third ); + + + return defaultFilterWrappers; + } + +} diff --git a/src/main/java/org/apache/maven/shared/filtering/MavenFileFilter.java b/src/main/java/org/apache/maven/shared/filtering/MavenFileFilter.java new file mode 100755 index 0000000..e8f32ff --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/MavenFileFilter.java @@ -0,0 +1,79 @@ +/* + * 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. + */ +package org.apache.maven.shared.filtering; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.apache.maven.project.MavenProject; + +/** + * @author <a href="mailto:[email protected]">olamy</a> + * @since 22 janv. 08 + * @version $Id$ + */ +public interface MavenFileFilter +{ + + /** + * Will copy a file with some filtering using defaultFilterWrappers + * @see #getDefaultFilterWrappers(MavenProject, List) + * + * @param from file to copy/filter + * @param to destination file + * @param filtering enable or not filering + * @param mavenProject the mavenproject + * @param filters {@link List} of properties file + * @throws IOException + */ + public void copyFile( File from, final File to, boolean filtering, MavenProject mavenProject, + List/* File */filters, boolean escapedBackslashesInFilePath, String encoding ) + throws MavenFilteringException; + + /** + * @param from + * @param to + * @param filtering + * @param filterWrappers + * @throws MavenFilteringException + */ + public void copyFile( File from, final File to, boolean filtering, List /*FileUtils.FilterWrapper*/filterWrappers, String encoding ) + throws MavenFilteringException; + + /** + * + * Will return the default FileUtils.FilterWrappers + * + * <ul> + * <li>interpolation with token ${ } and values from System.getProperties, project.getProperties and from filters.</li> + * <li>interpolation with token @ @ and values from System.getProperties, project.getProperties and from filters.</li> + * <li>interpolation with token ${ } and values from mavenProject interpolation.</li> + * </ul> + * + * @param mavenProject + * @param filters {@link List} of properties file + * + * @return {@link List} of FileUtils.FilterWrapper + * + */ + public List/*FileUtils.FilterWrapper*/getDefaultFilterWrappers( MavenProject mavenProject, List/* File */filters, + boolean escapedBackslashesInFilePath ) + throws MavenFilteringException; +} diff --git a/src/main/java/org/apache/maven/shared/filtering/MavenFilteringException.java b/src/main/java/org/apache/maven/shared/filtering/MavenFilteringException.java new file mode 100755 index 0000000..25cb808 --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/MavenFilteringException.java @@ -0,0 +1,63 @@ +/* + * 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. + */ +package org.apache.maven.shared.filtering; + +/** + * @author <a href="mailto:[email protected]">olamy</a> + * @since 22 janv. 08 + * @version $Id$ + */ +public class MavenFilteringException + extends Exception +{ + + /** + * + */ + public MavenFilteringException() + { + // nothing + } + + /** + * @param message + */ + public MavenFilteringException( String message ) + { + super( message ); + } + + /** + * @param cause + */ + public MavenFilteringException( Throwable cause ) + { + super( cause ); + } + + /** + * @param message + * @param cause + */ + public MavenFilteringException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/src/main/java/org/apache/maven/shared/filtering/PropertyUtils.java b/src/main/java/org/apache/maven/shared/filtering/PropertyUtils.java new file mode 100755 index 0000000..424d689 --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/PropertyUtils.java @@ -0,0 +1,199 @@ +package org.apache.maven.shared.filtering; + +/* + * 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 org.codehaus.plexus.util.IOUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Iterator; +import java.util.Properties; + + +/** + * @author <a href="mailto:[email protected]">Kenney Westerhof</a> + * @author William Ferguson + * @version $Id$ + */ +public final class PropertyUtils +{ + private PropertyUtils() + { + // prevent instantiation + } + + /** + * Reads a property file, resolving all internal variables, using the supplied base properties. + * <p> + * The properties are resolved iteratively, so if the value of property A refers to property B, then after resolution + * the value of property B will contain the value of property B. + * </p> + * + * @param propFile The property file to load. + * @param baseProps Properties containing the initial values to subsitute into the properties file. + * @return Properties object containing the properties in the file with their values fully resolved. + * @throws IOException if profile does not exist, or cannot be read. + */ + public static Properties loadPropertyFile( File propFile, Properties baseProps ) + throws IOException + { + if ( !propFile.exists() ) + { + throw new FileNotFoundException( propFile.toString() ); + } + + final Properties fileProps = new Properties(); + final FileInputStream inStream = new FileInputStream( propFile ); + try + { + fileProps.load( inStream ); + } + finally + { + IOUtil.close( inStream ); + } + + final Properties combinedProps = new Properties(); + combinedProps.putAll( baseProps ); + combinedProps.putAll( fileProps ); + + // The algorithm iterates only over the fileProps which is all that is required to resolve + // the properties defined within the file. This is slighlty different to current, however + // I suspect that this was the actual original intent. + // + // The difference is that #loadPropertyFile(File, boolean, boolean) also resolves System properties + // whose values contain expressions. I believe this is unexpected and is not validated by the test cases, + // as can be verified by replacing the implementation of #loadPropertyFile(File, boolean, boolean) + // with the commented variant I have provided that reuses this method. + + for ( Iterator iter = fileProps.keySet().iterator(); iter.hasNext(); ) + { + final String k = (String) iter.next(); + final String propValue = getPropertyValue( k, combinedProps ); + fileProps.setProperty( k, propValue ); + } + + return fileProps; + } + + /** + * Reads a property file, resolving all internal variables. + * + * @param propfile The property file to load + * @param fail wheter to throw an exception when the file cannot be loaded or to return null + * @param useSystemProps wheter to incorporate System.getProperties settings into the returned Properties object. + * @return the loaded and fully resolved Properties object + */ + public static Properties loadPropertyFile( File propfile, boolean fail, boolean useSystemProps ) + throws IOException + { + + final Properties baseProps = new Properties(); + + if (useSystemProps) + { + baseProps.putAll(System.getProperties()); + } + + final Properties resolvedProps = new Properties(); + try + { + resolvedProps.putAll(loadPropertyFile(propfile, baseProps)); + } catch (FileNotFoundException e) + { + if (fail) + { + throw new FileNotFoundException(propfile.toString()); + } + } + + if (useSystemProps) + { + resolvedProps.putAll(baseProps); + } + + return resolvedProps; + } + + + /** + * Retrieves a property value, replacing values like ${token} + * using the Properties to look them up. + * + * It will leave unresolved properties alone, trying for System + * properties, 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}. + */ + private static String getPropertyValue( String k, Properties p ) + { + // This can also be done using InterpolationFilterReader, + // but it requires reparsing the file over and over until + // it doesn't change. + + 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 ); + + // if no matching } then bail + if ( ( idx2 = v.indexOf( '}' ) ) < 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 ); + } + + // 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( k ) ) + { + ret += "${" + nk + "}"; + } + else + { + v = nv + v; + } + } + return ret + v; + } +} diff --git a/src/main/java/org/apache/maven/shared/filtering/ReflectionProperties.java b/src/main/java/org/apache/maven/shared/filtering/ReflectionProperties.java new file mode 100755 index 0000000..a6d9ef9 --- /dev/null +++ b/src/main/java/org/apache/maven/shared/filtering/ReflectionProperties.java @@ -0,0 +1,87 @@ +package org.apache.maven.shared.filtering; + +/* + * 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.util.AbstractMap; +import java.util.Set; + +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.introspection.ReflectionValueExtractor; + + +/** + * @author Andreas Hoheneder (ahoh_at_inode.at) + * @version $Id$ + */ +public class ReflectionProperties + extends AbstractMap +{ + + private MavenProject project; + + boolean escapedBackslashesInFilePath; + + public ReflectionProperties( MavenProject mavenProject ) + { + this(mavenProject, false); + } + + public ReflectionProperties( MavenProject mavenProject, boolean escapedBackslashesInFilePath ) + { + super(); + + project = mavenProject; + + this.escapedBackslashesInFilePath = escapedBackslashesInFilePath; + } + + public Object get( Object key ) + { + Object value = null; + try + { + value = ReflectionValueExtractor.evaluate( "" + key , project ); + + if ( escapedBackslashesInFilePath && value != null && + "java.lang.String".equals( value.getClass().getName() ) ) + { + String val = (String) value; + + // Check if it's a windows path + if ( val.indexOf( ":\\" ) == 1 ) + { + value = StringUtils.replace( (String)value, "\\", "\\\\" ); + value = StringUtils.replace( (String)value, ":", "\\:" ); + } + } + } + catch ( Exception e ) + { + //TODO: remove the try-catch block when ReflectionValueExtractor.evaluate() throws no more exceptions + } + return value; + } + + public Set entrySet() + { + throw new UnsupportedOperationException( "Cannot enumerate properties in a project" ); + } +} diff --git a/src/test/java/org/apache/maven/shared/filtering/TestReflectionProperties.java b/src/test/java/org/apache/maven/shared/filtering/TestReflectionProperties.java new file mode 100755 index 0000000..e0a7077 --- /dev/null +++ b/src/test/java/org/apache/maven/shared/filtering/TestReflectionProperties.java @@ -0,0 +1,121 @@ +/* + * 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. + */ +package org.apache.maven.shared.filtering; + +import java.io.File; +import java.io.FileInputStream; +import java.util.Properties; + +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.PlexusTestCase; + +/** + * @author <a href="mailto:[email protected]">olamy</a> + * @since 22 janv. 08 + * @version $Id$ + */ +public class TestReflectionProperties + extends PlexusTestCase +{ + + public void testSimpleFiltering() + throws Exception + { + Properties allProperties = System.getProperties(); + FileInputStream readFileInputStream = null; + try + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setVersion( "1.0" ); + mavenProject.setGroupId( "org.apache" ); + System.setProperty( "foo", "bar" ); + MavenFileFilter mavenFileFilter = (MavenFileFilter) lookup( MavenFileFilter.class.getName(), "default" ); + + File from = new File( getBasedir() + "/src/test/units-files/reflection-test.properties" ); + File to = new File( getBasedir() + "/target/reflection-test.properties" ); + + if (to.exists()) + { + to.delete(); + } + + mavenFileFilter.copyFile( from, to, true, mavenProject, null, false, null ); + + Properties reading = new Properties(); + readFileInputStream = new FileInputStream( to ); + reading.load( readFileInputStream ); + assertEquals( "1.0", reading.get( "version" ) ); + assertEquals( "org.apache", reading.get( "groupId" ) ); + assertEquals( "bar", reading.get( "foo" ) ); + assertEquals( "none filtered", reading.get( "none" ) ); + } + finally + { + if ( readFileInputStream != null ) + { + readFileInputStream.close(); + } + System.setProperties( allProperties ); + } + + } + + public void testSimpleNonFiltering() + throws Exception + { + Properties allProperties = System.getProperties(); + FileInputStream readFileInputStream = null; + try + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setVersion( "1.0" ); + mavenProject.setGroupId( "org.apache" ); + System.setProperty( "foo", "bar" ); + MavenFileFilter mavenFileFilter = (MavenFileFilter) lookup( MavenFileFilter.class.getName(), "default" ); + + File from = new File( getBasedir() + "/src/test/units-files/reflection-test.properties" ); + File to = new File( getBasedir() + "/target/reflection-test.properties" ); + + if (to.exists()) + { + to.delete(); + } + + mavenFileFilter.copyFile( from, to, false, mavenProject, null, false, null ); + + Properties reading = new Properties(); + readFileInputStream = new FileInputStream( to ); + reading.load( readFileInputStream ); + assertEquals( "${pom.version}", reading.get( "version" ) ); + assertEquals( "${pom.groupId}", reading.get( "groupId" ) ); + assertEquals( "${foo}", reading.get( "foo" ) ); + assertEquals( "none filtered", reading.get( "none" ) ); + } + finally + { + if ( readFileInputStream != null ) + { + readFileInputStream.close(); + } + System.setProperties( allProperties ); + } + + } + +} diff --git a/src/test/resources/pom.xml b/src/test/resources/pom.xml new file mode 100755 index 0000000..12f0265 --- /dev/null +++ b/src/test/resources/pom.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<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"> + + <parent> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-shared-components</artifactId> + <version>8</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-filtering</artifactId> + <packaging>jar</packaging> + <version>1.0-alpha-1-SNAPSHOT</version> + + <name>Maven Files Filtering</name> + + <scm> + <connection>scm:svn:https://svn.apache.org/repos/asf/maven/sandbox/trunk/shared/maven-interpolation</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/sandbox/trunk/shared/maven-interpolation</developerConnection> + <url>http://svn.apache.org/viewcvs.cgi/maven/sandbox/trunk/shared/maven-interpolation</url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>1.3.4</version> + <executions> + <execution> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0.6</version> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>1.4.9</version> + </dependency> + </dependencies> + +</project> diff --git a/src/test/units-files/reflection-test.properties b/src/test/units-files/reflection-test.properties new file mode 100755 index 0000000..022a0a0 --- /dev/null +++ b/src/test/units-files/reflection-test.properties @@ -0,0 +1,22 @@ +#/* +# * 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. +# */ +version=${pom.version} +groupId=${pom.groupId} +foo=${foo} +none=none filtered \ No newline at end of file
