[OSGi] Populate brooklyn.properties from config admin

Also reload properties when config admin is updated.


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/0ac07fe3
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/0ac07fe3
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/0ac07fe3

Branch: refs/heads/master
Commit: 0ac07fe3d010b5afa470e9489ba64aeafbd18537
Parents: 66e9f56
Author: Svetoslav Neykov <[email protected]>
Authored: Thu Apr 7 16:02:02 2016 +0300
Committer: Svetoslav Neykov <[email protected]>
Committed: Fri Apr 8 10:05:12 2016 +0300

----------------------------------------------------------------------
 .../core/internal/BrooklynProperties.java       | 23 ++++-
 .../mgmt/internal/LocalManagementContext.java   |  2 +-
 karaf/init/pom.xml                              |  5 +
 .../brooklyn/launcher/osgi/ConfigSupplier.java  | 59 ++++++++++++
 .../brooklyn/launcher/osgi/OsgiLauncher.java    | 93 ++++++++++++++++---
 .../resources/OSGI-INF/blueprint/blueprint.xml  | 22 ++---
 .../launcher/osgi/OsgiLauncherTest.java         | 97 ++++++++++++++++++++
 .../common/BrooklynPropertiesFactoryHelper.java | 27 +++++-
 pom.xml                                         |  1 +
 9 files changed, 299 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynProperties.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynProperties.java 
b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynProperties.java
index ea7cd07..3d0b128 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynProperties.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynProperties.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
 
 /** 
  * Utils for accessing command-line and system-env properties;
@@ -78,6 +79,7 @@ public interface BrooklynProperties extends Map, 
StringConfigMap {
             private String globalLocationMetadataFile = null;
             private String globalPropertiesFile = null;
             private String localPropertiesFile = null;
+            private Supplier<Map<?, ?>> propertiesSupplier;
             private BrooklynProperties originalProperties = null;
 
             private Builder(boolean setGlobalFileDefaults) {
@@ -131,10 +133,18 @@ public interface BrooklynProperties extends Map, 
StringConfigMap {
                 globalPropertiesFile = val;
                 return this;
             }
+
+            /**
+             * A {@link Supplier} which returns a fresh view of the current 
properties
+             */
+            public Builder propertiesSupplier(Supplier<Map<?, ?>> 
propertiesSupplier) {
+                this.propertiesSupplier = propertiesSupplier;
+                return this;
+            }
             
             @Beta
             public boolean hasDelegateOriginalProperties() {
-                return this.originalProperties==null;
+                return this.originalProperties!=null;
             }
             
             /**
@@ -155,6 +165,7 @@ public interface BrooklynProperties extends Map, 
StringConfigMap {
                 // But might that make unit tests run very badly when 
developer is offline?
                 addPropertiesFromUrl(properties, defaultLocationMetadataUrl, 
false);
                 
+                addPropertiesFromMapSupplier(properties, propertiesSupplier);
                 addPropertiesFromFile(properties, globalLocationMetadataFile);
                 addPropertiesFromFile(properties, globalPropertiesFile);
                 addPropertiesFromFile(properties, localPropertiesFile);
@@ -178,6 +189,7 @@ public interface BrooklynProperties extends Map, 
StringConfigMap {
                         .add("globalLocationMetadataUrl", 
globalLocationMetadataFile)
                         .add("globalPropertiesFile", globalPropertiesFile)
                         .add("localPropertiesFile", localPropertiesFile)
+                        .add("propertiesSupplier", propertiesSupplier)
                         .toString();
             }
         }
@@ -204,6 +216,15 @@ public interface BrooklynProperties extends Map, 
StringConfigMap {
                 p.addFrom(f);
             }
         }
+
+        private static void addPropertiesFromMapSupplier(BrooklynProperties p, 
Supplier<Map<?, ?>> propertiesSupplier) {
+            if (propertiesSupplier != null) {
+                Map<?, ?> newProps = propertiesSupplier.get();
+                if (newProps != null) {
+                    p.addFrom(newProps);
+                }
+            }
+        }
     }
 
     public BrooklynProperties addEnvironmentVars();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
index 76500bc..0731b84 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
@@ -394,7 +394,7 @@ public class LocalManagementContext extends 
AbstractManagementContext {
         
         BrooklynProperties properties = builder.build();
         configMap = new DeferredBrooklynProperties(properties, this);
-        if (brooklynAdditionalProperties != null) {
+        if (brooklynAdditionalProperties != null && 
!brooklynAdditionalProperties.isEmpty()) {
             log.info("Reloading additional brooklyn properties from " + 
brooklynAdditionalProperties);
             configMap.addFromMap(brooklynAdditionalProperties);
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/karaf/init/pom.xml
----------------------------------------------------------------------
diff --git a/karaf/init/pom.xml b/karaf/init/pom.xml
index 3531656..4791dd8 100644
--- a/karaf/init/pom.xml
+++ b/karaf/init/pom.xml
@@ -54,6 +54,11 @@
             <artifactId>org.apache.karaf.system.core</artifactId>
             <version>${karaf.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>${felix-osgi-compendium.version}</version>
+        </dependency>
 
         <dependency>
             <groupId>org.testng</groupId>

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/ConfigSupplier.java
----------------------------------------------------------------------
diff --git 
a/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/ConfigSupplier.java
 
b/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/ConfigSupplier.java
new file mode 100644
index 0000000..b1880a0
--- /dev/null
+++ 
b/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/ConfigSupplier.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.brooklyn.launcher.osgi;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.osgi.service.cm.Configuration;
+
+import com.google.common.base.Supplier;
+
+public class ConfigSupplier implements Supplier<Map<?, ?>> {
+    private Map<?, ?> props;
+
+    public ConfigSupplier(@Nullable Configuration config) {
+        if (config != null) {
+            this.props = dictToMap(config.getProperties());
+        } else {
+            this.props = MutableMap.of();
+        }
+    }
+
+    @Override
+    public Map<?, ?> get() {
+        return props;
+    }
+
+    public void update(Map<?, ?> props) {
+        this.props = props;
+    }
+
+    private static Map<?, ?> dictToMap(Dictionary<?, ?> props) {
+        Map<Object, Object> mapProps = MutableMap.of();
+        Enumeration<?> keyEnum = props.keys();
+        while (keyEnum.hasMoreElements()) {
+            Object key = keyEnum.nextElement();
+            mapProps.put(key, props.get(key));
+        }
+        return mapProps;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/OsgiLauncher.java
----------------------------------------------------------------------
diff --git 
a/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/OsgiLauncher.java 
b/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/OsgiLauncher.java
index 03a1a2d..913920f 100644
--- 
a/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/OsgiLauncher.java
+++ 
b/karaf/init/src/main/java/org/apache/brooklyn/launcher/osgi/OsgiLauncher.java
@@ -15,6 +15,9 @@
  */
 package org.apache.brooklyn.launcher.osgi;
 
