https://issues.apache.org/jira/browse/AMQ-4682 - use spring.schemas for spring.xsd resolution - use brokerContext for configurationurl, support property PropertyPlaceholderConfigurer locations and system prop replacement, nested networkConnector elements - excludedDestinations,dynamicallyIncludedDestinations etc. lists and sets of destination

This commit is contained in:
gtully 2013-09-03 00:28:46 +01:00
parent 2ea02bc8fb
commit 634a81898c
17 changed files with 492 additions and 46 deletions

View File

@ -27,6 +27,7 @@ public interface BrokerContext {
Object getBean(String name); Object getBean(String name);
public Map getBeansOfType(Class type); Map getBeansOfType(Class type);
String getConfigurationUrl();
} }

View File

@ -24,4 +24,5 @@ package org.apache.activemq.broker;
public interface BrokerContextAware { public interface BrokerContextAware {
void setBrokerContext(BrokerContext brokerContext); void setBrokerContext(BrokerContext brokerContext);
BrokerContext getBrokerContext();
} }

View File

@ -2948,12 +2948,4 @@ public class BrokerService implements Service {
public void setStoreOpenWireVersion(int storeOpenWireVersion) { public void setStoreOpenWireVersion(int storeOpenWireVersion) {
this.storeOpenWireVersion = storeOpenWireVersion; this.storeOpenWireVersion = storeOpenWireVersion;
} }
public String getConfigurationUrl() {
return configurationUrl;
}
public void setConfigurationUrl(String configurationUrl) {
this.configurationUrl = configurationUrl;
}
} }

View File

