activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dej...@apache.org
Subject [2/2] git commit: https://issues.apache.org/jira/browse/AMQ-5305 - modify <destination> element with runtime configuration plugin
Date Thu, 28 Aug 2014 12:08:52 GMT
https://issues.apache.org/jira/browse/AMQ-5305 - modify <destination> element with runtime configuration plugin


Project: http://git-wip-us.apache.org/repos/asf/activemq/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/bbc039fc
Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/bbc039fc
Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/bbc039fc

Branch: refs/heads/trunk
Commit: bbc039fceb85239667563f8c852db6ed016b73f8
Parents: b76d831
Author: Dejan Bosanac <dejan@nighttale.net>
Authored: Thu Aug 28 14:08:11 2014 +0200
Committer: Dejan Bosanac <dejan@nighttale.net>
Committed: Thu Aug 28 14:08:41 2014 +0200

----------------------------------------------------------------------
 .../plugin/AuthorizationPluginProcessor.java    |  77 +++
 .../activemq/plugin/ConfigurationProcessor.java |  36 +
 .../plugin/DefaultConfigurationProcessor.java   | 215 ++++++
 .../plugin/DestinationInterceptorProcessor.java |  34 +
 .../plugin/DestinationPolicyProcessor.java      |  37 ++
 .../activemq/plugin/DestinationsProcessor.java  |  76 +++
 .../org/apache/activemq/plugin/JAXBUtils.java   |  65 ++
 .../plugin/NetworkConnectorProcessor.java       |  80 +++
 .../plugin/NetworkConnectorsProcessor.java      |  34 +
 .../activemq/plugin/PluginsProcessor.java       |  37 ++
 .../activemq/plugin/PolicyEntryProcessor.java   |  71 ++
 .../activemq/plugin/PolicyMapProcessor.java     |  44 ++
 .../activemq/plugin/ProcessorFactory.java       |  39 ++
 .../plugin/PropertiesPlaceHolderUtil.java       | 183 +++++
 .../plugin/RuntimeConfigurationBroker.java      | 660 +------------------
 .../SimpleAuthenticationPluginProcessor.java    |  47 ++
 .../VirtualDestinationInterceptorProcessor.java | 116 ++++
 .../src/main/resources/binding.xjb              |   4 +
 .../org/apache/activemq/DestinationsTest.java   |  72 ++
 .../org/apache/activemq/destinationTest-add.xml |  36 +
 .../activemq/destinationTest-original.xml       |  34 +
 .../apache/activemq/destinationTest-remove.xml  |  36 +
 22 files changed, 1409 insertions(+), 624 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/AuthorizationPluginProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/AuthorizationPluginProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/AuthorizationPluginProcessor.java
