You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2020/02/13 22:11:11 UTC

[maven-filtering] 01/44: [MNG-3374] Create a common component for files filtering start some jobs for this issue

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 <ol...@apache.org>
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:olamy@apache.org">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:olamy@apache.org">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:olamy@apache.org">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:olamy@apache.org">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:kenney@neonics.com">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:olamy@apache.org">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