@ -17,16 +17,23 @@
package org.apache.activemq.plugin; package org.apache.activemq.plugin;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.management.JMException; import javax.management.JMException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
@ -42,6 +49,7 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema; import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory; import javax.xml.validation.SchemaFactory;
import org.apache.activemq.broker.Broker; import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerContext;
import org.apache.activemq.broker.BrokerFilter; import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext; import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.broker.jmx.ManagementContext; import org.apache.activemq.broker.jmx.ManagementContext;
@ -59,7 +67,10 @@ import org.apache.activemq.broker.region.virtual.VirtualDestination;
import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor; import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
import org.apache.activemq.broker.region.virtual.VirtualTopic; import org.apache.activemq.broker.region.virtual.VirtualTopic;
import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.apache.activemq.filter.DestinationMapEntry; import org.apache.activemq.filter.DestinationMapEntry;
import org.apache.activemq.network.DiscoveryNetworkConnector;
import org.apache.activemq.network.NetworkConnector; import org.apache.activemq.network.NetworkConnector;
import org.apache.activemq.plugin.jmx.RuntimeConfigurationView; import org.apache.activemq.plugin.jmx.RuntimeConfigurationView;
import org.apache.activemq.schema.core.DtoAuthorizationEntry; import org.apache.activemq.schema.core.DtoAuthorizationEntry;
@ -71,6 +82,8 @@ import org.apache.activemq.schema.core.DtoCompositeTopic;
import org.apache.activemq.schema.core.DtoNetworkConnector; import org.apache.activemq.schema.core.DtoNetworkConnector;
import org.apache.activemq.schema.core.DtoPolicyEntry; import org.apache.activemq.schema.core.DtoPolicyEntry;
import org.apache.activemq.schema.core.DtoPolicyMap; import org.apache.activemq.schema.core.DtoPolicyMap;
import org.apache.activemq.schema.core.DtoQueue;
import org.apache.activemq.schema.core.DtoTopic;
import org.apache.activemq.schema.core.DtoVirtualDestinationInterceptor; import org.apache.activemq.schema.core.DtoVirtualDestinationInterceptor;
import org.apache.activemq.schema.core.DtoVirtualTopic; import org.apache.activemq.schema.core.DtoVirtualTopic;
import org.apache.activemq.security.AuthorizationBroker; import org.apache.activemq.security.AuthorizationBroker;
@ -82,9 +95,13 @@ import org.apache.activemq.spring.Utils;
import org.apache.activemq.util.IntrospectionSupport; import org.apache.activemq.util.IntrospectionSupport;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.xml.PluggableSchemaResolver;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
public class RuntimeConfigurationBroker extends BrokerFilter { public class RuntimeConfigurationBroker extends BrokerFilter {
@ -92,6 +109,7 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
public static final Logger LOG = LoggerFactory.getLogger(RuntimeConfigurationBroker.class); public static final Logger LOG = LoggerFactory.getLogger(RuntimeConfigurationBroker.class);
public static final String objectNamePropsAppendage = ",service=RuntimeConfiguration,name=Plugin"; public static final String objectNamePropsAppendage = ",service=RuntimeConfiguration,name=Plugin";
private final ReentrantReadWriteLock addDestinationBarrier = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock addDestinationBarrier = new ReentrantReadWriteLock();
PropertiesPlaceHolderUtil placeHolderUtil = null;
private long checkPeriod; private long checkPeriod;
private long lastModified = -1; private long lastModified = -1;
private Resource configToMonitor; private Resource configToMonitor;
@ -110,7 +128,12 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
public void start() throws Exception { public void start() throws Exception {
super.start(); super.start();
try { try {
configToMonitor = Utils.resourceFromString(next.getBrokerService().getConfigurationUrl()); BrokerContext brokerContext = next.getBrokerService().getBrokerContext();
if (brokerContext != null) {
configToMonitor = Utils.resourceFromString(brokerContext.getConfigurationUrl());
} else {
LOG.error("Null BrokerContext; impossible to determine configuration url resource from broker, updates cannot be tracked");
}
} catch (Exception error) { } catch (Exception error) {
LOG.error("failed to determine configuration url resource from broker, updates cannot be tracked", error); LOG.error("failed to determine configuration url resource from broker, updates cannot be tracked", error);
} }
@ -461,13 +484,8 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
DtoNetworkConnector networkConnector = (DtoNetworkConnector) o; DtoNetworkConnector networkConnector = (DtoNetworkConnector) o;
if (networkConnector.getUri() != null) { if (networkConnector.getUri() != null) {
try { try {
NetworkConnector nc = DiscoveryNetworkConnector nc = fromDto(networkConnector, new DiscoveryNetworkConnector());
getBrokerService().addNetworkConnector(networkConnector.getUri()); getBrokerService().addNetworkConnector(nc);
Properties properties = new Properties();
IntrospectionSupport.getProperties(networkConnector, properties, null);
properties.remove("uri");
LOG.trace("applying networkConnector props: " + properties);
IntrospectionSupport.setProperties(nc, properties);
nc.start(); nc.start();
info("started new network connector: " + nc); info("started new network connector: " + nc);
} catch (Exception e) { } catch (Exception e) {
@ -545,11 +563,65 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
private <T> T fromDto(Object dto, T instance) { private <T> T fromDto(Object dto, T instance) {
Properties properties = new Properties(); Properties properties = new Properties();
IntrospectionSupport.getProperties(dto, properties, null); IntrospectionSupport.getProperties(dto, properties, null);
replacePlaceHolders(properties);
LOG.trace("applying props: " + properties + ", to " + instance.getClass().getSimpleName()); LOG.trace("applying props: " + properties + ", to " + instance.getClass().getSimpleName());
IntrospectionSupport.setProperties(instance, properties); IntrospectionSupport.setProperties(instance, properties);
// deal with nested elements
for (Object nested : filter(dto, Object.class)) {
String elementName = nested.getClass().getSimpleName();
if (elementName.endsWith("s")) {
Method setter = findSetter(instance, elementName);
if (setter != null) {
List<Object> argument = new LinkedList<Object>();
for (Object elementContent : filter(nested, Object.class)) {
argument.add(fromDto(elementContent, inferTargetObject(elementContent)));
}
try {
setter.invoke(instance, matchType(argument, setter.getParameterTypes()[0]));
} catch (Exception e) {
info("failed to invoke " + setter + " on " + instance, e);
}
} else {
info("failed to find setter for " + elementName + " on :" + instance);
}
} else {
info("unsupported mapping of element for non plural:" + elementName);
}
}
return instance; return instance;
} }
private Object matchType(List<Object> parameterValues, Class<?> aClass) {
Object result = parameterValues;
if (Set.class.isAssignableFrom(aClass)) {
result = new HashSet(parameterValues);
}
return result;
}
private Object inferTargetObject(Object elementContent) {
if (DtoTopic.class.isAssignableFrom(elementContent.getClass())) {
return new ActiveMQTopic();
} else if (DtoQueue.class.isAssignableFrom(elementContent.getClass())) {
return new ActiveMQQueue();
} else {
info("update not supported for dto: " + elementContent);
return new Object();
}
}
private 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;
}
private <T> List<Object> filter(Object obj, Class<T> type) { private <T> List<Object> filter(Object obj, Class<T> type) {
return filter(getContents(obj), type); return filter(getContents(obj), type);
} }
@ -559,7 +631,7 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
for (Object o : objectList) { for (Object o : objectList) {
if (o instanceof JAXBElement) { if (o instanceof JAXBElement) {
JAXBElement element = (JAXBElement) o; JAXBElement element = (JAXBElement) o;
if (element.getDeclaredType() == type) { if (type.isAssignableFrom(element.getDeclaredType())) {
result.add((T) element.getValue()); result.add((T) element.getValue());
} }
} else if (type.isAssignableFrom(o.getClass())) { } else if (type.isAssignableFrom(o.getClass())) {
@ -591,6 +663,8 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
// if we can parse we can track mods // if we can parse we can track mods
lastModified = configToMonitor.lastModified(); lastModified = configToMonitor.lastModified();
loadPropertiesPlaceHolderSupport(doc);
} catch (IOException e) { } catch (IOException e) {
info("Failed to access: " + configToMonitor, e); info("Failed to access: " + configToMonitor, e);
} catch (JAXBException e) { } catch (JAXBException e) {
@ -604,20 +678,97 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
return jaxbConfig; return jaxbConfig;
} }
private Schema getSchema() throws SAXException { private void loadPropertiesPlaceHolderSupport(Document doc) {
BrokerContext brokerContext = getBrokerService().getBrokerContext();
if (brokerContext != null && !brokerContext.getBeansOfType(PropertyPlaceholderConfigurer.class).isEmpty()) {
Properties initialProperties = new Properties(System.getProperties());
placeHolderUtil = new PropertiesPlaceHolderUtil(initialProperties);
mergeProperties(doc, initialProperties);
}
}
private void mergeProperties(Document doc, Properties initialProperties) {
// find resources
// <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
// <property name="locations">
// <value>${props.base}users.properties</value>
// </property>
// </bean>
String resourcesString = null;
NodeList beans = doc.getElementsByTagName("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 (beanProp.hasAttributes() && beanProp.getAttributes().getNamedItem("name").getTextContent().equals("locations")) {
NodeList locationsPropNodes = beanProp.getChildNodes();
for (int k = 0; k < locationsPropNodes.getLength(); k++) {
Node location = locationsPropNodes.item(k);
if (Node.ELEMENT_NODE == location.getNodeType() && location.getLocalName().equals("value")) {
resourcesString = location.getFirstChild().getTextContent();
break;
}
}
}
}
}
}
}
List<Resource> propResources = new LinkedList<Resource>();
if (resourcesString != null) {
for (String value : resourcesString.split(",")) {
try {
propResources.add(Utils.resourceFromString(replacePlaceHolders(value)));
} catch (MalformedURLException e) {
info("failed to resolve resource: " + value, e);
}
}
}
for (Resource resource : propResources) {
Properties properties = new Properties();
try {
properties.load(resource.getInputStream());
} catch (IOException e) {
info("failed to load properties resource: " + resource, e);
}
initialProperties.putAll(properties);
}
}
private void replacePlaceHolders(Properties properties) {
if (placeHolderUtil != null) {
placeHolderUtil.filter(properties);
}
}
private String replacePlaceHolders(String s) {
if (placeHolderUtil != null) {
s = placeHolderUtil.filter(s);
}
return s;
}
private Schema getSchema() throws SAXException, IOException {
if (schema == null) { if (schema == null) {
// need to pull the spring schemas from the classpath and find reelvant
// constants for the system id etc something like ...
//PluggableSchemaResolver resolver =
// new PluggableSchemaResolver(getClass().getClassLoader());
//InputSource springBeans = resolver.resolveEntity("http://www.springframework.org/schema/beans",
// "http://www.springframework.org/schema/beans/spring-beans-2.0.xsd");
//LOG.trace("Beans schema:" + springBeans);
SchemaFactory schemaFactory = SchemaFactory.newInstance( SchemaFactory schemaFactory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI); XMLConstants.W3C_XML_SCHEMA_NS_URI);
schema = schemaFactory.newSchema(
new Source[]{new StreamSource(getClass().getResource("/activemq.xsd").toExternalForm()), // avoid going to the net to pull down the spring schema
new StreamSource("http://www.springframework.org/schema/beans/spring-beans-2.0.xsd")}); final PluggableSchemaResolver springResolver =
new PluggableSchemaResolver(getClass().getClassLoader());
final InputSource beanInputSource =
springResolver.resolveEntity(
"http://www.springframework.org/schema/beans",
"http://www.springframework.org/schema/beans/spring-beans-2.0.xsd");
schema = schemaFactory.newSchema(new Source[]{
new StreamSource(getClass().getResource("/activemq.xsd").toExternalForm()),
new StreamSource(beanInputSource.getByteStream())
});
} }
return schema; return schema;
} }
@ -637,4 +788,43 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
public void setCheckPeriod(long checkPeriod) { public void setCheckPeriod(long checkPeriod) {
this.checkPeriod = checkPeriod; this.checkPeriod = checkPeriod;
} }
static public class PropertiesPlaceHolderUtil {
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 str;
}
}
} }

View File

@ -19,6 +19,34 @@
<jxb:property name="Contents" /> <jxb:property name="Contents" />
</jxb:bindings> </jxb:bindings>
<jxb:bindings node="xs:element[@name='queue']/xs:complexType/xs:choice">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='topic']/xs:complexType/xs:choice">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='networkConnector']/xs:complexType/xs:choice">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='networkConnector']/xs:complexType/xs:choice/xs:choice/xs:element[@name='excludedDestinations']/xs:complexType/xs:sequence">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='networkConnector']/xs:complexType/xs:choice/xs:choice/xs:element[@name='dynamicallyIncludedDestinations']/xs:complexType/xs:sequence">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='networkConnector']/xs:complexType/xs:choice/xs:choice/xs:element[@name='durableDestinations']/xs:complexType/xs:sequence">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='networkConnector']/xs:complexType/xs:choice/xs:choice/xs:element[@name='staticallyIncludedDestinations']/xs:complexType/xs:sequence">
<jxb:property name="Contents" />
</jxb:bindings>
<jxb:bindings node="xs:element[@name='broker']/xs:complexType/xs:choice/xs:choice/xs:element[@name='destinationInterceptors']/xs:complexType/xs:choice"> <jxb:bindings node="xs:element[@name='broker']/xs:complexType/xs:choice/xs:choice/xs:element[@name='destinationInterceptors']/xs:complexType/xs:choice">
<jxb:property name="Contents" /> <jxb:property name="Contents" />
</jxb:bindings> </jxb:bindings>

