SLING-4728 - avoid system properties in CrankstartSetup

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1722133 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/crankstart/junit/CrankstartSetup.java b/src/main/java/org/apache/sling/crankstart/junit/CrankstartSetup.java
index 295cb80..4f80ce9 100644
--- a/src/main/java/org/apache/sling/crankstart/junit/CrankstartSetup.java
+++ b/src/main/java/org/apache/sling/crankstart/junit/CrankstartSetup.java
@@ -11,12 +11,15 @@
 import java.net.ServerSocket;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Random;
+import java.util.Properties;
+import java.util.UUID;
 
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.sling.crankstart.launcher.Launcher;
+import org.apache.sling.crankstart.launcher.PropertiesVariableResolver;
+import org.apache.sling.provisioning.model.ModelUtility.VariableResolver;
 import org.junit.rules.ExternalResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,9 +32,12 @@
     private final String storagePath = getOsgiStoragePath(); 
     private Thread crankstartThread;
     private final String baseUrl = "http://localhost:" + port;
+    private final Properties replacementProps = new Properties();
     
     private static List<CrankstartSetup> toCleanup = new ArrayList<CrankstartSetup>();
     
+    private VariableResolver variablesResolver = new PropertiesVariableResolver(replacementProps, Launcher.VARIABLE_OVERRIDE_PREFIX);
+    
     private String [] modelPaths;
     
     @Override
@@ -101,8 +107,8 @@
         log.info("Starting {}", this);
         
         final HttpUriRequest get = new HttpGet(baseUrl);
-        System.setProperty("crankstart.model.http.port", String.valueOf(port));
-        System.setProperty("crankstart.model.osgi.storage.path", storagePath);
+        replacementProps.setProperty("crankstart.model.http.port", String.valueOf(port));
+        replacementProps.setProperty("crankstart.model.osgi.storage.path", storagePath);
         
         try {
             new DefaultHttpClient().execute(get);
@@ -110,7 +116,7 @@
         } catch(IOException expected) {
         }
         
-        final Launcher launcher = new Launcher();
+        final Launcher launcher = new Launcher().withVariableResolver(variablesResolver);
         for(String path : modelPaths) {
             mergeModelResource(launcher, path);
         }
@@ -154,8 +160,7 @@
     
     private static String getOsgiStoragePath() {
         final File tmpRoot = new File(System.getProperty("java.io.tmpdir"));
-        final Random random = new Random();
-        final File tmpFolder = new File(tmpRoot, System.currentTimeMillis() + "_" + random.nextInt());
+        final File tmpFolder = new File(tmpRoot, CrankstartSetup.class.getSimpleName() + "_" + UUID.randomUUID());
         if(!tmpFolder.mkdir()) {
             fail("Failed to create " + tmpFolder.getAbsolutePath());
         }
diff --git a/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java b/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java
index ff694de..f68451f 100644
--- a/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java
+++ b/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java
@@ -55,21 +55,17 @@
     
     public static final String VARIABLE_OVERRIDE_PREFIX = "crankstart.model.";
 
-    /** Allow for overriding model variables with system properties */ 
-    private final VariableResolver overridingVariableResolver = new VariableResolver() {
-        @Override
-        public String resolve(Feature f, String variableName) {
-            final String overrideKey = VARIABLE_OVERRIDE_PREFIX + variableName;
-            final String sysProp = System.getProperty(overrideKey);
-            if(sysProp == null) {
-                return f.getVariables().get(variableName);
-            } else {
-                log.info("Overriding model variable {}={} (from system property {})", variableName, sysProp, overrideKey);
-                return sysProp;
+    /** Default variable resolver using system properties */
+    public static final VariableResolver DEFAULT_VARIABLE_RESOLVER = 
+        new PropertiesVariableResolver(System.getProperties(), VARIABLE_OVERRIDE_PREFIX) {
+            @Override
+            protected void onOverride(String variableName, String value, String propertyName) {
+                log.info("Overriding model variable {}={} (from system property {})", variableName, value, propertyName);
             }
-        }
-        
-    };
+        };
+    
+    /** Allow for overriding model variables */ 
+    private VariableResolver variableResolver; 
     
     public static final FeatureFilter NOT_CRANKSTART_FILTER = new FeatureFilter() {
         @Override
@@ -87,8 +83,17 @@
     
     public Launcher(String ... args) throws Exception {
         MavenResolver.setup();
+        withVariableResolver(null);
         withModelPaths(args);
     }
+    
+    /** Use the supplied VariableResolver. Defaults to DEFAULT_VARIABLE_RESOLVER if v
+     *  is null or if this is not called. 
+     */
+    public Launcher withVariableResolver(VariableResolver v) {
+        variableResolver = (v == null ? DEFAULT_VARIABLE_RESOLVER : v);
+        return this;
+    }
 
     /** Add models from the supplied paths, can be either files or folders */ 
     public Launcher withModelPaths(String ... paths) throws Exception {
@@ -118,7 +123,7 @@
     
     public void computeEffectiveModel() throws Exception {
         new NestedModelsMerger(model).visit();
-        model = ModelUtility.getEffectiveModel(model, overridingVariableResolver);
+        model = ModelUtility.getEffectiveModel(model, variableResolver);
     }
     
     public Model getModel() {
diff --git a/src/main/java/org/apache/sling/crankstart/launcher/PropertiesVariableResolver.java b/src/main/java/org/apache/sling/crankstart/launcher/PropertiesVariableResolver.java
new file mode 100644
index 0000000..b0d1437
--- /dev/null
+++ b/src/main/java/org/apache/sling/crankstart/launcher/PropertiesVariableResolver.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sling.crankstart.launcher;
+
+import java.util.Properties;
+
+import org.apache.sling.provisioning.model.Feature;
+import org.apache.sling.provisioning.model.ModelUtility.VariableResolver;
+
+/** VariableResolver that uses a Properties object */
+public class PropertiesVariableResolver implements VariableResolver {
+    private final Properties props;
+    private final String variableNamePrefix;
+    
+    public PropertiesVariableResolver(Properties props, String variableNamePrefix) {
+        this.props = props;
+        this.variableNamePrefix = variableNamePrefix;
+    }
+    
+    @Override
+    public String resolve(Feature f, String variableName) {
+        final String propertyName = variableNamePrefix + variableName;
+        final String value = props.getProperty(propertyName);
+        if(value == null) {
+            return f.getVariables().get(variableName);
+        } else {
+            onOverride(variableName, value, propertyName);
+            return value;
+        }
+    }
+    
+    protected void onOverride(String variableName, String value, String propertyName) {
+    }
+}
\ No newline at end of file