https://issues.apache.org/jira/browse/AMQ-4821 - refix; we now use any referenced factorybean for default properties

This commit is contained in:
gtully 2013-10-24 22:08:36 +01:00
parent c2eb4863a8
commit da45d994ac
6 changed files with 185 additions and 26 deletions

View File

@ -157,6 +157,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
<argLine>-Xmx512M -Djava.awt.headless=true</argLine>
<systemProperties>
<property>
<name>org.apache.activemq.default.directory.prefix</name>

View File

@ -17,6 +17,7 @@
package org.apache.activemq.plugin;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.ArrayList;
@ -94,6 +95,8 @@ import org.apache.activemq.spring.Utils;
import org.apache.activemq.util.IntrospectionSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.xml.PluggableSchemaResolver;
import org.springframework.core.io.Resource;
@ -694,19 +697,20 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
if (brokerContext != null) {
Properties initialProperties = new Properties(System.getProperties());
placeHolderUtil = new PropertiesPlaceHolderUtil(initialProperties);
mergeProperties(doc, initialProperties);
mergeProperties(doc, initialProperties, brokerContext);
}
}
private void mergeProperties(Document doc, Properties initialProperties) {
private void mergeProperties(Document doc, Properties initialProperties, BrokerContext brokerContext) {
// find resources
// <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
// <property name="locations">
// <property name="locations" || name="properties">
// ...
// </property>
// </bean>
String resourcesString = "";
NodeList beans = doc.getElementsByTagName("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")) {
@ -714,26 +718,50 @@ public class RuntimeConfigurationBroker extends BrokerFilter {
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").getTextContent().equals("locations")) {
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.getElementsByTagName("value");
for (int k = 0; k < values.getLength(); k++) {
Node value = values.item(k);
if (!resourcesString.isEmpty()) {
resourcesString += ",";
// 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());
}
}
}
resourcesString += value.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", 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 : resourcesString.split(",")) {
for (String value : resources) {
try {
if (!value.isEmpty()) {
propResources.add(Utils.resourceFromString(replacePlaceHolders(value)));

View File

@ -20,9 +20,14 @@ import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
public class CustomPropertiesBean implements FactoryBean<Properties> {
Properties properties = new Properties();
public CustomPropertiesBean() {
properties.put("custom", "isKing");
}
@Override
public Properties getObject() throws Exception {
return System.getProperties();
return properties;
}
@Override

View File

@ -127,20 +127,59 @@ public class SpringBeanTest extends RuntimeConfigTestSupport {
assertTrue("broker alive", brokerService.isStarted());
ObjectName objectName =
new ObjectName(brokerService.getBrokerObjectName().toString() +
RuntimeConfigurationBroker.objectNamePropsAppendage);
RuntimeConfigurationViewMBean runtimeConfigurationView =
(RuntimeConfigurationViewMBean) brokerService.getManagementContext().newProxyInstance(objectName,
RuntimeConfigurationViewMBean.class, false);
new ObjectName(brokerService.getBrokerObjectName().toString() +
RuntimeConfigurationBroker.objectNamePropsAppendage);
RuntimeConfigurationViewMBean runtimeConfigurationView =
(RuntimeConfigurationViewMBean) brokerService.getManagementContext().newProxyInstance(objectName,
RuntimeConfigurationViewMBean.class, false);
String propOfInterest = "modified";
HashMap<String, String> props = new HashMap<String, String>();
IntrospectionSupport.getProperties(runtimeConfigurationView, props, null);
LOG.info("mbean attributes before: " + props);
String propOfInterest = "modified";
HashMap<String, String> props = new HashMap<String, String>();
IntrospectionSupport.getProperties(runtimeConfigurationView, props, null);
LOG.info("mbean attributes before: " + props);
assertNotEquals("unknown", props.get(propOfInterest));
}
@Test
public void testAddPropertyRefFromFileAndBeanFactory() throws Exception {
System.setProperty("network.uri", "static:(tcp://localhost:8888)");
System.setProperty("props.base", "classpath:");
final String brokerConfig = "SpringPropertyTestFileListBeanFactory-broker";
applyNewConfig(brokerConfig, "emptyUpdatableConfig1000-spring-property-file-list-and-beanFactory");
startBroker(brokerConfig);
assertTrue("broker alive", brokerService.isStarted());
ObjectName objectName =
new ObjectName(brokerService.getBrokerObjectName().toString() +
RuntimeConfigurationBroker.objectNamePropsAppendage);
RuntimeConfigurationViewMBean runtimeConfigurationView =
(RuntimeConfigurationViewMBean) brokerService.getManagementContext().newProxyInstance(objectName,
RuntimeConfigurationViewMBean.class, false);
String propOfInterest = "modified";
HashMap<String, String> props = new HashMap<String, String>();
IntrospectionSupport.getProperties(runtimeConfigurationView, props, null);
LOG.info("mbean attributes before: " + props);
assertNotEquals("unknown", props.get(propOfInterest));
assertEquals("our custom prop is applied", "isKing", brokerService.getBrokerName());
applyNewConfig(brokerConfig, "spring-property-file-list-and-beanFactory-new-nc", SLEEP);
assertTrue("new network connectors", Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisified() throws Exception {
return 1 == brokerService.getNetworkConnectors().size();
}
}));
assertEquals("our custom prop is applied", "isKing", brokerService.getNetworkConnectors().get(0).getName());
}
}

View File

@ -0,0 +1,41 @@
<?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">
<list>
<value>${props.base}users.properties</value>
<value>${props.base}users.properties</value>
</list>
</property>
<property name="properties">
<bean class="org.apache.activemq.CustomPropertiesBean"/>
</property>
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" brokerName="${custom}">
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
</broker>
</beans>

View File

@ -0,0 +1,45 @@
<?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">
<list>
<value>${props.base}users.properties</value>
<value>${props.base}users.properties</value>
</list>
</property>
<property name="properties">
<bean class="org.apache.activemq.CustomPropertiesBean"/>
</property>
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" brokerName="${custom}">
<plugins>
<runtimeConfigurationPlugin checkPeriod="1000" />
</plugins>
<networkConnectors>
<networkConnector uri="${network.uri}" networkTTL="1" name="${custom}" />
</networkConnectors>
</broker>
</beans>