View File

@ -59,7 +59,7 @@ public class MBeanTest extends RuntimeConfigTestSupport {
LOG.info("Result from update: " + result); LOG.info("Result from update: " + result);
assertTrue("got sensible result", result.contains("started")); assertTrue("got sensible result: " + result, result.contains("started"));
assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size()); assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size());
@ -72,7 +72,7 @@ public class MBeanTest extends RuntimeConfigTestSupport {
} }
@Test @Test
public void testUpdateFailedMod() throws Exception { public void testUpdateFailedModParseError() throws Exception {
final String brokerConfig = "mBeanTest-manual-broker"; final String brokerConfig = "mBeanTest-manual-broker";
applyNewConfig(brokerConfig, "emptyManualUpdateConfig"); applyNewConfig(brokerConfig, "emptyManualUpdateConfig");
startBroker(brokerConfig); startBroker(brokerConfig);
@ -96,7 +96,7 @@ public class MBeanTest extends RuntimeConfigTestSupport {
String result = runtimeConfigurationView.updateNow(); String result = runtimeConfigurationView.updateNow();
LOG.info("Result from failed update: " + result); LOG.info("Result from failed update: " + result);
assertTrue("got sensible result", result.contains("dudElement")); assertTrue("got sensible result: " + result, result.contains("dudElement"));
HashMap<String, String> propsAfter = new HashMap<String, String>(); HashMap<String, String> propsAfter = new HashMap<String, String>();
IntrospectionSupport.getProperties(runtimeConfigurationView, propsAfter, null); IntrospectionSupport.getProperties(runtimeConfigurationView, propsAfter, null);
@ -111,7 +111,7 @@ public class MBeanTest extends RuntimeConfigTestSupport {
result = runtimeConfigurationView.updateNow(); result = runtimeConfigurationView.updateNow();
LOG.info("Result from update: " + result); LOG.info("Result from update: " + result);
assertTrue("got sensible result", result.contains("started")); assertTrue("got sensible result: " + result, result.contains("started"));
assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size()); assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size());
propsAfter = new HashMap<String, String>(); propsAfter = new HashMap<String, String>();

View File

@ -16,6 +16,8 @@
*/ */
package org.apache.activemq; package org.apache.activemq;
import java.util.List;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.network.NetworkConnector; import org.apache.activemq.network.NetworkConnector;
import org.apache.activemq.util.Wait; import org.apache.activemq.util.Wait;
import org.junit.Before; import org.junit.Before;
@ -51,6 +53,14 @@ public class NetworkConnectorTest extends RuntimeConfigTestSupport {
applyNewConfig(brokerConfig, configurationSeed + "-one-nc"); applyNewConfig(brokerConfig, configurationSeed + "-one-nc");
assertEquals("no new network connectors", 1, brokerService.getNetworkConnectors().size()); assertEquals("no new network connectors", 1, brokerService.getNetworkConnectors().size());
assertSame("same instance", networkConnector, brokerService.getNetworkConnectors().get(0)); assertSame("same instance", networkConnector, brokerService.getNetworkConnectors().get(0));
// verify nested elements
assertEquals("has exclusions", 2, networkConnector.getExcludedDestinations().size());
assertEquals("one statically included", 1, networkConnector.getStaticallyIncludedDestinations().size());
assertEquals("one dynamically included", 1, networkConnector.getDynamicallyIncludedDestinations().size());
assertEquals("one durable", 1, networkConnector.getDurableDestinations().size());
} }

View File

@ -16,13 +16,14 @@
*/ */
package org.apache.activemq; package org.apache.activemq;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import javax.management.ObjectName; import javax.management.ObjectName;
import org.apache.activemq.network.DiscoveryNetworkConnector;
import org.apache.activemq.plugin.RuntimeConfigurationBroker; import org.apache.activemq.plugin.RuntimeConfigurationBroker;
import org.apache.activemq.plugin.jmx.RuntimeConfigurationViewMBean; import org.apache.activemq.plugin.jmx.RuntimeConfigurationViewMBean;
import org.apache.activemq.util.IntrospectionSupport; import org.apache.activemq.util.IntrospectionSupport;
import org.apache.activemq.util.Wait;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -31,8 +32,8 @@ import static org.junit.Assert.*;
public class SpringBeanTest extends RuntimeConfigTestSupport { public class SpringBeanTest extends RuntimeConfigTestSupport {
@Test @Test
public void testUpdateNow() throws Exception { public void testModifiable() throws Exception {
final String brokerConfig = "SpromgBeanTest-broker"; final String brokerConfig = "SpringBeanTest-broker";
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-bean"); applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-bean");
startBroker(brokerConfig); startBroker(brokerConfig);
assertTrue("broker alive", brokerService.isStarted()); assertTrue("broker alive", brokerService.isStarted());
@ -65,4 +66,54 @@ public class SpringBeanTest extends RuntimeConfigTestSupport {
assertEquals("modified is same", props.get(propOfInterest), propsAfter.get(propOfInterest)); assertEquals("modified is same", props.get(propOfInterest), propsAfter.get(propOfInterest));
} }
@Test
public void testAddPropertyRef() throws Exception {
System.setProperty("network.uri", "static:(tcp://localhost:8888)");
final String brokerConfig = "SpringPropertyTest-broker";
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property");
startBroker(brokerConfig);
assertTrue("broker alive", brokerService.isStarted());
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-nc", SLEEP);
assertTrue("new network connectors", Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisified() throws Exception {
return 1 == brokerService.getNetworkConnectors().size();
}
}));
DiscoveryNetworkConnector discoveryNetworkConnector =
(DiscoveryNetworkConnector) brokerService.getNetworkConnectors().get(0);
assertEquals("property replaced", System.getProperty("network.uri"), discoveryNetworkConnector.getUri().toASCIIString());
}
@Test
public void testAddPropertyRefFromFile() throws Exception {
System.setProperty("network.uri", "static:(tcp://localhost:8888)");
System.setProperty("props.base", "classpath:");
final String brokerConfig = "SpringPropertyTest-broker";
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-file");
startBroker(brokerConfig);
assertTrue("broker alive", brokerService.isStarted());
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-file-nc", SLEEP);
assertTrue("new network connectors", Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisified() throws Exception {
return 1 == brokerService.getNetworkConnectors().size();
}
}));
DiscoveryNetworkConnector discoveryNetworkConnector =
(DiscoveryNetworkConnector) brokerService.getNetworkConnectors().get(0);
assertEquals("property replaced", System.getProperty("network.uri"), discoveryNetworkConnector.getUri().toASCIIString());
assertEquals("name is replaced", "guest", discoveryNetworkConnector.getName());
}
} }

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>${props.base}users.properties</value>
</property>
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
<networkConnectors>
<networkConnector uri="${network.uri}" networkTTL="1" name="${guest}" />
</networkConnectors>
</broker>
</beans>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>${props.base}users.properties</value>
</property>
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
</broker>
</beans>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
<networkConnectors>
<networkConnector uri="${network.uri}" networkTTL="1" name="one" />
</networkConnectors>
</broker>
</beans>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
</broker>
</beans>

