return (T) context.getBean(name);
}
+ public <T> T getAntRef(String antId) {
+ return (T) project.getReference(antId);
+ }
+
public SlcExecution getSlcExecution() {
return (SlcExecution) project
.getReference(AntConstants.REF_SLC_EXECUTION);
\r
// set overridden references\r
if (distributionArg != null) {\r
- deployment.setDistribution(distributionArg.getBeanInstance());\r
+ deployment.setDistribution(distributionArg.getInstance());\r
log.trace("Overrides distribution");\r
}\r
\r
if (deploymentDataArg != null) {\r
- deployment.setDeploymentData(deploymentDataArg.getBeanInstance());\r
+ deployment.setDeploymentData(deploymentDataArg.getInstance());\r
log.trace("Overrides deployment data");\r
}\r
\r
if (targetDataArg != null) {\r
- deployment.setTargetData(targetDataArg.getBeanInstance());\r
+ deployment.setTargetData(targetDataArg.getInstance());\r
log.trace("Overrides target data");\r
}\r
\r
--- /dev/null
+package org.argeo.slc.ant.spring;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.argeo.slc.core.SlcException;
+
+/** List of overrides */
+public class ListArg {
+ private List<OverrideArg> list = new Vector<OverrideArg>();
+
+ /** Creates override sub tag. */
+ public OverrideArg createOverride() {
+ OverrideArg overrideArg = new OverrideArg();
+ list.add(overrideArg);
+ return overrideArg;
+ }
+
+ /** Gets as list of objects. */
+ public List<Object> getAsObjectList(List<Object> originalList) {
+ if (originalList != null && originalList.size() != list.size()) {
+ throw new SlcException("Cannot merge lists of different sizes.");
+ }
+
+ List<Object> objectList = new Vector<Object>(list.size());
+
+ for (int i = 0; i < list.size(); i++) {
+ OverrideArg arg = list.get(i);
+
+ if (originalList != null)
+ arg.setOriginal(originalList.get(i));
+
+ objectList.add(arg.getObject());
+ }
+ return objectList;
+ }
+}
return arg;\r
}\r
\r
- public Map<String, Object> getMap() {\r
- if (map.size() == 0) {\r
- for (EntryArg arg : entries) {\r
- String key = arg.getKey();\r
- if (map.containsKey(key)) {\r
- throw new SlcException("Key '" + key + "' already set.");\r
- } else {\r
- map.put(key, arg.getValueStr());\r
- }\r
+ public Map<String, Object> getAsObjectMap(Map<String, Object> originalMap) {\r
+ Map<String, Object> objectMap = new TreeMap<String, Object>();\r
+ for (EntryArg arg : entries) {\r
+ String key = arg.getKey();\r
+\r
+ if (objectMap.containsKey(key)) {\r
+ throw new SlcException("Key '" + key + "' already set.");\r
}\r
+\r
+ if (originalMap != null && originalMap.containsKey(key)\r
+ && arg.getOverrideArg() != null)\r
+ arg.getOverrideArg().setOriginal(originalMap.get(key));\r
+\r
+ objectMap.put(key, arg.getObject());\r
+\r
}\r
+ return objectMap;\r
+ }\r
+\r
+ /**\r
+ * Returns a cached reference if it was already called. This reference could\r
+ * have been modified externally and thus not anymore be in line with the\r
+ * configuration.\r
+ */\r
+ public Map<String, Object> getMap() {\r
+ if (map.size() == 0)\r
+ map = getAsObjectMap(null);\r
return map;\r
}\r
\r
this.key = key;\r
}\r
\r
- public Object getValueStr() {\r
+ public Object getObject() {\r
if (overrideArg != null) {\r
return overrideArg.getObject();\r
} else if (valueStr != null) {\r
throw new BuildException("Value already set");\r
}\r
}\r
+\r
+ public OverrideArg getOverrideArg() {\r
+ return overrideArg;\r
+ }\r
+\r
}\r
}\r
package org.argeo.slc.ant.spring;\r
\r
import java.util.List;\r
-import java.util.Vector;\r
+import java.util.Map;\r
\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
import org.apache.tools.ant.BuildException;\r
\r
/** Ant type allowing to override bean properties. */\r
public class OverrideArg extends SpringArg<Object> {\r
+ private final static Log log = LogFactory.getLog(OverrideArg.class);\r
+\r
private String name;\r
private Object value;\r
- private OverrideList overrideList;\r
+ private ListArg overrideList;\r
private MapArg overrideMap;\r
\r
+ private Boolean merge = false;\r
+\r
/** The name of the property to override. */\r
public String getName() {\r
return name;\r
}\r
\r
/** Creates override list sub tag. */\r
- public OverrideList createList() {\r
+ public ListArg createList() {\r
checkValueAlreadySet();\r
- overrideList = new OverrideList();\r
+ overrideList = new ListArg();\r
return overrideList;\r
}\r
\r
*/\r
public Object getObject() {\r
if (value != null) {\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Returns override object as value");\r
return value;\r
- } else if (getBean() != null || getAntref() != null) {\r
- return getBeanInstance();\r
+ } else if (getBean() != null\r
+ || getAntref() != null\r
+ // works on original if no collection is defined\r
+ || (getOriginal() != null && overrideList == null && overrideMap == null)) {\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Returns override object as instance");\r
+ return getInstance();\r
} else if (overrideList != null) {\r
- return overrideList.getAsObjectList();\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Returns override object as list");\r
+ return overrideList.getAsObjectList((List<Object>) getOriginal());\r
} else if (overrideMap != null) {\r
- return overrideMap.getMap();\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Returns override object as map");\r
+ return overrideMap\r
+ .getAsObjectMap((Map<String, Object>) getOriginal());\r
} else {\r
throw new BuildException("Value or bean not set.");\r
}\r
protected void checkValueAlreadySet() {\r
super.checkValueAlreadySet();\r
if (value != null || overrideList != null || overrideMap != null) {\r
- throw new BuildException("Value already set.");\r
+ if (!getMerge()) {\r
+ throw new BuildException("Value already set.");\r
+ }\r
}\r
}\r
\r
- /** List of overrides */\r
- protected class OverrideList {\r
- private List<OverrideArg> list = new Vector<OverrideArg>();\r
-\r
- /** Creates override sub tag. */\r
- public OverrideArg createOverride() {\r
- OverrideArg overrideArg = new OverrideArg();\r
- list.add(overrideArg);\r
- return overrideArg;\r
- }\r
+ public Boolean getMerge() {\r
+ return merge;\r
+ }\r
\r
- /** Gets as list of objects. */\r
- public List<Object> getAsObjectList() {\r
- List<Object> objectList = new Vector<Object>();\r
- for (OverrideArg arg : list) {\r
- objectList.add(arg.getObject());\r
- }\r
- return objectList;\r
- }\r
+ public void setMerge(Boolean merge) {\r
+ this.merge = merge;\r
}\r
+\r
}\r
import java.util.List;\r
import java.util.Vector;\r
\r
-import org.apache.tools.ant.BuildException;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
import org.apache.tools.ant.types.DataType;\r
import org.argeo.slc.ant.AntConstants;\r
import org.argeo.slc.core.SlcException;\r
\r
/** Abstract Ant type wrapping a Spring bean. */\r
public class SpringArg<T> extends DataType {\r
+ private final static Log log = LogFactory.getLog(SpringArg.class);\r
+\r
private List<OverrideArg> overrides = new Vector<OverrideArg>();\r
\r
private String bean;\r
private String antref;\r
+ /**\r
+ * Reference to the original object, used to merge overrides. <b>this object\r
+ * will be modified</b>.\r
+ */\r
+ private T original;\r
\r
// cache bean instance to avoid reading it twice if it is a prototype\r
- private T beanInstance = null;\r
+ private T instance = null;\r
\r
/** The <u>name</u> of the underlying bean, as set through the attribute. */\r
public String getBean() {\r
* Retrieve the instance of the bean, and sets the overridden properties.\r
* <b>The value is cached.</b>\r
*/\r
- public T getBeanInstance() {\r
- if (beanInstance == null) {\r
+ public T getInstance() {\r
+ if (instance == null) {\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Creates instance");\r
+\r
if (bean != null) {\r
- beanInstance = (T) getContext().getBean(bean);\r
- if (beanInstance == null)\r
+ instance = (T) getContext().getBean(bean);\r
+ if (instance == null)\r
throw new SlcException("No object found for Spring bean "\r
+ bean);\r
} else if (antref != null) {\r
- beanInstance = (T) getProject().getReference(antref);\r
- if (beanInstance == null)\r
+ instance = (T) getProject().getReference(antref);\r
+ if (instance == null)\r
throw new SlcException("No object found for Ant reference "\r
+ antref);\r
+ } else if (original != null) {\r
+ instance = original;\r
} else {\r
throw new SlcException(\r
"Don't know how to retrieve bean instance");\r
}\r
\r
- setOverridenProperties(beanInstance);\r
+ setOverridenProperties(instance);\r
\r
// FIXME: why are we doing this? Could not find any object using it\r
- if (beanInstance instanceof InitializingBean) {\r
+ if (instance instanceof InitializingBean) {\r
try {\r
- ((InitializingBean) beanInstance).afterPropertiesSet();\r
+ ((InitializingBean) instance).afterPropertiesSet();\r
} catch (Exception e) {\r
throw new SlcException("Could not initialize bean", e);\r
}\r
}\r
+ } else {\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Returns cached instance");\r
}\r
- return beanInstance;\r
+ return instance;\r
}\r
\r
protected void setOverridenProperties(Object obj) {\r
"The name of the property to override has to be set.");\r
}\r
\r
- // LogFactory.getLog(getClass()).debug(\r
- // "Prop " + override.getName());\r
+ if (log.isTraceEnabled())\r
+ log.trace(this + "\t: Overrides property " + override.getName()\r
+ + " with " + override);\r
+\r
+ if (override.getMerge() == true) {\r
+ // if override is marked as merged retrieve the value and set is\r
+ // as original\r
+ override.setOriginal(wrapper.getPropertyValue(override\r
+ .getName()));\r
+ }\r
wrapper.setPropertyValue(override.getName(), override.getObject());\r
}\r
\r
}\r
\r
protected void checkValueAlreadySet() {\r
- if (antref != null || bean != null) {\r
- throw new BuildException("Value already set.");\r
+ if (antref != null || bean != null || original != null) {\r
+ throw new SlcException("Instance value already defined.");\r
}\r
}\r
\r
+ public void setOriginal(T original) {\r
+ checkValueAlreadySet();\r
+ this.original = original;\r
+ }\r
+\r
+ public T getOriginal() {\r
+ return original;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuffer buf = new StringBuffer(getClass().getSimpleName());\r
+ if (bean != null) {\r
+ buf.append("#bean=").append(bean);\r
+ } else if (antref != null) {\r
+ buf.append("#antref=").append(antref);\r
+ } else if (original != null) {\r
+ buf.append("#orig=").append(original.hashCode());\r
+ } else {\r
+ buf.append("#noid");\r
+ }\r
+ buf.append("#").append(hashCode());\r
+ return buf.toString();\r
+ }\r
}\r
@Override
public void execute() throws BuildException {
for (BeanArg bean : beans) {
- Object instance = bean.getBeanInstance();
+ Object instance = bean.getInstance();
if (bean.getAntid() != null) {
getProject().addReference(bean.getAntid(), instance);
} else {
\r
// notify registered args\r
for (SpringArg arg : sAwareArgs) {\r
- Object obj = arg.getBeanInstance();\r
+ Object obj = arg.getInstance();\r
\r
if (obj instanceof StructureAware) {\r
StructureAware<TreeSPath> sAwareT = (StructureAware<TreeSPath>) obj;\r
\r
class StructureElementArg extends SpringArg {\r
public StructureElement getStructureElement() {\r
- return (StructureElement) getBeanInstance();\r
+ return (StructureElement) getInstance();\r
}\r
}
\ No newline at end of file
if (!mode.equals(StructureRegistry.READ)) {\r
for (SpringArg<TestResult> result : results) {\r
try {\r
- result.getBeanInstance().close();\r
+ result.getInstance().close();\r
} catch (RuntimeException e) {\r
log.error("Could not close result "\r
+ (result.getBean() != null ? result.getBean()\r
\r
// set overridden references\r
if (testDataArg != null) {\r
- testRun.setTestData(testDataArg.getBeanInstance());\r
+ testRun.setTestData(testDataArg.getInstance());\r
log.trace("Overrides test data");\r
}\r
\r
if (testDefinitionArg != null) {\r
- testRun.setTestDefinition(testDefinitionArg.getBeanInstance());\r
+ testRun.setTestDefinition(testDefinitionArg.getInstance());\r
log.trace("Overrides test definition");\r
}\r
\r
if (deployedSystemArg != null) {\r
- testRun.setDeployedSystem(deployedSystemArg.getBeanInstance());\r
+ testRun.setDeployedSystem(deployedSystemArg.getInstance());\r
log.trace("Overrides deployed system");\r
}\r
\r
if (testResultArg != null) {\r
- testRun.setTestResult(testResultArg.getBeanInstance());\r
+ testRun.setTestResult(testResultArg.getInstance());\r
log.trace("Overrides test result");\r
}\r
\r
import java.util.UUID;
import org.argeo.slc.ant.AntConstants;
+import org.argeo.slc.ant.AntExecutionContext;
import org.argeo.slc.ant.AntSlcApplication;
import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.runtime.SlcExecutionOutput;
import org.argeo.slc.unit.AbstractSpringTestCase;
import org.springframework.core.io.FileSystemResource;
-public class MinimalAntClasspathTestCase extends AbstractSpringTestCase {
+public class MinimalAntClasspathTestCase extends AbstractSpringTestCase
+ implements SlcExecutionOutput<AntExecutionContext> {
protected void execute(String scriptPath) {
AntSlcApplication slcApp = new AntSlcApplication();
slcApp.setRootDir(new FileSystemResource(new File("src/test/resources")
scriptPath);
slcExecution.setUser("user");
- slcApp.execute(slcExecution, null, null, null);
+ slcApp.execute(slcExecution, null, null, this);
+ }
+
+ /** to be overridden */
+ public void postExecution(AntExecutionContext executionContext) {
}
}
--- /dev/null
+package org.argeo.slc.ant;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+public class DummyObject {
+ private String name;
+ private Long value;
+ private DummyObject other;
+ private List<DummyObject> children = new Vector<DummyObject>();
+ private Map<String, DummyObject> map = new TreeMap<String, DummyObject>();
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Long getValue() {
+ return value;
+ }
+
+ public void setValue(Long value) {
+ this.value = value;
+ }
+
+ public DummyObject getOther() {
+ return other;
+ }
+
+ public void setOther(DummyObject other) {
+ this.other = other;
+ }
+
+ public List<DummyObject> getChildren() {
+ return children;
+ }
+
+ public void setChildren(List<DummyObject> children) {
+ this.children = children;
+ }
+
+ public Map<String, DummyObject> getMap() {
+ return map;
+ }
+
+ public void setMap(Map<String, DummyObject> map) {
+ this.map = map;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.ant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.unit.MinimalAntClasspathTestCase;
+
+public class OverrideTest extends MinimalAntClasspathTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ public void testSimpleRun() {
+ execute("/org/argeo/slc/ant/buildOverride.xml");
+ }
+
+ @Override
+ public void postExecution(AntExecutionContext executionContext) {
+ log.info("Analyzing context after execution...");
+
+ DummyObject dummy1UnModified = executionContext
+ .getAntRef("dummy1.unmodified");
+ assertEquals("dummy2", dummy1UnModified.getOther().getName());
+ assertEquals(2, dummy1UnModified.getChildren().size());
+ assertEquals(2, dummy1UnModified.getMap().size());
+
+ DummyObject dummy1Modif1 = executionContext.getAntRef("dummy1.modif1");
+ assertEquals("dummy1.modif1", dummy1Modif1.getName());
+ assertEquals("dummy3", dummy1Modif1.getOther().getName());
+
+ DummyObject dummy1Modif2 = executionContext.getAntRef("dummy1.modif2");
+ assertEquals(1, dummy1Modif2.getChildren().size());
+ assertEquals("dummy3", dummy1Modif2.getChildren().get(0).getName());
+
+ DummyObject dummy1Modif3 = executionContext.getAntRef("dummy1.modif3");
+ assertEquals(2, dummy1Modif3.getChildren().size());
+ assertEquals("dummy3", dummy1Modif3.getChildren().get(0).getName());
+ assertEquals("dummy2", dummy1Modif3.getChildren().get(1).getName());
+
+ DummyObject dummy1Modif4 = executionContext.getAntRef("dummy1.modif4");
+ assertEquals(2, dummy1Modif4.getChildren().size());
+ assertEquals("dummy3", dummy1Modif4.getChildren().get(0).getName());
+ assertEquals("dummy1.modif1", dummy1Modif4.getChildren().get(0)
+ .getOther().getName());
+ assertEquals("dummy2", dummy1Modif4.getChildren().get(1).getName());
+ assertEquals(1, dummy1Modif4.getChildren().get(1).getChildren().size());
+ assertEquals("dummy3", dummy1Modif4.getChildren().get(1).getChildren()
+ .get(0).getName());
+
+ DummyObject dummy1Modif5 = executionContext.getAntRef("dummy1.modif5");
+ assertEquals(2, dummy1Modif5.getMap().size());
+ assertEquals("dummy3", dummy1Modif5.getMap().get("key1").getName());
+ assertEquals("dummy2", dummy1Modif5.getMap().get("key2").getName());
+
+ DummyObject dummy1Modif6 = executionContext.getAntRef("dummy1.modif6");
+ assertEquals(2, dummy1Modif6.getMap().size());
+ assertEquals("dummy2.merged", dummy1Modif6.getMap().get("key1").getName());
+ assertEquals("dummy3.merged", dummy1Modif6.getMap().get("key2").getName());
+
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return inPackage("acOverride.xml");
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.5.xsd">
+
+
+ <bean id="dummy1" parent="template.dummy" scope="prototype">
+ <property name="name" value="dummy1" />
+ <property name="other" ref="dummy2" />
+ <property name="children">
+ <list>
+ <ref bean="dummy2" />
+ <ref bean="dummy3" />
+ </list>
+ </property>
+ <property name="map">
+ <map>
+ <entry key="key1">
+ <ref bean="dummy2" />
+ </entry>
+ <entry key="key2">
+ <ref bean="dummy3" />
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <bean id="dummy2" parent="template.dummy" scope="prototype">
+ <property name="name" value="dummy2" />
+ </bean>
+
+ <bean id="dummy3" parent="template.dummy" scope="prototype">
+ <property name="name" value="dummy3" />
+ </bean>
+
+ <!-- Templates -->
+ <bean id="template.dummy" class="org.argeo.slc.ant.DummyObject"
+ abstract="true">
+ </bean>
+
+
+
+</beans>
\ No newline at end of file
--- /dev/null
+<project default="test">\r
+\r
+ <target name="test">\r
+ <slc.register>
+ <object antid="dummy1.unmodified" bean="dummy1" />
+ <object antid="dummy1.modif1" bean="dummy1">
+ <override name="name" value="dummy1.modif1" />
+ <override name="other" bean="dummy3" />
+ </object>
+ <object antid="dummy1.modif2" bean="dummy1">
+ <override name="children">
+ <list>
+ <override bean="dummy3" />
+ </list>
+ </override>
+ </object>
+ <object antid="dummy1.modif3" bean="dummy1">
+ <override name="children" merge="true">
+ <list>
+ <override>
+ <override name="name" value="dummy3" />
+ </override>
+ <override>
+ <override name="name" value="dummy2" />
+ </override>
+ </list>
+ </override>
+ </object>
+ <object antid="dummy1.modif4" bean="dummy1">
+ <override name="children" merge="true">
+ <list>
+ <override>
+ <override name="name" value="dummy3" />
+ <override name="other" antref="dummy1.modif1" />
+ </override>
+ <override>
+ <override name="name" value="dummy2" />
+ <override name="children">
+ <list>
+ <override bean="dummy3" />
+ </list>
+ </override>
+ </override>
+ </list>
+ </override>
+ </object>
+ <object antid="dummy1.modif5" bean="dummy1">
+ <override name="map">
+ <map>
+ <entry key="key1">
+ <override bean="dummy3" />
+ </entry>
+ <entry key="key2">
+ <override bean="dummy2" />
+ </entry>
+ </map>
+ </override>
+ </object>
+ <object antid="dummy1.modif6" bean="dummy1">
+ <override name="map" merge="true">
+ <map>
+ <entry key="key1">
+ <override>
+ <override name="name" value="dummy2.merged" />
+ </override>
+ </entry>
+ <entry key="key2">
+ <override>
+ <override name="name" value="dummy3.merged" />
+ </override>
+ </entry>
+ </map>
+ </override>
+ </object>
+ </slc.register>\r
+ </target>\r
+</project>
\ No newline at end of file