FELIX-1627: add support for variable expansion in sigil defaults.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@817664 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/bldcommon/build.properties b/sigil/bldcommon/build.properties
index 07df5b2..ef17fae 100644
--- a/sigil/bldcommon/build.properties
+++ b/sigil/bldcommon/build.properties
@@ -9,7 +9,7 @@
 
 build.dir	= ${basedir}/build
 build_xml	= build.xml
-classes.dir	= ${build.dir}/classes
+classes.dir	= ${build.dir}/main-classes
 deps.dir	= ${build.dir}/deps
 composite.dir	= ${basedir}/xml
 src.dir		= ${basedir}/src
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldConfig.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldConfig.java
index 058a97d..902bab9 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldConfig.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldConfig.java
@@ -19,7 +19,6 @@
 
 package org.apache.felix.sigil.config;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -94,9 +93,9 @@
     {
     }
 
-    public BldConfig(Properties p, File basedir) throws IOException
+    public BldConfig(Properties p) throws IOException
     {
-        merge(p, basedir);
+        merge(p);
     }
 
     public void setDefault(BldConfig dflt)
@@ -392,7 +391,7 @@
      * @param p
      * @throws IOException 
      */
-    public void merge(Properties p, File basedir) throws IOException
+    public void merge(Properties p) throws IOException
     {
         if (p.isEmpty())
             return;
@@ -437,12 +436,6 @@
             String[] keys = key.split(SUBKEY_SEP, 2);
             String value = p.getProperty(key);
 
-            // expand ${.} and ${..} relative to file
-            if (value.contains("${.}"))
-                value = value.replace("${.}", basedir.getPath());
-            else if (value.contains("${..}"))
-                value = value.replace("${..}", basedir.getParent());
-
             if (keys.length > 1)
             {
                 Properties p2 = sub.get(keys[0]);
@@ -522,7 +515,7 @@
             {
                 if (bundleKeys.contains(subKey))
                 {
-                    BldConfig config2 = new BldConfig(props, basedir);
+                    BldConfig config2 = new BldConfig(props);
                     Properties unkProps = config2.getUnknown();
 
                     if (config2.map.containsKey(M_IMPORTS))
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
index 0480f7e..ed4d370 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldProject.java
@@ -67,7 +67,7 @@
     private BldConfig config;
     private BldConverter convert;
     private BundleModelElement requirements;
-    private File baseDir;
+    private final File baseDir;
     private URI loc;
     private Properties packageDefaults;
     private TreeSet<String> packageWildDefaults;
@@ -87,7 +87,7 @@
     {
         // allow System property overrides, e.g.
         // ANT_OPTS='-Dsigil.option\;addMissingImports=false' ant
-        config.merge(getOverrides(), null);
+        config.merge(getOverrides());
 
         InputStream in = null;
         try
@@ -100,7 +100,7 @@
 
             Properties p = new Properties();
             p.load(bis);
-            config.merge(p, baseDir);
+            config.merge(p);
 
             Properties unknown = config.getUnknown();
             if (!unknown.isEmpty())
@@ -158,15 +158,7 @@
 
         if (defaults != null)
         {
-            defaults = BldUtil.expand(defaults, new Properties()
-            {
-                private static final long serialVersionUID = 1L;
-
-                public String getProperty(String name)
-                {
-                    return System.getenv(name);
-                }
-            });
+            defaults = BldUtil.expand(defaults, new BldProperties(base));
         }
         else
         {
@@ -184,6 +176,7 @@
             {
                 File file = new File(base, defaults).getCanonicalFile();
                 URL url = file.toURL();
+                BldProperties bp = new BldProperties(file.getParentFile());
 
                 if (dflt == null)
                 {
@@ -197,9 +190,19 @@
                 }
 
                 Properties p = new Properties();
-                // FIXME stream not closed
-                p.load(url.openStream());
-                dflt.merge(p, file.getParentFile());
+                InputStream stream = url.openStream();
+                p.load(stream);
+                stream.close();
+
+                // expand variables in defaults
+                for (Object k : p.keySet())
+                {
+                    String key = (String) k;
+                    String value = p.getProperty(key);
+                    p.setProperty(key, BldUtil.expand(value, bp));
+                }
+
+                dflt.merge(p);
 
                 ignore = false;
                 loadDefaults(p, file.getParentFile(), dflt);
@@ -618,6 +621,7 @@
     public Map<String, Properties> getRepositoryConfig()
     {
         HashMap<String, Properties> map = new HashMap<String, Properties>();
+        BldProperties bp = new BldProperties(baseDir);
 
         for (String name : config.getList(null, BldConfig.C_REPOSITORIES))
         {
@@ -627,14 +631,7 @@
             {
                 String key = (String) k;
                 String value = repo.getProperty(key);
-
-                String expand = BldUtil.expand(value, new BldProperties(this));
-
-                if (!value.equals(expand))
-                {
-                    value = expand;
-                    repo.setProperty(key, value);
-                }
+                repo.setProperty(key, BldUtil.expand(value, bp));
             }
 
             map.put(name, repo);
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldProperties.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldProperties.java
index 49149cd..6b9e376 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldProperties.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldProperties.java
@@ -19,86 +19,55 @@
 
 package org.apache.felix.sigil.config;
 
-
+import java.io.File;
 import java.io.IOException;
-import java.util.Map;
 import java.util.Properties;
 
-
 public class BldProperties extends Properties
 {
     private static final long serialVersionUID = 1L;
-    private static final Map<String, String> env = System.getenv();
-    private static final Properties sys = System.getProperties();
+    private static final BldProperties global = new BldProperties(null);
+    private static final Properties sysEnv;
 
-    private final BldProject project;
-    private String dot;
-    private String dotdot;
-
-    private static final BldProperties global = new BldProperties();
-
-
-    private BldProperties()
+    static
     {
-        this.project = null;
+        Properties env = new Properties();
+        env.putAll(System.getenv());
+        sysEnv = new Properties(env);
+        sysEnv.putAll(System.getProperties());
+        // Note: these are System properties, NOT Ant properties.
     }
 
-
-    BldProperties( BldProject project ) throws NullPointerException
+    private final Properties mySysEnv;
+    
+    BldProperties(File baseDir)
     {
-        if ( project == null )
+        mySysEnv = new Properties(sysEnv);
+        
+        try
         {
-            throw new NullPointerException();
-        }
-        this.project = project;
-    }
-
-
-    public String getProperty( String key, String defaultValue )
-    {
-        if ( project != null )
-        {
-            try
+            if (baseDir != null)
             {
-                if ( ".".equals( key ) )
-                {
-                    if ( dot == null )
-                    {
-                        dot = project.resolve( "." ).getCanonicalPath();
-                    }
-                    return dot;
-                }
-                else if ( "..".equals( key ) )
-                {
-                    if ( dotdot == null )
-                    {
-                        dotdot = project.resolve( ".." ).getCanonicalPath();
-                    }
-                    return dotdot;
-                }
-            }
-            catch ( IOException e )
-            {
-                throw new IllegalStateException( e );
+                mySysEnv.setProperty(".", baseDir.getCanonicalPath());
+                mySysEnv.setProperty("..", baseDir.getParentFile().getCanonicalPath());
             }
         }
-
-        String val = sys.getProperty( key, env.get( key ) );
-
-        if ( val == null )
+        catch (IOException e)
         {
-            val = defaultValue;
+            // TODO Auto-generated catch block
+            e.printStackTrace();
         }
-
-        return val;
     }
 
-
-    public String getProperty( String key )
+    public String getProperty(String key, String defaultValue)
     {
-        return getProperty( key, null );
+        return mySysEnv.getProperty(key, defaultValue);
     }
 
+    public String getProperty(String key)
+    {
+        return mySysEnv.getProperty(key);
+    }
 
     public static Properties global()
     {
diff --git a/sigil/common/core/src/org/apache/felix/sigil/config/BldUtil.java b/sigil/common/core/src/org/apache/felix/sigil/config/BldUtil.java
index bfedb8a..7473c7d 100644
--- a/sigil/common/core/src/org/apache/felix/sigil/config/BldUtil.java
+++ b/sigil/common/core/src/org/apache/felix/sigil/config/BldUtil.java
@@ -19,13 +19,10 @@
 
 package org.apache.felix.sigil.config;
 
-
-import java.util.Map;
 import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-
 // taken from Newton Launcher
 
 public class BldUtil
@@ -57,85 +54,87 @@
      *      with word as the message.
      * </pre>
      */
-    public static String expand( String s, Properties p )
+    public static String expand(String s, Properties p)
     {
         // regex to match property references e.g. ${name}
         // TODO this is very simplistic, so strings to be expanded should not
         // contain $ or }, except where substitution is expected.
         // Update: propRef regex now allows substitutions to contain $,
         // e.g. where a Windows ${user.name} is $Admin or similar.
-        final Pattern propRef = Pattern.compile( "\\$\\{(((\\$[^\\{\\}])|[^\\$\\}])+\\$?)\\}" );
-        final Pattern backslash = Pattern.compile( "\\\\" );
-        final Pattern dollar = Pattern.compile( "\\$" );
+        final Pattern propRef = Pattern.compile("\\$\\{(((\\$[^\\{\\}])|[^\\$\\}])+\\$?)\\}");
+        final Pattern backslash = Pattern.compile("\\\\");
+        final Pattern dollar = Pattern.compile("\\$");
 
-        if ( s == null )
+        if (s == null)
         {
             return null;
         }
 
-        if ( s.indexOf( "${" ) == -1 )
+        if (s.indexOf("${") == -1)
         { // shortcut if no expansions
             return s;
         }
 
-        for ( int i = 0; i < 20; i++ )
+        for (int i = 0; i < 20; i++)
         { // avoids self-referencing expansions
             // System.out.println("XXX expand[" + i + "] = [" + s + "]");
-            Matcher matcher = propRef.matcher( s );
+            Matcher matcher = propRef.matcher(s);
 
-            if ( !matcher.find() )
+            if (!matcher.find())
             {
                 // replace unmatched items
-                s = s.replaceAll( "\\Q??[\\E", "\\${" );
-                s = s.replaceAll( "\\Q??]\\E", "}" );
+                s = s.replaceAll("\\Q??[\\E", "\\${");
+                s = s.replaceAll("\\Q??]\\E", "}");
                 // debug("expanded: " + s);
-                if ( s.indexOf( "${" ) != -1 )
+                if (s.indexOf("${") != -1)
                 {
-                    throw new RuntimeException( "Can't expand: " + s );
+                    throw new RuntimeException("Can't expand: " + s);
                 }
                 return s;
             }
 
-            String key = matcher.group( 1 );
-            String[] keydef = key.split( ":[=+-?@]", 2 );
+            String key = matcher.group(1);
+            String[] keydef = key.split(":[=+-?@]", 2);
             String replace;
 
-            if ( keydef.length != 2 )
+            if (keydef.length != 2)
             {
-                replace = key.length() == 0 ? null : p.getProperty( key );
+                replace = key.length() == 0 ? null : p.getProperty(key);
             }
             else
             {
-                replace = keydef[0].length() == 0 ? null : p.getProperty( keydef[0] );
+                replace = keydef[0].length() == 0 ? null : p.getProperty(keydef[0]);
 
-                if ( replace != null && ( replace.length() == 0 || replace.indexOf( "${" ) != -1 ) )
+                if (replace != null
+                    && (replace.length() == 0 || replace.indexOf("${") != -1))
                 {
                     // don't want unexpanded replacement, as it may stop ${...:-default}
                     replace = null;
                 }
 
-                if ( key.indexOf( ":+" ) != -1 )
+                if (key.indexOf(":+") != -1)
                 {
-                    replace = ( ( replace == null ) ? "" : keydef[1] );
+                    replace = ((replace == null) ? "" : keydef[1]);
                 }
-                else if ( replace == null )
+                else if (replace == null)
                 {
                     replace = keydef[1];
 
-                    if ( key.indexOf( ":?" ) != -1 )
+                    if (key.indexOf(":?") != -1)
                     {
-                        String msg = "${" + keydef[0] + ":?" + keydef[1] + "} property not set";
-                        throw new RuntimeException( msg );
+                        String msg = "${" + keydef[0] + ":?" + keydef[1]
+                            + "} property not set";
+                        throw new RuntimeException(msg);
                     }
 
-                    if ( key.indexOf( ":=" ) != -1 )
+                    if (key.indexOf(":=") != -1)
                     {
-                        p.setProperty( keydef[0], keydef[1] );
+                        p.setProperty(keydef[0], keydef[1]);
                     }
                 }
             }
 
-            if ( replace == null )
+            if (replace == null)
             {
                 // TODO: this is a hack to avoid looping on unmatched references
                 // should really leave unchanged and process rest of string.
@@ -155,18 +154,17 @@
             // to
             // escape literal characters in the replacement string.
             // escape any \ or $ in replacement string
-            replace = backslash.matcher( replace ).replaceAll( "\\\\\\\\" );
-            replace = dollar.matcher( replace ).replaceAll( "\\\\\\$" );
+            replace = backslash.matcher(replace).replaceAll("\\\\\\\\");
+            replace = dollar.matcher(replace).replaceAll("\\\\\\$");
 
-            s = s.replaceAll( "\\Q${" + key + "}\\E", replace );
+            s = s.replaceAll("\\Q${" + key + "}\\E", replace);
         }
 
-        throw new RuntimeException( "expand: loop expanding: " + s );
+        throw new RuntimeException("expand: loop expanding: " + s);
     }
 
-
-    public static String expand( String s )
+    public static String expand(String s)
     {
-        return expand( s, BldProperties.global() );
-    }    
+        return expand(s, BldProperties.global());
+    }
 }