View File

@ -27,7 +27,21 @@
</plugins> </plugins>
<networkConnectors> <networkConnectors>
<networkConnector uri="static:(tcp://localhost:5555)" networkTTL="1" name="one" /> <networkConnector uri="static:(tcp://localhost:5555)" networkTTL="1" name="one" >
<excludedDestinations>
<topic physicalName="LAN.>"/>
<queue physicalName="LAN.>"/>
</excludedDestinations>
<dynamicallyIncludedDestinations>
<queue physicalName="DynamicallyIncluded.*" />
</dynamicallyIncludedDestinations>
<staticallyIncludedDestinations>
<topic physicalName="StaticallyIncluded.*" />
</staticallyIncludedDestinations>
<durableDestinations>
<topic physicalName="durableDest" />
</durableDestinations>
</networkConnector>
</networkConnectors> </networkConnectors>
</broker> </broker>
</beans> </beans>

View File

@ -26,6 +26,7 @@ import org.springframework.context.ApplicationContextAware;
public class SpringBrokerContext implements BrokerContext, ApplicationContextAware { public class SpringBrokerContext implements BrokerContext, ApplicationContextAware {
ApplicationContext applicationContext; ApplicationContext applicationContext;
String configurationUrl;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
@ -43,4 +44,11 @@ public class SpringBrokerContext implements BrokerContext, ApplicationContextAwa
return applicationContext.getBeansOfType(type); return applicationContext.getBeansOfType(type);
} }
public void setConfigurationUrl(String configurationUrl) {
this.configurationUrl = configurationUrl;
}
public String getConfigurationUrl() {
return configurationUrl;
}
} }