new file mode 100644
index 0000000..e7f2fa0
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/AuthorizationPluginProcessor.java
@@ -0,0 +1,77 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.filter.DestinationMapEntry;
+import org.apache.activemq.security.*;
+import org.apache.activemq.schema.core.DtoAuthorizationPlugin;
+import org.apache.activemq.schema.core.DtoAuthorizationMap;
+import org.apache.activemq.schema.core.DtoAuthorizationEntry;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class AuthorizationPluginProcessor extends DefaultConfigurationProcessor {
+
+    public AuthorizationPluginProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public void modify(Object existing, Object candidate) {
+        try {
+            // replace authorization map - need exclusive write lock to total broker
+            AuthorizationBroker authorizationBroker =
+                    (AuthorizationBroker) plugin.getBrokerService().getBroker().getAdaptor(AuthorizationBroker.class);
+
+            authorizationBroker.setAuthorizationMap(fromDto(filter(candidate, DtoAuthorizationPlugin.Map.class)));
+        } catch (Exception e) {
+            plugin.info("failed to apply modified AuthorizationMap to AuthorizationBroker", e);
+        }
+    }
+
+    private AuthorizationMap fromDto(List<Object> map) {
+        XBeanAuthorizationMap xBeanAuthorizationMap = new XBeanAuthorizationMap();
+        for (Object o : map) {
+            if (o instanceof DtoAuthorizationPlugin.Map) {
+                DtoAuthorizationPlugin.Map dtoMap = (DtoAuthorizationPlugin.Map) o;
+                List<DestinationMapEntry> entries = new LinkedList<DestinationMapEntry>();
+                // revisit - would like to map getAuthorizationMap to generic getContents
+                for (Object authMap : filter(dtoMap.getAuthorizationMap(), DtoAuthorizationMap.AuthorizationEntries.class)) {
+                    for (Object entry : filter(getContents(authMap), DtoAuthorizationEntry.class)) {
+                        entries.add(fromDto(entry, new XBeanAuthorizationEntry()));
+                    }
+                }
+                xBeanAuthorizationMap.setAuthorizationEntries(entries);
+                try {
+                    xBeanAuthorizationMap.afterPropertiesSet();
+                } catch (Exception e) {
+                    plugin.info("failed to update xBeanAuthorizationMap auth entries:", e);
+                }
+
+                for (Object entry : filter(dtoMap.getAuthorizationMap(), DtoAuthorizationMap.TempDestinationAuthorizationEntry.class)) {
+                    // another restriction - would like to be getContents
+                    DtoAuthorizationMap.TempDestinationAuthorizationEntry dtoEntry = (DtoAuthorizationMap.TempDestinationAuthorizationEntry) entry;
+                    xBeanAuthorizationMap.setTempDestinationAuthorizationEntry(fromDto(dtoEntry.getTempDestinationAuthorizationEntry(), new TempDestinationAuthorizationEntry()));
+                }
+            } else {
+                plugin.info("No support for updates to: " + o);
+            }
+        }
+        return xBeanAuthorizationMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ConfigurationProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ConfigurationProcessor.java
new file mode 100644
index 0000000..89dc2b2
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ConfigurationProcessor.java
@@ -0,0 +1,36 @@
+/**
+ * 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.activemq.plugin;
+
+import java.util.List;
+import org.apache.activemq.schema.core.DtoBroker;
+
+public interface ConfigurationProcessor {
+
+    public void processChanges(List current, List modified);
+
+    public void processChanges(DtoBroker current, DtoBroker modified);
+
+    public void modify(Object existing, Object candidate);
+
+    public void addNew(Object o);
+
+    public void remove(Object o);
+
+    public ConfigurationProcessor findProcessor(Object o);
+
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DefaultConfigurationProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DefaultConfigurationProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DefaultConfigurationProcessor.java
new file mode 100644
index 0000000..fddfe48
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DefaultConfigurationProcessor.java
@@ -0,0 +1,215 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.util.IntrospectionSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.bind.JAXBElement;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Pattern;
+import org.apache.activemq.schema.core.DtoBroker;
+
+public class DefaultConfigurationProcessor implements ConfigurationProcessor {
+
+    public static final Logger LOG = LoggerFactory.getLogger(DefaultConfigurationProcessor.class);
+    RuntimeConfigurationBroker plugin;
+    Class configurationClass;
+
+    Pattern matchPassword = Pattern.compile("password=.*,");
+
+    public DefaultConfigurationProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        this.plugin = plugin;
+        this.configurationClass = configurationClass;
+    }
+
+    @Override
+    public void processChanges(DtoBroker currentConfiguration, DtoBroker modifiedConfiguration) {
+        List current = filter(currentConfiguration, configurationClass);
+        List modified = filter(modifiedConfiguration, configurationClass);
+
+        if (current.equals(modified)) {
+            plugin.debug("no changes to " + configurationClass.getSimpleName());
+            return;
+        } else {
+            plugin.info("changes to " + configurationClass.getSimpleName());
+        }
+
+        processChanges(current, modified);
+    }
+
+    public void processChanges(List current, List modified) {
+        int modIndex = 0, currentIndex = 0;
+        for (; modIndex < modified.size() && currentIndex < current.size(); modIndex++, currentIndex++) {
+            // walk the list for mods
+            applyModifications(getContents(current.get(currentIndex)),
+                    getContents(modified.get(modIndex)));
+        }
+
+        for (; modIndex < modified.size(); modIndex++) {
+            // new element; add all
+            for (Object nc : getContents(modified.get(modIndex))) {
+                ConfigurationProcessor processor = findProcessor(nc);
+                if (processor != null) {
+                    processor.addNew(nc);
+                } else {
+                    addNew(nc);
+                }
+            }
+        }
+
+        for (; currentIndex < current.size(); currentIndex++) {
+            // removal of element; remove all
+            for (Object nc : getContents(current.get(currentIndex))) {
+                ConfigurationProcessor processor = findProcessor(nc);
+                if (processor != null) {
+                    processor.remove(nc);
+                } else {
+                    remove(nc);
+                }
+            }
+        }
+    }
+
+    protected void applyModifications(List<Object> current, List<Object> modification) {
+        int modIndex = 0, currentIndex = 0;
+        for (; modIndex < modification.size() && currentIndex < current.size(); modIndex++, currentIndex++) {
+            Object existing = current.get(currentIndex);
+            Object candidate = modification.get(modIndex);
+            if (!existing.equals(candidate)) {
+                plugin.info("modification to:" + existing + " , with: " + candidate);
+                ConfigurationProcessor processor = findProcessor(existing);
+                if (processor != null) {
+                    processor.modify(existing, candidate);
+                } else {
+                    modify(existing, candidate);
+                }
+            }
+        }
+        for (; modIndex < modification.size(); modIndex++) {
+            Object mod = modification.get(modIndex);
+            ConfigurationProcessor processor = findProcessor(mod);
+            if (processor != null) {
+                processor.addNew(mod);
+            } else {
+                addNew(mod);
+            }
+        }
+        for (; currentIndex < current.size(); currentIndex++) {
+            Object mod = current.get(currentIndex);
+            ConfigurationProcessor processor = findProcessor(mod);
+            if (processor != null) {
+                processor.remove(mod);
+            } else {
+                remove(mod);
+            }
+        }
+    }
+
+    public void modify(Object existing, Object candidate) {
+        remove(existing);
+        addNew(candidate);
+    }
+
+    public void addNew(Object o) {
+        plugin.info("No runtime support for additions of " + o);
+    }
+
+    public void remove(Object o) {
+        plugin.info("No runtime support for removal of: " + o);
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        plugin.info("No processor for " + o);
+        return null;
+    }
+
+    // mapping all supported updatable elements to support getContents
+    protected List<Object> getContents(Object o) {
+        List<Object> answer = new ArrayList<Object>();
+        try {
+            Object val = o.getClass().getMethod("getContents", new Class[]{}).invoke(o, new Object[]{});
+            if (val instanceof List) {
+                answer = (List<Object>) val;
+            } else {
+                answer.add(val);
+            }
+        } catch (NoSuchMethodException mappingIncomplete) {
+            plugin.debug(filterPasswords(o) + " has no modifiable elements");
+        } catch (Exception e) {
+            plugin.info("Failed to access getContents for " + o + ", runtime modifications not supported", e);
+        }
+        return answer;
+    }
+
+    protected String filterPasswords(Object toEscape) {
+        return matchPassword.matcher(toEscape.toString()).replaceAll("password=???,");
+    }
+
+    protected <T> List<Object> filter(Object obj, Class<T> type) {
+        return filter(getContents(obj), type);
+    }
+
+    protected <T> List<Object> filter(List<Object> objectList, Class<T> type) {
+        List<Object> result = new LinkedList<Object>();
+        for (Object o : objectList) {
+            if (o instanceof JAXBElement) {
+                JAXBElement element = (JAXBElement) o;
+                if (type.isAssignableFrom(element.getDeclaredType())) {
+                    result.add((T) element.getValue());
+                }
+            } else if (type.isAssignableFrom(o.getClass())) {
+                result.add((T) o);
+            }
+        }
+        return result;
+    }
+
+    protected <T> T fromDto(Object dto, T instance) {
+        Properties properties = new Properties();
+        IntrospectionSupport.getProperties(dto, properties, null);
+        plugin.placeHolderUtil.filter(properties);
+        LOG.trace("applying props: " + filterPasswords(properties) + ", to " + instance.getClass().getSimpleName());
+        IntrospectionSupport.setProperties(instance, properties);
+
+        // deal with nested elements
+        for (Object nested : filter(dto, Object.class)) {
+            String elementName = nested.getClass().getSimpleName();
+            Method setter = JAXBUtils.findSetter(instance, elementName);
+            if (setter != null) {
+                List<Object> argument = new LinkedList<Object>();
+                for (Object elementContent : filter(nested, Object.class)) {
+                    argument.add(fromDto(elementContent, JAXBUtils.inferTargetObject(elementContent)));
+                }
+                try {
+                    setter.invoke(instance, JAXBUtils.matchType(argument, setter.getParameterTypes()[0]));
+                } catch (Exception e) {
+                    plugin.info("failed to invoke " + setter + " on " + instance, e);
+                }
+            } else {
+                plugin.info("failed to find setter for " + elementName + " on :" + instance);
+            }
+        }
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationInterceptorProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationInterceptorProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationInterceptorProcessor.java
new file mode 100644
index 0000000..b98b34e
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationInterceptorProcessor.java
@@ -0,0 +1,34 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.schema.core.DtoVirtualDestinationInterceptor;
+
+public class DestinationInterceptorProcessor extends DefaultConfigurationProcessor {
+
+    public DestinationInterceptorProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        if (o instanceof DtoVirtualDestinationInterceptor) {
+            return new VirtualDestinationInterceptorProcessor(plugin, o.getClass());
+        }
+        return super.findProcessor(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationPolicyProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationPolicyProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationPolicyProcessor.java
new file mode 100644
index 0000000..3e59610
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationPolicyProcessor.java
@@ -0,0 +1,37 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.schema.core.DtoPolicyEntry;
+import org.apache.activemq.schema.core.DtoPolicyMap;
+
+public class DestinationPolicyProcessor extends DefaultConfigurationProcessor {
+
+    public DestinationPolicyProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        if (o instanceof DtoPolicyEntry) {
+            return new PolicyEntryProcessor(plugin, o.getClass());
+        } else if (o instanceof DtoPolicyMap) {
+            return new PolicyMapProcessor(plugin, o.getClass());
+        }
+        return super.findProcessor(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationsProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationsProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationsProcessor.java
new file mode 100644
index 0000000..b0e737c
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/DestinationsProcessor.java
@@ -0,0 +1,76 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.command.ActiveMQDestination;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.command.ActiveMQTopic;
+
+import org.apache.activemq.schema.core.DtoQueue;
+import org.apache.activemq.schema.core.DtoTopic;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DestinationsProcessor extends DefaultConfigurationProcessor {
+
+    public DestinationsProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public void processChanges(List current, List modified) {
+        for (Object destinations : modified) {
+            for (Object dto : getContents(destinations)) {
+                try {
+                    ActiveMQDestination destination = createDestination(dto);
+                    if (!containsDestination(destination)) {
+                        plugin.addDestination(plugin.getBrokerService().getAdminConnectionContext(), destination, true);
+                        plugin.info("Added destination " + destination);
+                    }
+                } catch (Exception e) {
+                    plugin.info("Failed to add a new destination for DTO: " + dto, e);
+                }
+            }
+        }
+    }
+
+    protected boolean containsDestination(ActiveMQDestination destination) throws Exception {
+        return Arrays.asList(plugin.getBrokerService().getRegionBroker().getDestinations()).contains(destination);
+    }
+
+    @Override
+    public void addNew(Object o) {
+        try {
+            ActiveMQDestination destination = createDestination(o);
+            plugin.addDestination(plugin.getBrokerService().getAdminConnectionContext(), destination, true);
+            plugin.info("Added destination " + destination);
+        } catch (Exception e) {
+            plugin.info("Failed to add a new destination for DTO: " + o, e);
+        }
+    }
+
+    private ActiveMQDestination createDestination(Object dto) throws Exception {
+        if (dto instanceof DtoQueue) {
+            return new ActiveMQQueue(((DtoQueue) dto).getPhysicalName());
+        } else if (dto instanceof DtoTopic) {
+            return new ActiveMQTopic(((DtoTopic) dto).getPhysicalName());
+        } else {
+            throw new Exception("Unknown destination type for DTO " + dto);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/JAXBUtils.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/JAXBUtils.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/JAXBUtils.java
new file mode 100644
index 0000000..2d0d54d
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/JAXBUtils.java
@@ -0,0 +1,65 @@
+/**
+ * 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.activemq.plugin;
+
+import javax.xml.bind.JAXBElement;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.command.ActiveMQTopic;
+import org.apache.activemq.schema.core.DtoTopic;
+import org.apache.activemq.schema.core.DtoQueue;
+import org.apache.activemq.schema.core.DtoAuthenticationUser;
+import org.apache.activemq.security.AuthenticationUser;
+
+public class JAXBUtils {
+
+    public static Method findSetter(Object instance, String elementName) {
+        String setter = "set" + elementName;
+        for (Method m : instance.getClass().getMethods()) {
+            if (setter.equals(m.getName())) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    public static Object inferTargetObject(Object elementContent) {
+        if (DtoTopic.class.isAssignableFrom(elementContent.getClass())) {
+            return new ActiveMQTopic();
+        } else if (DtoQueue.class.isAssignableFrom(elementContent.getClass())) {
+            return new ActiveMQQueue();
+        } else if (DtoAuthenticationUser.class.isAssignableFrom(elementContent.getClass())) {
+            return new AuthenticationUser();
+        } else {
+            return new Object();
+        }
+    }
+
+    public static Object matchType(List<Object> parameterValues, Class<?> aClass) {
+        Object result = parameterValues;
+        if (Set.class.isAssignableFrom(aClass)) {
+            result = new HashSet(parameterValues);
+        }
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java
new file mode 100644
index 0000000..a761d5b
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorProcessor.java
@@ -0,0 +1,80 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.network.DiscoveryNetworkConnector;
+import org.apache.activemq.network.NetworkConnector;
+import org.apache.activemq.schema.core.DtoNetworkConnector;
+import org.apache.activemq.util.IntrospectionSupport;
+
+import java.util.TreeMap;
+
+public class NetworkConnectorProcessor extends DefaultConfigurationProcessor {
+
+    public NetworkConnectorProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public void addNew(Object o) {
+        DtoNetworkConnector networkConnector = (DtoNetworkConnector) o;
+        if (networkConnector.getUri() != null) {
+            try {
+                DiscoveryNetworkConnector nc = fromDto(networkConnector, new DiscoveryNetworkConnector());
+                plugin.getBrokerService().addNetworkConnector(nc);
+                nc.start();
+                plugin.info("started new network connector: " + nc);
+            } catch (Exception e) {
+                plugin.info("Failed to add new networkConnector " + networkConnector, e);
+            }
+        }
+    }
+
+    @Override
+    public void remove(Object o) {
+        DtoNetworkConnector toRemove = (DtoNetworkConnector) o;
+        for (NetworkConnector existingCandidate :
+                plugin.getBrokerService().getNetworkConnectors()) {
+            if (configMatch(toRemove, existingCandidate)) {
+                if (plugin.getBrokerService().removeNetworkConnector(existingCandidate)) {
+                    try {
+                        existingCandidate.stop();
+                        plugin.info("stopped and removed networkConnector: " + existingCandidate);
+                    } catch (Exception e) {
+                        plugin.info("Failed to stop removed network connector: " + existingCandidate);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean configMatch(DtoNetworkConnector dto, NetworkConnector candidate) {
+        TreeMap<String, String> dtoProps = new TreeMap<String, String>();
+        IntrospectionSupport.getProperties(dto, dtoProps, null);
+
+        TreeMap<String, String> candidateProps = new TreeMap<String, String>();
+        IntrospectionSupport.getProperties(candidate, candidateProps, null);
+
+        // every dto prop must be present in the candidate
+        for (String key : dtoProps.keySet()) {
+            if (!candidateProps.containsKey(key) || !candidateProps.get(key).equals(dtoProps.get(key))) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorsProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorsProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorsProcessor.java
new file mode 100644
index 0000000..ed429b4
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/NetworkConnectorsProcessor.java
@@ -0,0 +1,34 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.schema.core.DtoNetworkConnector;
+
+public class NetworkConnectorsProcessor extends DefaultConfigurationProcessor {
+
+    public NetworkConnectorsProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        if (o instanceof DtoNetworkConnector) {
+            return new NetworkConnectorProcessor(plugin, o.getClass());
+        }
+        return super.findProcessor(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PluginsProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PluginsProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PluginsProcessor.java
new file mode 100644
index 0000000..180a8ce
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PluginsProcessor.java
@@ -0,0 +1,37 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.schema.core.DtoSimpleAuthenticationPlugin;
+import org.apache.activemq.schema.core.DtoAuthorizationPlugin;
+
+public class PluginsProcessor extends DefaultConfigurationProcessor {
+
+    public PluginsProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        if (o instanceof DtoSimpleAuthenticationPlugin) {
+            return new SimpleAuthenticationPluginProcessor(plugin, o.getClass());
+        } else if (o instanceof DtoAuthorizationPlugin) {
+            return new AuthorizationPluginProcessor(plugin, o.getClass());
+        }
+        return super.findProcessor(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyEntryProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyEntryProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyEntryProcessor.java
new file mode 100644
index 0000000..4d0dc42
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyEntryProcessor.java
@@ -0,0 +1,71 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.broker.region.*;
+import org.apache.activemq.broker.region.policy.PolicyEntry;
+import org.apache.activemq.broker.region.policy.PolicyMap;
+
+import java.util.Set;
+
+public class PolicyEntryProcessor extends DefaultConfigurationProcessor {
+
+    public PolicyEntryProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public void addNew(Object o) {
+        PolicyEntry addition = fromDto(o, new PolicyEntry());
+        PolicyMap existingMap = plugin.getBrokerService().getDestinationPolicy();
+        existingMap.put(addition.getDestination(), addition);
+        applyRetrospectively(addition);
+        plugin.info("added policy for: " + addition.getDestination());
+    }
+
+    @Override
+    public void modify(Object existing, Object candidate) {
+        PolicyMap existingMap = plugin.getBrokerService().getDestinationPolicy();
+
+        PolicyEntry updatedEntry = fromDto(candidate, new PolicyEntry());
+
+        Set existingEntry = existingMap.get(updatedEntry.getDestination());
+        if (existingEntry.size() == 1) {
+            updatedEntry = fromDto(candidate, (PolicyEntry) existingEntry.iterator().next());
+            applyRetrospectively(updatedEntry);
+            plugin.info("updated policy for: " + updatedEntry.getDestination());
+        } else {
+            plugin.info("cannot modify policy matching multiple destinations: " + existingEntry + ", destination:" + updatedEntry.getDestination());
+        }
+    }
+
+    protected void applyRetrospectively(PolicyEntry updatedEntry) {
+        RegionBroker regionBroker = (RegionBroker) plugin.getBrokerService().getRegionBroker();
+        for (Destination destination : regionBroker.getDestinations(updatedEntry.getDestination())) {
+            Destination target = destination;
+            if (destination instanceof DestinationFilter) {
+                target = ((DestinationFilter)destination).getNext();
+            }
+            if (target.getActiveMQDestination().isQueue()) {
+                updatedEntry.update((Queue) target);
+            } else if (target.getActiveMQDestination().isTopic()) {
+                updatedEntry.update((Topic) target);
+            }
+            plugin.debug("applied update to:" + target);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyMapProcessor.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyMapProcessor.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyMapProcessor.java
new file mode 100644
index 0000000..150542b
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PolicyMapProcessor.java
@@ -0,0 +1,44 @@
+/**
+ * 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.activemq.plugin;
+
+import java.util.List;
+import org.apache.activemq.schema.core.DtoPolicyMap;
+import org.apache.activemq.schema.core.DtoPolicyEntry;
+
+public class PolicyMapProcessor extends DefaultConfigurationProcessor {
+
+    public PolicyMapProcessor(RuntimeConfigurationBroker plugin, Class configurationClass) {
+        super(plugin, configurationClass);
+    }
+
+    @Override
+    public void modify(Object existing, Object candidate) {
+        List<Object> existingEntries = filter(existing, DtoPolicyMap.PolicyEntries.class);
+        List<Object> candidateEntries = filter(candidate, DtoPolicyMap.PolicyEntries.class);
+        // walk the map for mods
+        applyModifications(getContents(existingEntries.get(0)), getContents(candidateEntries.get(0)));
+    }
+
+    @Override
+    public ConfigurationProcessor findProcessor(Object o) {
+        if (o instanceof DtoPolicyEntry) {
+            return new PolicyEntryProcessor(plugin, o.getClass());
+        }
+        return super.findProcessor(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ProcessorFactory.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ProcessorFactory.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ProcessorFactory.java
new file mode 100644
index 0000000..e034cd9
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/ProcessorFactory.java
@@ -0,0 +1,39 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.schema.core.DtoBroker;
+
+public class ProcessorFactory {
+
+    public static ConfigurationProcessor createProcessor(RuntimeConfigurationBroker plugin, Class dtoClass) {
+        if (dtoClass.equals(DtoBroker.Plugins.class)) {
+            return new PluginsProcessor(plugin, dtoClass);
+        } else if (dtoClass.equals(DtoBroker.NetworkConnectors.class)) {
+            return new NetworkConnectorsProcessor(plugin, dtoClass);
+        } else if (dtoClass.equals(DtoBroker.DestinationPolicy.class)) {
+            return new DestinationPolicyProcessor(plugin, dtoClass);
+        } else if (dtoClass.equals(DtoBroker.DestinationInterceptors.class)) {
+            return new DestinationInterceptorProcessor(plugin, dtoClass);
+        } else if (dtoClass.equals(DtoBroker.Destinations.class)) {
+            return new DestinationsProcessor(plugin, dtoClass);
+        } else {
+            return new DefaultConfigurationProcessor(plugin, dtoClass);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/bbc039fc/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PropertiesPlaceHolderUtil.java
----------------------------------------------------------------------
diff --git a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PropertiesPlaceHolderUtil.java b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PropertiesPlaceHolderUtil.java
new file mode 100644
index 0000000..fdfe006
--- /dev/null
+++ b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/PropertiesPlaceHolderUtil.java
@@ -0,0 +1,183 @@
+/**
+ * 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.activemq.plugin;
+
+import org.apache.activemq.broker.BrokerContext;
+import org.apache.activemq.spring.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.core.io.Resource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PropertiesPlaceHolderUtil {
+
+    public static final Logger LOG = LoggerFactory.getLogger(PropertiesPlaceHolderUtil.class);
+
+    static final Pattern pattern = Pattern.compile("\\$\\{([^\\}]+)\\}");
+    final Properties properties;
+
+    public PropertiesPlaceHolderUtil(Properties properties) {
+        this.properties = properties;
+    }
+
+    public void filter(Properties toFilter) {
+        for (Map.Entry<Object, Object> entry : toFilter.entrySet()) {
+            String val = (String) entry.getValue();
+            String newVal = filter(val);
+            if (!val.equals(newVal)) {
+                toFilter.put(entry.getKey(), newVal);
+            }
+        }
+    }
+
+    public String filter(String str) {
+        int start = 0;
+        while (true) {
+            Matcher matcher = pattern.matcher(str);
+            if (!matcher.find(start)) {
+                break;
+            }
+            String group = matcher.group(1);
+            String property = properties.getProperty(group);
+            if (property != null) {
+                str = matcher.replaceFirst(Matcher.quoteReplacement(property));
+            } else {
+                start = matcher.end();
+            }
+        }
+        return replaceBytePostfix(str);
+    }
+
+    static Pattern[] byteMatchers = new Pattern[] {
+            Pattern.compile("^\\s*(\\d+)\\s*(b)?\\s*$", Pattern.CASE_INSENSITIVE),
+            Pattern.compile("^\\s*(\\d+)\\s*k(b)?\\s*$", Pattern.CASE_INSENSITIVE),
+            Pattern.compile("^\\s*(\\d+)\\s*m(b)?\\s*$", Pattern.CASE_INSENSITIVE),
+            Pattern.compile("^\\s*(\\d+)\\s*g(b)?\\s*$", Pattern.CASE_INSENSITIVE)};
+
+    // xbean can Xb, Xkb, Xmb, Xg etc
+    private String replaceBytePostfix(String str) {
+        try {
+            for (int i=0; i< byteMatchers.length; i++) {
+                Matcher matcher = byteMatchers[i].matcher(str);
+                if (matcher.matches()) {
+                    long value = Long.parseLong(matcher.group(1));
+                    for (int j=1; j<=i; j++) {
+                        value *= 1024;
+                    }
+                    return String.valueOf(value);
+                }
+            }
+        } catch (NumberFormatException ignored) {
+            LOG.debug("nfe on: " + str, ignored);
+        }
+        return str;
+    }
+
+    public void mergeProperties(Document doc, Properties initialProperties, BrokerContext brokerContext) {
+        // find resources
+        //        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+        //            <property name="locations" || name="properties">
+        //              ...
+        //            </property>
+        //          </bean>
+        LinkedList<String> resources = new LinkedList<String>();
+        LinkedList<String> propertiesClazzes = new LinkedList<String>();
+        NodeList beans = doc.getElementsByTagNameNS("*", "bean");
+        for (int i = 0; i < beans.getLength(); i++) {
+            Node bean = beans.item(0);
+            if (bean.hasAttributes() && bean.getAttributes().getNamedItem("class").getTextContent().contains("PropertyPlaceholderConfigurer")) {
+                if (bean.hasChildNodes()) {
+                    NodeList beanProps = bean.getChildNodes();
+                    for (int j = 0; j < beanProps.getLength(); j++) {
+                        Node beanProp = beanProps.item(j);
+                        if (Node.ELEMENT_NODE == beanProp.getNodeType() && beanProp.hasAttributes() && beanProp.getAttributes().getNamedItem("name") != null) {
+                            String propertyName = beanProp.getAttributes().getNamedItem("name").getTextContent();
+                            if ("locations".equals(propertyName)) {
+
+                                // interested in value or list/value of locations property
+                                Element beanPropElement = (Element) beanProp;
+                                NodeList values = beanPropElement.getElementsByTagNameNS("*", "value");
+                                for (int k = 0; k < values.getLength(); k++) {
+                                    Node value = values.item(k);
+                                    resources.add(value.getFirstChild().getTextContent());
+                                }
+                            } else if ("properties".equals(propertyName)) {
+
+                                // bean or beanFactory
+                                Element beanPropElement = (Element) beanProp;
+                                NodeList values = beanPropElement.getElementsByTagNameNS("*", "bean");
+                                for (int k = 0; k < values.getLength(); k++) {
+                                    Node value = values.item(k);
+                                    if (value.hasAttributes()) {
+                                        Node beanClassTypeNode = value.getAttributes().getNamedItem("class");
+                                        if (beanClassTypeNode != null) {
+                                            propertiesClazzes.add(beanClassTypeNode.getFirstChild().getTextContent());
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        for (String value : propertiesClazzes) {
+            try {
+                Object springBean = getClass().getClassLoader().loadClass(value).newInstance();
+                if (springBean instanceof FactoryBean) {
+                    // can't access the factory or created properties from spring context so we got to recreate
+                    initialProperties.putAll((Properties) FactoryBean.class.getMethod("getObject", (Class<?>[]) null).invoke(springBean));
+                }
+            } catch (Throwable e) {
+                LOG.debug("unexpected exception processing properties bean class: " + propertiesClazzes, e);
+            }
+        }
+        List<Resource> propResources = new LinkedList<Resource>();
+        for (String value : resources) {
+            try {
+                if (!value.isEmpty()) {
+                    propResources.add(Utils.resourceFromString(filter(value)));
+                }
+            } catch (MalformedURLException e) {
+                LOG.info("failed to resolve resource: " + value, e);
+            }
+        }
+        for (Resource resource : propResources) {
+            Properties properties = new Properties();
+            try {
+                properties.load(resource.getInputStream());
+            } catch (IOException e) {
+                LOG.info("failed to load properties resource: " + resource, e);
+            }
+            initialProperties.putAll(properties);
+        }
+    }
+
+}


Mime
View raw message