+import java.io.IOException;
+import java.util.Map;
+
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -23,36 +26,78 @@ import org.apache.brooklyn.core.BrooklynVersionService;
 import org.apache.brooklyn.core.internal.BrooklynProperties;
 import org.apache.brooklyn.core.mgmt.persist.PersistMode;
 import org.apache.brooklyn.launcher.common.BasicLauncher;
+import org.apache.brooklyn.launcher.common.BrooklynPropertiesFactoryHelper;
 import org.apache.brooklyn.rest.BrooklynWebConfig;
 import 
org.apache.brooklyn.rest.security.provider.BrooklynUserWithRandomPasswordSecurityProvider;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.javalang.Threads;
+import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Initializer for brooklyn-core when running in an OSGi environment.
- *
- * Temporarily here; should be totally contained in blueprint beans' 
init-methods.
  */
 public class OsgiLauncher extends BasicLauncher<OsgiLauncher> {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(OsgiLauncher.class);
+    public static final String BROOKLYN_CONFIG_PID = "brooklyn";
+    
+    private Object reloadLock = new Object();
 
     private BrooklynVersionService brooklynVersion;
 
+    private String globalBrooklynProperties;
+    private String localBrooklynProperties;
+
+    private ConfigurationAdmin configAdmin;
+    private ConfigSupplier configSupplier;
+
+
     @Override
     public OsgiLauncher start() {
         // make sure brooklyn-core bundle is started
         brooklynVersion.getVersion();
 
+        Configuration brooklynConfig = getConfiguration(configAdmin, 
BROOKLYN_CONFIG_PID);
+        // Note that this doesn't check whether the files exist, just that 
there are potential alternative sources for configuration.
+        if (brooklynConfig == null && 
Strings.isEmpty(globalBrooklynProperties) && 
Strings.isEmpty(localBrooklynProperties)) {
+            LOG.warn("Config Admin PID '" + BROOKLYN_CONFIG_PID + "' not 
found, not using external configuration. Create a brooklyn.cfg file in etc 
folder.");
+        }
+        configSupplier = new ConfigSupplier(brooklynConfig);
+        BrooklynPropertiesFactoryHelper helper = new 
BrooklynPropertiesFactoryHelper(
+                globalBrooklynProperties, localBrooklynProperties, 
configSupplier);
+        setBrooklynPropertiesBuilder(helper.createPropertiesBuilder());
         return super.start();
     }
 
+    private Configuration getConfiguration(ConfigurationAdmin configAdmin, 
String brooklynConfigPid) {
+        String filter = '(' + Constants.SERVICE_PID + '=' + brooklynConfigPid 
+ ')';
+        Configuration[] configs;
+        try {
+            configs = configAdmin.listConfigurations(filter);
+        } catch (InvalidSyntaxException | IOException e) {
+            throw Exceptions.propagate(e);
+        }
+        if (configs != null && configs.length > 0) {
+            return configs[0];
+        } else {
+            return null;
+        }
+    }
+
     // Called by blueprint container
     // init-method can't find the start method for some reason, provide an 
alternative
     public void init() {
-        start();
+        synchronized (reloadLock) {
+            LOG.debug("OsgiLauncher init");
+            start();
+        }
     }
 
     // Called by blueprint container
@@ -61,6 +106,27 @@ public class OsgiLauncher extends 
BasicLauncher<OsgiLauncher> {
         Threads.runShutdownHooks();
     }
 
+    @Override
+    protected void startingUp() {
+        super.startingUp();
+        ManagementContext managementContext = getManagementContext();
+        BrooklynProperties brooklynProperties = (BrooklynProperties) 
managementContext.getConfig();
+        if (BrooklynWebConfig.hasNoSecurityOptions(brooklynProperties)) {
+            LOG.info("No security provider options specified. Define a 
security provider or users to prevent a random password being created and 
logged.");
+            brooklynProperties.put(
+                    BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE,
+                    new 
BrooklynUserWithRandomPasswordSecurityProvider(managementContext));
+        }
+    }
+
+    public void updateProperties(Map<?, ?> props) {
+        synchronized (reloadLock) {
+            LOG.info("Updating brooklyn config because of config admin 
changes.");
+            configSupplier.update(props);
+            getManagementContext().reloadBrooklynProperties();
+        }
+    }
+
     public void setBrooklynVersion(BrooklynVersionService brooklynVersion) {
         this.brooklynVersion = brooklynVersion;
     }
@@ -118,17 +184,16 @@ public class OsgiLauncher extends 
BasicLauncher<OsgiLauncher> {
         copyPersistedState(destinationDir);
     }
 
-    @Override
-    protected void startingUp() {
-        super.startingUp();
-        ManagementContext managementContext = getManagementContext();
-        BrooklynProperties brooklynProperties = (BrooklynProperties) 
managementContext.getConfig();
-        if (BrooklynWebConfig.hasNoSecurityOptions(brooklynProperties)) {
-            LOG.info("No security provider options specified. Define a 
security provider or users to prevent a random password being created and 
logged.");
-            brooklynProperties.put(
-                    BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE,
-                    new 
BrooklynUserWithRandomPasswordSecurityProvider(managementContext));
-        }
+    public void setConfigAdmin(ConfigurationAdmin configAdmin) {
+        this.configAdmin = configAdmin;
+    }
+
+    public void setGlobalBrooklynProperties(String globalBrooklynProperties) {
+        this.globalBrooklynProperties = globalBrooklynProperties;
+    }
+
+    public void setLocalBrooklynProperties(String localBrooklynProperties) {
+        this.localBrooklynProperties = localBrooklynProperties;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/karaf/init/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/karaf/init/src/main/resources/OSGI-INF/blueprint/blueprint.xml 
b/karaf/init/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 51dfce8..0ed314c 100644
--- a/karaf/init/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/karaf/init/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -30,6 +30,9 @@ limitations under the License.
     <reference id="systemService"
                interface="org.apache.karaf.system.SystemService" />
 
+    <reference id="configAdmin"
+               interface="org.osgi.service.cm.ConfigurationAdmin" />
+
     <cm:property-placeholder persistent-id="org.apache.brooklyn.osgilauncher" 
update-strategy="reload">
         <cm:default-properties>
             <cm:property name="ignoreCatalogErrors" value="true"/>
@@ -44,24 +47,12 @@ limitations under the License.
         </cm:default-properties>
     </cm:property-placeholder>
 
-    <bean id="propertiesBuilderFactory"
-          
class="org.apache.brooklyn.launcher.common.BrooklynPropertiesFactoryHelper">
-        <argument value="${globalBrooklynPropertiesFile}"/>
-        <argument value="${localBrooklynPropertiesFile}"/>
-    </bean>
-
-    <bean id="propertiesBuilder"
-          
class="org.apache.brooklyn.core.internal.BrooklynProperties.Factory.Builder"
-          factory-ref="propertiesBuilderFactory"
-          factory-method="createPropertiesBuilder"/>
-
     <bean id="launcher"
           class="org.apache.brooklyn.launcher.osgi.OsgiLauncher"
           init-method="init"
           destroy-method="destroy">
 
         <property name="brooklynVersion" ref="brooklynVersion"/>
-        <property name="brooklynPropertiesBuilder" ref="propertiesBuilder"/>
 
         <property name="ignoreCatalogErrors" value="${ignoreCatalogErrors}"/>
         <property name="ignorePersistenceErrors" 
value="${ignorePersistenceErrors}"/>
@@ -70,6 +61,13 @@ limitations under the License.
         <property name="persistenceDir" value="${persistenceDir}"/>
         <property name="persistenceLocation" value="${persistenceLocation}"/>
         <property name="persistPeriod" value="${persistPeriod}"/>
+        <property name="globalBrooklynProperties" 
value="${globalBrooklynPropertiesFile}"/>
+        <property name="localBrooklynProperties" 
value="${localBrooklynPropertiesFile}"/>
+        <property name="configAdmin" ref="configAdmin"/>
+
+        <cm:managed-properties persistent-id="brooklyn"
+                               update-method="updateProperties"
+                               update-strategy="component-managed" />
     </bean>
 
     <bean id="localManagementContextService"

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/karaf/itest/src/test/java/org/apache/brooklyn/launcher/osgi/OsgiLauncherTest.java
----------------------------------------------------------------------
diff --git 
a/karaf/itest/src/test/java/org/apache/brooklyn/launcher/osgi/OsgiLauncherTest.java
 
b/karaf/itest/src/test/java/org/apache/brooklyn/launcher/osgi/OsgiLauncherTest.java
new file mode 100644
index 0000000..eecd558
--- /dev/null
+++ 
b/karaf/itest/src/test/java/org/apache/brooklyn/launcher/osgi/OsgiLauncherTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.brooklyn.launcher.osgi;
+
+import static org.apache.brooklyn.KarafTestUtils.defaultOptionsWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static 
org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
+import static 
org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+
+import org.apache.brooklyn.KarafTestUtils;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.test.IntegrationTest;
+import org.apache.karaf.features.BootFinished;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.util.Filter;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+@Category(IntegrationTest.class)
+public class OsgiLauncherTest {
+
+    private static final String TEST_VALUE_RUNTIME = "test.value";
+    private static final String TEST_KEY_RUNTIME = "test.key";
+    private static final String TEST_VALUE_IN_CFG = "test.cfg";
+    private static final String TEST_KEY_IN_CFG = "test.key.in.cfg";
+
+    @Inject
+    protected ManagementContext mgmt;
+
+    @Inject
+    protected ConfigurationAdmin configAdmin;
+
+    /**
+     * To make sure the tests run only when the boot features are fully
+     * installed
+     */
+    @Inject
+    @Filter(timeout = 120000)
+    BootFinished bootFinished;
+
+    @Configuration
+    public static Option[] configuration() throws Exception {
+        return defaultOptionsWith(
+                
editConfigurationFilePut("etc/org.apache.brooklyn.osgilauncher.cfg", 
"globalBrooklynPropertiesFile", ""),
+                
editConfigurationFilePut("etc/org.apache.brooklyn.osgilauncher.cfg", 
"localBrooklynPropertiesFile", ""),
+                editConfigurationFilePut("etc/brooklyn.cfg", TEST_KEY_IN_CFG, 
TEST_VALUE_IN_CFG),
+                features(KarafTestUtils.brooklynFeaturesRepository(), 
"brooklyn-osgi-launcher")
+                // Uncomment this for remote debugging the tests on port 5005
+                // ,KarafDistributionOption.debugConfiguration()
+        );
+    }
+
+    @Test
+    public void testConfig() throws IOException {
+        
assertFalse(mgmt.getConfig().getAllConfig().containsKey(TEST_KEY_RUNTIME));
+        org.osgi.service.cm.Configuration config = 
configAdmin.getConfiguration("brooklyn", null);
+        assertEquals(config.getProperties().get(TEST_KEY_IN_CFG), 
TEST_VALUE_IN_CFG);
+        config.getProperties().put(TEST_KEY_RUNTIME, TEST_VALUE_RUNTIME);
+        config.update();
+        Asserts.succeedsEventually(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(TEST_VALUE_RUNTIME, 
mgmt.getConfig().getFirst(TEST_KEY_RUNTIME));
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BrooklynPropertiesFactoryHelper.java
----------------------------------------------------------------------
diff --git 
a/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BrooklynPropertiesFactoryHelper.java
 
b/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BrooklynPropertiesFactoryHelper.java
index f41167a..2aff0f6 100644
--- 
a/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BrooklynPropertiesFactoryHelper.java
+++ 
b/launcher-common/src/main/java/org/apache/brooklyn/launcher/common/BrooklynPropertiesFactoryHelper.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.launcher.common;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.util.Map;
 
 import org.apache.brooklyn.core.internal.BrooklynProperties;
 import org.apache.brooklyn.core.internal.BrooklynProperties.Factory.Builder;
@@ -32,27 +33,45 @@ import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Supplier;
+
 public class BrooklynPropertiesFactoryHelper {
     private static final Logger LOG = 
LoggerFactory.getLogger(BrooklynPropertiesFactoryHelper.class);
 
     private final String globalBrooklynPropertiesFile;
     private final String localBrooklynPropertiesFile;
+    private final Supplier<Map<?, ?>> propertiesSupplier;
     private final BrooklynProperties brooklynProperties;
 
     public BrooklynPropertiesFactoryHelper(String 
globalBrooklynPropertiesFile, String localBrooklynPropertiesFile) {
-        this(globalBrooklynPropertiesFile, localBrooklynPropertiesFile, null);
+        this(globalBrooklynPropertiesFile, localBrooklynPropertiesFile, null, 
null);
     }
 
     public BrooklynPropertiesFactoryHelper(BrooklynProperties 
brooklynProperties) {
-        this(null, null, brooklynProperties);
+        this(null, null, brooklynProperties, null);
     }
 
     public BrooklynPropertiesFactoryHelper(String globalBrooklynPropertiesFile,
             String localBrooklynPropertiesFile,
             BrooklynProperties brooklynProperties) {
+        this(globalBrooklynPropertiesFile, localBrooklynPropertiesFile, 
brooklynProperties, null);
+    }
+
+    public BrooklynPropertiesFactoryHelper(
+            String globalBrooklynPropertiesFile,
+            String localBrooklynPropertiesFile,
+            Supplier<Map<?, ?>> propertiesSupplier) {
+        this(globalBrooklynPropertiesFile, localBrooklynPropertiesFile, null, 
propertiesSupplier);
+    }
+
+    public BrooklynPropertiesFactoryHelper(String globalBrooklynPropertiesFile,
+            String localBrooklynPropertiesFile,
+            BrooklynProperties brooklynProperties,
+            Supplier<Map<?, ?>> propertiesSupplier) {
         this.globalBrooklynPropertiesFile = globalBrooklynPropertiesFile;
         this.localBrooklynPropertiesFile = localBrooklynPropertiesFile;
         this.brooklynProperties = brooklynProperties;
+        this.propertiesSupplier = propertiesSupplier;
     }
 
     public BrooklynProperties.Factory.Builder createPropertiesBuilder() {
@@ -84,6 +103,10 @@ public class BrooklynPropertiesFactoryHelper {
                 checkFilePermissionsX00(localProperties);
                 builder.localPropertiesFile(localProperties.getAbsolutePath());
             }
+
+            if (propertiesSupplier != null) {
+                builder.propertiesSupplier(propertiesSupplier);
+            }
             return builder;
         } else {
             if (globalBrooklynPropertiesFile != null)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0ac07fe3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 433e912..bc7dde6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -157,6 +157,7 @@
         <jna.version>4.0.0</jna.version>
         <winrm4j.version>0.3.5</winrm4j.version>
         <karaf.version>4.0.4</karaf.version>
+        <felix-osgi-compendium.version>1.4.0</felix-osgi-compendium.version>
         <!-- Transitive dependencies, declared explicitly to avoid version 
mismatch -->
         <clojure.version>1.4.0</clojure.version>
         <zookeeper.version>3.3.4</zookeeper.version>

Reply via email to