View File

@ -20,8 +20,10 @@ import java.beans.PropertyEditorManager;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import org.apache.activemq.broker.BrokerContextAware;
import org.apache.activemq.broker.BrokerFactoryHandler; import org.apache.activemq.broker.BrokerFactoryHandler;
import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.spring.SpringBrokerContext;
import org.apache.activemq.spring.Utils; import org.apache.activemq.spring.Utils;
import org.apache.activemq.util.IntrospectionSupport; import org.apache.activemq.util.IntrospectionSupport;
import org.apache.activemq.util.URISupport; import org.apache.activemq.util.URISupport;
@ -85,11 +87,10 @@ public class XBeanBrokerFactory implements BrokerFactoryHandler {
throw new IllegalArgumentException("The configuration has no BrokerService instance for resource: " + config); throw new IllegalArgumentException("The configuration has no BrokerService instance for resource: " + config);
} }
if (broker instanceof ApplicationContextAware) { SpringBrokerContext springBrokerContext = new SpringBrokerContext();
((ApplicationContextAware)broker).setApplicationContext(context); springBrokerContext.setApplicationContext(context);
} springBrokerContext.setConfigurationUrl(uri);
broker.setBrokerContext(springBrokerContext);
broker.setConfigurationUrl(uri);
// TODO warning resources from the context may not be closed down! // TODO warning resources from the context may not be closed down!

View File

@ -281,6 +281,11 @@ public class JmsFrameTranslator extends LegacyFrameTranslator implements
this.brokerContext = brokerContext; this.brokerContext = brokerContext;
} }
@Override
public BrokerContext getBrokerContext() {
return this.brokerContext;
}
/** /**
* Return an Advisory message as a JSON formatted string * Return an Advisory message as a JSON formatted string
* @param ds * @param ds

View File

@ -52,4 +52,9 @@ public class XStreamBrokerContext implements BrokerContext {
return null; return null;
} }
@Override
public String getConfigurationUrl() {
return null;
}
} }