From: Mathieu Baudier Date: Sat, 22 Nov 2008 12:07:45 +0000 (+0000) Subject: Introduce org.argeo.slc.lib.detached X-Git-Tag: argeo-slc-2.1.7~2403 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=8235a54f85d7ff7ba23873c7612d50097ecdd809;p=gpl%2Fargeo-slc.git Introduce org.argeo.slc.lib.detached git-svn-id: https://svn.argeo.org/slc/trunk@1850 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/runtime/org.argeo.slc.lib.detached/.classpath b/runtime/org.argeo.slc.lib.detached/.classpath new file mode 100644 index 000000000..9653ef0ac --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/runtime/org.argeo.slc.lib.detached/.project b/runtime/org.argeo.slc.lib.detached/.project new file mode 100644 index 000000000..f874c09a1 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/.project @@ -0,0 +1,23 @@ + + + org.argeo.slc.agent + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + diff --git a/runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs b/runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..964778b0e --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Aug 29 11:31:46 CEST 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/runtime/org.argeo.slc.lib.detached/build.xml b/runtime/org.argeo.slc.lib.detached/build.xml new file mode 100644 index 000000000..4213f1de9 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/pom.xml b/runtime/org.argeo.slc.lib.detached/pom.xml new file mode 100644 index 000000000..396598180 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/pom.xml @@ -0,0 +1,135 @@ + + 4.0.0 + + org.argeo.slc + argeo-slc + 0.11.2-SNAPSHOT + ../org.argeo.slc + + org.argeo.slc.agent + jar + Argeo SLC Agent + + + scm:svn:https://www.argeo.org/svn/slc/trunk/org.argeo.slc.agent + + + https://www.argeo.org/svn/slc/trunk/org.argeo.slc.agent + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.maven.plugins + maven-assembly-plugin + + + src/assembly/base.xml + + + + + assembly-base + package + + single + + + + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.slc.* + + *,org.argeo.slc.core.test.spring,org.apache.commons.cli;resolution:=optional + + + + + + + + org.argeo.slc + org.argeo.slc.core + ${project.version} + + + org.argeo.slc + org.argeo.slc.detached + ${project.version} + + + + org.springframework.ws + org.springframework.ws + + + + javax.xml.soap + com.springsource.javax.xml.soap + + + com.sun.xml + + com.springsource.com.sun.xml.messaging.saaj + + + + + org.argeo.dep.osgi + org.argeo.dep.osgi.ant + + + + org.apache.commons + com.springsource.org.apache.commons.net + + + org.apache.oro + com.springsource.org.apache.oro + + + + org.apache.bsf + com.springsource.org.apache.bsf + + + org.beanshell + com.springsource.bsh + + + + + org.argeo.dep.osgi + org.argeo.dep.osgi.commons.cli + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/assembly/base.xml b/runtime/org.argeo.slc.lib.detached/src/assembly/base.xml new file mode 100644 index 000000000..aef97a5cd --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/assembly/base.xml @@ -0,0 +1,16 @@ + + base + false + + tar.gz + + + + src/base + + 0755 + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/base/bin/slc b/runtime/org.argeo.slc.lib.detached/src/base/bin/slc new file mode 100755 index 000000000..ca8ef49d9 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/base/bin/slc @@ -0,0 +1,35 @@ +#!/bin/sh + +# Find home +if [ -z "$ARGEO_SLC_HOME" -o ! -d "$ARGEO_SLC_HOME" ] ; then + ## resolve links - $0 may be a link to home + PRG="$0" + progname=`basename "$0"` + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi + done + + ARGEO_SLC_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + ARGEO_SLC_HOME=`cd "$ARGEO_SLC_HOME" && pwd` +fi + +echo ARGEO_SLC_HOME=$ARGEO_SLC_HOME + +for i in "${ARGEO_SLC_HOME}"/lib/*.jar + do + CLASSPATH="$CLASSPATH:$i" + done + +#echo CLASSPATH=$CLASSPATH + +java -cp $CLASSPATH org.argeo.slc.cli.SlcMain "$@" diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java new file mode 100644 index 000000000..f89742d61 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java @@ -0,0 +1,47 @@ +package org.argeo.slc.ant; + +public interface AntConstants { + // ANT + /** The Ant reference to the Spring application context used. */ + public static final String REF_ROOT_CONTEXT = "slcApplicationContext"; + /** The Ant reference to the SLC structure registry used. */ + public static final String REF_STRUCTURE_REGISTRY = "slcStructureRegistry"; + /** The Ant reference to the TreePath of the current project */ + public static final String REF_PROJECT_PATH = "slcProjectPath"; + /** + * Resource path to the property file listing the SLC specific Ant tasks: + * /org/argeo/slc/ant/taskdefs.properties + */ + public static final String SLC_TASKDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/taskdefs.properties"; + /** + * Resource path to the property file listing the SLC specific Ant types: + * /org/argeo/slc/ant/typedefs.properties + */ + public static final String SLC_TYPEDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/typedefs.properties"; + public static final String REF_SLC_EXECUTION = "slcExecution"; + + // SLC EXECUTION + public static final String EXECTYPE_ANT = "org.apache.tools.ant"; + public static final String EXECTYPE_SLC_ANT = "org.argeo.slc.ant"; + + public final static String EXECATTR_RUNTIME = "slc.runtime"; + public final static String EXECATTR_ANT_FILE = "ant.file"; + public final static String EXECATTR_ANT_TARGETS = "ant.targets"; + + // PROPERTIES + /** Property for the root dir (SLC root property file). */ + public final static String ROOT_DIR_PROPERTY = "slc.rootDir"; + /** Property for the conf dir (SLC root property file). */ + public final static String CONF_DIR_PROPERTY = "slc.confDir"; + /** Property for the work dir (SLC root property file). */ + public final static String WORK_DIR_PROPERTY = "slc.workDir"; + /** Name of the Spring bean used by default */ + public final static String DEFAULT_TEST_RUN_PROPERTY = "slc.defaultTestRun"; + + /** Property for the runtime to use. */ + public final static String RUNTIME_PROPERTY = "slc.runtime"; + + // LOG4J + public final static String MDC_ANT_PROJECT = "slc.ant.project"; + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java new file mode 100644 index 000000000..75bfd340e --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java @@ -0,0 +1,33 @@ +package org.argeo.slc.ant; + +import org.apache.tools.ant.Project; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.runtime.SlcExecutionContext; +import org.springframework.context.ApplicationContext; + +public class AntExecutionContext implements SlcExecutionContext { + private final Project project; + + public AntExecutionContext(Project project) { + this.project = project; + } + + public T getBean(String name) { + ApplicationContext context = (ApplicationContext) project + .getReference(AntConstants.REF_ROOT_CONTEXT); + return (T) context.getBean(name); + } + + public T getAntRef(String antId) { + return (T) project.getReference(antId); + } + + public SlcExecution getSlcExecution() { + return (SlcExecution) project + .getReference(AntConstants.REF_SLC_EXECUTION); + } + + public Project getProject() { + return project; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java new file mode 100644 index 000000000..1adb21058 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java @@ -0,0 +1,91 @@ +package org.argeo.slc.ant; + +import java.io.File; +import java.net.URL; +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; +import org.apache.tools.ant.helper.ProjectHelper2; +import org.argeo.slc.core.SlcException; + +/** Run regular Ant script (that is, not SLC instrumented) */ +public class AntRunner { + private URL buildFile; + private String[] targets; + private Properties properties; + + public AntRunner() { + + } + + public AntRunner(URL buildFile, String target, Properties properties) { + this(buildFile, new String[] { target }, properties); + } + + public AntRunner(URL buildFile, String[] targets, Properties properties) { + this.buildFile = buildFile; + this.targets = targets; + this.properties = properties; + } + + public void run() { + Project p = new Project(); + + String path = buildFile.getFile(); + p.setUserProperty("ant.file", path); + p.setBaseDir(extractBaseDir(path)); + + p.init(); + ProjectHelper projectHelper = new ProjectHelper2(); + p.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, projectHelper); + projectHelper.parse(p, buildFile); + + if (properties != null) { + for (Map.Entry entry : properties.entrySet()) { + p.setUserProperty(entry.getKey().toString(), entry.getValue() + .toString()); + } + } + + p.fireBuildStarted(); + Throwable exception = null; + try { + if (targets == null) { + p.executeTarget(p.getDefaultTarget()); + } else { + p.executeTargets(new Vector(Arrays.asList(targets))); + } + } catch (Throwable e) { + exception = e; + throw new SlcException("Could not run Ant script " + buildFile, e); + } finally { + p.fireBuildFinished(exception); + } + + } + + private File extractBaseDir(String path) { + String baseDir = null; + if (path.length() > 1) { + int indx = path.lastIndexOf('/', path.length() - 1); + if (indx == -1 || indx == 0) { + baseDir = "/"; + } else { + baseDir = path.substring(0, indx) + "/"; + } + } else { + baseDir = "/"; + } + File file = new File(baseDir); + if (file.exists()) { + return file; + } else { + return new File(System.getProperty("user.dir")); + } + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java new file mode 100644 index 000000000..410098d21 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java @@ -0,0 +1,424 @@ +package org.argeo.slc.ant; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.Appender; +import org.apache.log4j.LogManager; +import org.apache.log4j.MDC; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; +import org.apache.tools.ant.helper.ProjectHelper2; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.structure.tree.TreeSRegistry; +import org.argeo.slc.logging.Log4jUtils; +import org.argeo.slc.runtime.SlcExecutionOutput; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.SystemPropertyUtils; + +public class AntSlcApplication { + private final static String DEFAULT_APP_LOG4J_PROPERTIES = "org/argeo/slc/ant/defaultAppLog4j.properties"; + + private final static Log log = LogFactory.getLog(AntSlcApplication.class); + + private Resource contextLocation; + private ConfigurableApplicationContext parentContext; + + private Resource rootDir; + private Resource confDir; + private File workDir; + + public void execute(SlcExecution slcExecution, Properties properties, + Map references, + SlcExecutionOutput executionOutput) { + + // Properties and application logging initialization + initSystemProperties(properties); + Log4jUtils.initLog4j("classpath:" + DEFAULT_APP_LOG4J_PROPERTIES); + + log.info("\n###\n### Start SLC execution " + slcExecution.getUuid() + + "\n###\n"); + if (log.isDebugEnabled()) { + log.debug("rootDir=" + rootDir); + log.debug("confDir=" + confDir); + log.debug("workDir=" + workDir); + } + + // Ant coordinates + String scriptRelativePath = findAntScript(slcExecution); + List targets = findAntTargets(slcExecution); + + // Spring initialization + ConfigurableApplicationContext ctx = createExecutionContext(slcExecution); + + // Ant project initialization + Project project = new Project(); + AntExecutionContext executionContext = new AntExecutionContext(project); + project.addReference(AntConstants.REF_ROOT_CONTEXT, ctx); + project.addReference(AntConstants.REF_SLC_EXECUTION, slcExecution); + + try { + initProject(project, properties, references); + parseProject(project, scriptRelativePath); + + // Execute project + initStructure(project, scriptRelativePath); + runProject(project, targets); + + if (executionOutput != null) + executionOutput.postExecution(executionContext); + } finally { + ctx.close(); + } + } + + protected void initSystemProperties(Properties userProperties) { + // Set user properties as system properties so that Spring can access + // them + if (userProperties != null) { + for (Object key : userProperties.keySet()) { + System.setProperty(key.toString(), userProperties + .getProperty(key.toString())); + } + } + + if (System.getProperty(AntConstants.DEFAULT_TEST_RUN_PROPERTY) == null) { + System.setProperty(AntConstants.DEFAULT_TEST_RUN_PROPERTY, + "defaultTestRun"); + } + + try { + if (rootDir != null) + setSystemPropertyForRes(AntConstants.ROOT_DIR_PROPERTY, rootDir); + if (confDir != null) + setSystemPropertyForRes(AntConstants.CONF_DIR_PROPERTY, confDir); + if (workDir != null) + System.setProperty(AntConstants.WORK_DIR_PROPERTY, workDir + .getCanonicalPath()); + + // Additional properties in slc.properties file. Already set sytem + // properties (such as the various directories) can be resolved in + // placeholders. + if (confDir != null) { + Resource slcPropertiesRes = confDir + .createRelative("slc.properties"); + if (slcPropertiesRes.exists()) { + Properties slcProperties = new Properties(); + InputStream in = slcPropertiesRes.getInputStream(); + try { + slcProperties.load(in); + } finally { + IOUtils.closeQuietly(in); + } + + for (Object obj : slcProperties.keySet()) { + String key = obj.toString(); + if (!System.getProperties().containsKey(key)) { + String value = SystemPropertyUtils + .resolvePlaceholders(slcProperties + .getProperty(key)); + System.setProperty(key, value); + } + } + } + } + } catch (Exception e) { + throw new SlcException("Cannot init system properties.", e); + } + } + + /** + * Set property as an absolute file path if the resource can be located on + * the file system, or as an url. + */ + private void setSystemPropertyForRes(String key, Resource res) + throws IOException { + String value = null; + try { + value = res.getFile().getCanonicalPath(); + } catch (IOException e) { + value = res.getURL().toString(); + } + System.setProperty(key, value); + } + + protected ConfigurableApplicationContext createExecutionContext( + SlcExecution slcExecution) { + try { + + // Find runtime definition + Resource runtimeRes = null; + String runtimeStr = slcExecution.getAttributes().get( + AntConstants.EXECATTR_RUNTIME); + if (runtimeStr == null) + runtimeStr = System.getProperty(AntConstants.RUNTIME_PROPERTY, + "default"); + + ResourceLoader rl = new DefaultResourceLoader(getClass() + .getClassLoader()); + try {// tries absolute reference + runtimeRes = rl.getResource(runtimeStr); + } catch (Exception e) { + // silent + } + if (runtimeRes == null || !runtimeRes.exists()) { + if (confDir != null) + runtimeRes = confDir.createRelative("runtime/" + runtimeStr + + ".xml"); + } + + // Find runtime independent application context definition + if (confDir != null && contextLocation == null) { + contextLocation = confDir + .createRelative("applicationContext.xml"); + } + + GenericApplicationContext ctx = new GenericApplicationContext( + parentContext); + ctx.setDisplayName("SLC Execution #" + slcExecution.getUuid()); + + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx); + if (runtimeRes != null && runtimeRes.exists()) + xmlReader.loadBeanDefinitions(runtimeRes); + else + log.warn("No runtime context defined"); + + if (contextLocation != null && contextLocation.exists()) + xmlReader.loadBeanDefinitions(contextLocation); + else + log.warn("No runtime independent application context defined"); + + // Add property place holder + PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); + ppc.setIgnoreUnresolvablePlaceholders(true); + ctx.addBeanFactoryPostProcessor(ppc); + + ctx.refresh(); + return ctx; + } catch (Exception e) { + throw new SlcException( + "Cannot create SLC execution application context.", e); + } + } + + protected String findAntScript(SlcExecution slcExecution) { + String scriptStr = slcExecution.getAttributes().get( + AntConstants.EXECATTR_ANT_FILE); + if (scriptStr == null) + throw new SlcException("No Ant script provided"); + + return scriptStr; + } + + protected List findAntTargets(SlcExecution slcExecution) { + String targetList = slcExecution.getAttributes().get( + AntConstants.EXECATTR_ANT_TARGETS); + List targets = new Vector(); + if (targetList != null) { + StringTokenizer stTargets = new StringTokenizer(targetList, ","); + while (stTargets.hasMoreTokens()) { + targets.add(stTargets.nextToken()); + } + } + return targets; + } + + protected void initProject(Project project, Properties properties, + Map references) { + if (properties != null) { + for (Map.Entry entry : properties.entrySet()) { + project.setUserProperty(entry.getKey().toString(), entry + .getValue().toString()); + } + } + + if (references != null) { + for (Map.Entry entry : references.entrySet()) { + project.addReference(entry.getKey(), entry.getValue()); + } + } + + //project.addBuildListener(new CommonsLoggingListener()); + + ListableBeanFactory context = (ListableBeanFactory) project + .getReference(AntConstants.REF_ROOT_CONTEXT); + // Register build listeners + Map listeners = BeanFactoryUtils + .beansOfTypeIncludingAncestors(context, BuildListener.class, + false, false); + for (BuildListener listener : listeners.values()) { + project.addBuildListener(listener); + } + + // Register log4j appenders from context + MDC.put(AntConstants.MDC_ANT_PROJECT, project); + Map appenders = context.getBeansOfType( + Appender.class, false, true); + for (Appender appender : appenders.values()) { + LogManager.getRootLogger().addAppender(appender); + } + + project.init(); + addCustomTaskAndTypes(project); + } + + /** Loads the SLC specific Ant tasks. */ + protected void addCustomTaskAndTypes(Project project) { + Properties taskdefs = getDefs(project, + AntConstants.SLC_TASKDEFS_RESOURCE_PATH); + for (Object o : taskdefs.keySet()) { + String name = o.toString(); + try { + project.addTaskDefinition(name, Class.forName(taskdefs + .getProperty(name))); + } catch (ClassNotFoundException e) { + log.error("Unknown class for task " + name, e); + } + } + Properties typedefs = getDefs(project, + AntConstants.SLC_TYPEDEFS_RESOURCE_PATH); + for (Object o : typedefs.keySet()) { + String name = o.toString(); + try { + project.addDataTypeDefinition(name, Class.forName(typedefs + .getProperty(name))); + } catch (ClassNotFoundException e) { + log.error("Unknown class for type " + name, e); + } + } + } + + private Properties getDefs(Project project, String path) { + Properties defs = new Properties(); + try { + InputStream in = project.getClass().getResourceAsStream(path); + defs.load(in); + in.close(); + } catch (IOException e) { + throw new SlcException("Cannot load task definitions", e); + } + return defs; + } + + protected void initStructure(Project project, String scriptRelativePath) { + // Init structure registry + StructureRegistry registry = new TreeSRegistry(); + project.addReference(AntConstants.REF_STRUCTURE_REGISTRY, registry); + + // Lowest levels + StringTokenizer st = new StringTokenizer(scriptRelativePath, "/"); + TreeSPath currPath = null; + while (st.hasMoreTokens()) { + String name = st.nextToken(); + if (currPath == null) { + currPath = TreeSPath.createRootPath(name); + } else { + if (st.hasMoreTokens())// don't register project file + currPath = currPath.createChild(name); + } + registry.register(currPath, new SimpleSElement(name)); + } + + // Project level + String projectName = project.getName() != null + && !project.getName().equals("") ? project.getName() + : "project"; + TreeSPath projectPath = currPath.createChild(projectName); + + String projectDesc = project.getDescription() != null + && !project.getDescription().equals("") ? project + .getDescription() : projectPath.getName(); + + registry.register(projectPath, new SimpleSElement(projectDesc)); + project.addReference(AntConstants.REF_PROJECT_PATH, projectPath); + + if (log.isDebugEnabled()) + log.debug("Project path: " + projectPath); + } + + protected void parseProject(Project project, String scriptRelativePath) { + try { + Resource script = rootDir.createRelative(scriptRelativePath); + File baseDir = null; + try { + File scriptFile = script.getFile(); + baseDir = scriptFile.getParentFile(); + } catch (IOException e) {// resource is not a file + baseDir = new File(System.getProperty("user.dir")); + } + project.setBaseDir(baseDir); + // Reset basedir property, in order to avoid base dir override when + // running in Maven + project.setProperty("basedir", baseDir.getAbsolutePath()); + + ProjectHelper2 projectHelper = new ProjectHelper2(); + project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, + projectHelper); + projectHelper.parse(project, script.getURL()); + } catch (Exception e) { + throw new SlcException("Could not parse project for script " + + scriptRelativePath, e); + } + + } + + protected void runProject(Project p, List targets) { + p.fireBuildStarted(); + Throwable exception = null; + try { + if (targets.size() == 0) {// no target defined + p.executeTarget(p.getDefaultTarget()); + } else { + p.executeTargets(new Vector(targets)); + } + } catch (Throwable e) { + exception = e; + throw new SlcException("SLC Ant execution failed", exception); + } finally { + p.fireBuildFinished(exception); + } + } + + public void setContextLocation(Resource contextLocation) { + this.contextLocation = contextLocation; + } + + public void setRootDir(Resource rootDir) { + this.rootDir = rootDir; + } + + public void setConfDir(Resource confDir) { + this.confDir = confDir; + } + + public void setWorkDir(File workDir) { + this.workDir = workDir; + } + + public void setParentContext(ConfigurableApplicationContext runtimeContext) { + this.parentContext = runtimeContext; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java new file mode 100644 index 000000000..43b247c2b --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java @@ -0,0 +1,40 @@ +package org.argeo.slc.ant; + +import java.util.StringTokenizer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.util.FileNameMapper; + +public class RemoveRootDirMapper implements FileNameMapper { + private Log log = LogFactory.getLog(RemoveRootDirMapper.class); + private String to = "enabled"; + + public String[] mapFileName(String sourceFileName) { + StringTokenizer st = new StringTokenizer(sourceFileName, "/"); + boolean first = true; + boolean skipRoot = !to.equals("disabled"); + StringBuffer buf = new StringBuffer(""); + while (st.hasMoreTokens()) { + if (first && skipRoot) { // skip + st.nextToken(); + first = false; + } else { + buf.append(st.nextToken()).append('/'); + } + } + + if (log.isTraceEnabled()) { + log.trace("Source: " + sourceFileName + " - out: " + buf); + } + return new String[] { buf.toString() }; + } + + public void setFrom(String from) { + } + + public void setTo(String to) { + this.to = to; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java new file mode 100644 index 000000000..7447583ab --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java @@ -0,0 +1,202 @@ +package org.argeo.slc.ant; + +import java.util.List; +import java.util.Vector; + +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Level; +import org.apache.log4j.MDC; +import org.apache.log4j.spi.LoggingEvent; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.Project; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionNotifier; +import org.argeo.slc.core.process.SlcExecutionStep; + +public class SlcExecutionBuildListener extends AppenderSkeleton implements + BuildListener { + private List notifiers = new Vector(); + + private boolean currentStepNotified = true; + + // CUSTOMIZATIONS + /** + * Whether to log Ant initialization stuff before the first target has been + * called. + */ + private boolean logBeforeFirstTarget = false; + /** Whether the first target has been called. */ + private boolean firstTargetStarted = false; + + private boolean logTaskStartFinish = true; + + public SlcExecutionBuildListener() { + // Default log level + setThreshold(Level.INFO); + } + + public void buildStarted(BuildEvent event) { + SlcExecution slcExecution = getSlcExecution(event); + for (SlcExecutionNotifier notifier : notifiers) { + notifier.newExecution(slcExecution); + } + } + + public void buildFinished(BuildEvent event) { + SlcExecution slcExecution = getSlcExecution(event); + String oldStatus = slcExecution.getStatus(); + slcExecution.setStatus(SlcExecution.STATUS_FINISHED); + + for (SlcExecutionNotifier notifier : notifiers) { + notifier.updateStatus(slcExecution, oldStatus, slcExecution + .getStatus()); + } + } + + public void messageLogged(BuildEvent event) { + if (!shouldLog()) + return; + + SlcExecution slcExecution = getSlcExecution(event); + if (slcExecution != null) { + if (currentStepNotified) { + slcExecution.getSteps().add( + new SlcExecutionStep(event.getMessage())); + notifyStep(slcExecution, slcExecution.currentStep()); + currentStepNotified = true; + } else { + slcExecution.currentStep().addLog(event.getMessage()); + } + } else { + // TODO: log before initialization? + } + } + + public void targetStarted(BuildEvent event) { + if (!firstTargetStarted) + firstTargetStarted = true; + + addLogStep(event, "Target " + event.getTarget().getName() + " started"); + } + + public void targetFinished(BuildEvent event) { + addLogStep(event, "Target " + event.getTarget().getName() + " finished"); + } + + public void taskStarted(BuildEvent event) { + if (!shouldLog()) + return; + + SlcExecution slcExecution = getSlcExecution(event); + if (!currentStepNotified) { + notifyStep(slcExecution, slcExecution.currentStep()); + currentStepNotified = true; + } + + String msg = null; + if (logTaskStartFinish) + msg = "Task " + event.getTask().getTaskName() + " started"; + + slcExecution.getSteps().add(new SlcExecutionStep(msg)); + + currentStepNotified = false; + } + + public void taskFinished(BuildEvent event) { + if (!shouldLog()) + return; + + SlcExecution slcExecution = getSlcExecution(event); + if (!currentStepNotified) { + + if (logTaskStartFinish) + slcExecution.currentStep().addLog( + "Task " + event.getTask().getTaskName() + " finished"); + + notifyStep(slcExecution, slcExecution.currentStep()); + currentStepNotified = true; + } + } + + public void setNotifiers(List notifiers) { + this.notifiers = notifiers; + } + + protected SlcExecution getSlcExecution(BuildEvent event) { + return getSlcExecution(event.getProject()); + } + + protected SlcExecution getSlcExecution(Project project) { + SlcExecution slcExecution = (SlcExecution) project + .getReference(AntConstants.REF_SLC_EXECUTION); + + if (slcExecution == null) + throw new SlcException("No SLC Execution registered."); + return slcExecution; + } + + protected void addLogStep(BuildEvent event, String msg) { + SlcExecution slcExecution = getSlcExecution(event); + slcExecution.getSteps().add(new SlcExecutionStep(msg)); + + notifyStep(slcExecution, slcExecution.currentStep()); + currentStepNotified = true; + } + + protected void notifyStep(SlcExecution slcExecution, SlcExecutionStep step) { + Vector additionalSteps = new Vector(); + additionalSteps.add(step); + notifySteps(slcExecution, additionalSteps); + } + + protected void notifySteps(SlcExecution slcExecution, + List additionalSteps) { + for (SlcExecutionNotifier notifier : notifiers) { + notifier.addSteps(slcExecution, additionalSteps); + } + } + + /* Log4j methods */ + + @Override + protected void append(LoggingEvent event) { + Project project = (Project) MDC.get(AntConstants.MDC_ANT_PROJECT); + if (project == null) + throw new SlcException("No Ant project registered in Log4j MDC."); + + SlcExecution slcExecution = getSlcExecution(project); + if (currentStepNotified) { + slcExecution.getSteps().add( + new SlcExecutionStep(event.getMessage().toString())); + currentStepNotified = false; + } else { + slcExecution.currentStep().addLog(event.getMessage().toString()); + } + } + + protected boolean shouldLog() { + return logBeforeFirstTarget || firstTargetStarted; + } + + public void close() { + } + + public boolean requiresLayout() { + return false; + } + + public void setLogBeforeFirstTarget(boolean logBeforeFirstTarget) { + this.logBeforeFirstTarget = logBeforeFirstTarget; + } + + public void setLogTaskStartFinish(boolean logTaskStartFinish) { + this.logTaskStartFinish = logTaskStartFinish; + } + + public void setLogLevel(String logLevel) { + setThreshold(Level.toLevel(logLevel)); + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java new file mode 100644 index 000000000..2055e3b66 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java @@ -0,0 +1,72 @@ +package org.argeo.slc.ant.deploy; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.BuildException; +import org.argeo.slc.ant.spring.SpringArg; +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.Deployment; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; + +/** Ant task wrapping a deployment. */ +public class SlcDeployTask extends SAwareTask { + private Log log = LogFactory.getLog(SlcDeployTask.class); + + private String deploymentBean = null; + + private SpringArg deploymentDataArg; + private SpringArg targetDataArg; + private SpringArg distributionArg; + + @Override + public void executeActions(String mode) throws BuildException { + Deployment deployment = (Deployment) getContext().getBean( + deploymentBean); + + // set overridden references + if (distributionArg != null) { + deployment.setDistribution(distributionArg.getInstance()); + log.trace("Overrides distribution"); + } + + if (deploymentDataArg != null) { + deployment.setDeploymentData(deploymentDataArg.getInstance()); + log.trace("Overrides deployment data"); + } + + if (targetDataArg != null) { + deployment.setTargetData(targetDataArg.getInstance()); + log.trace("Overrides target data"); + } + + deployment.execute(); + } + + /** + * The bean name of the test run to use. If not set the default is used. + * + * @see SlcAntConfig + */ + public void setDeployment(String deploymentBean) { + this.deploymentBean = deploymentBean; + } + + /** Creates deployment data sub tag. */ + public SpringArg createDeploymentData() { + deploymentDataArg = new SpringArg(); + return deploymentDataArg; + } + + /** Creates target data sub tag. */ + public SpringArg createTargetData() { + targetDataArg = new SpringArg(); + return targetDataArg; + } + + public SpringArg createDistribution() { + distributionArg = new SpringArg(); + return distributionArg; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java new file mode 100644 index 000000000..c4cc74bb1 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java @@ -0,0 +1,35 @@ +package org.argeo.slc.ant.deploy; + +import java.lang.reflect.Method; + +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.deploy.DeployedSystemManager; + +public class SlcManagerTask extends SAwareTask { + private String action; + private String manager; + + @Override + protected void executeActions(String mode) { + DeployedSystemManager systemManager = getBean(manager); + + try { + Method method = systemManager.getClass().getMethod(action, null); + method.invoke(systemManager, null); + } catch (Exception e) { + throw new SlcException("Cannot execute action " + action + + " for manager " + manager, e); + } + } + + public void setAction(String action) { + this.action = action; + } + + public void setManager(String manager) { + this.manager = manager; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html new file mode 100644 index 000000000..76582d159 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html @@ -0,0 +1,6 @@ + + + +Integration of SLC Deploy in Ant. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java new file mode 100644 index 000000000..d973d3815 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java @@ -0,0 +1,76 @@ +package org.argeo.slc.ant.detached; + +import java.util.Properties; +import java.util.UUID; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.ant.spring.MapArg; +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.detached.DetachedAnswer; +import org.argeo.slc.detached.DetachedClient; +import org.argeo.slc.detached.DetachedRequest; +import org.argeo.slc.spring.SpringUtils; + +public class SlcDetachedTask extends SAwareTask { + private final static Log log = LogFactory.getLog(SlcDetachedTask.class); + + private String client; + private String action; + + private MapArg properties; + + @Override + protected void executeActions(String mode) { + // Find detached client + DetachedClient detachedClient = null; + if (client != null) + detachedClient = getBean(client); + else + detachedClient = SpringUtils.loadSingleFromContext(getContext(), + DetachedClient.class); + + if (detachedClient == null) + throw new SlcException("Could not find any detached client."); + + // Prepare and send request + DetachedRequest request = new DetachedRequest(UUID.randomUUID() + .toString()); + request.setRef(action); + + if (properties != null) { + Properties props = new Properties(); + props.putAll(properties.getMap()); + request.setProperties(props); + } + + try { + detachedClient.sendRequest(request); + DetachedAnswer answer = detachedClient.receiveAnswer(); + if (answer.getStatus() == DetachedAnswer.ERROR) + throw new SlcException("Error when executing request " + + answer.getUuid() + ": " + answer.getLog()); + else + log.info("Admin answer: " + answer.getLog()); + } catch (Exception e) { + throw new SlcException("Could not send request.", e); + } + } + + public void setClient(String driverBean) { + this.client = driverBean; + } + + public void setAction(String action) { + this.action = action; + } + + public MapArg createProperties() { + if (properties == null) + properties = new MapArg(); + else + throw new SlcException("Properties already declared."); + return properties; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html new file mode 100644 index 000000000..9f36fb1bf --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html @@ -0,0 +1,38 @@ + + + +Bases classes for SLC Ant extensions. +

Introduction

+SLC Ant allows to integrate Ant and Spring in order to run an +application based on top of SLC. Sequence of actions are defined in Ant +files with specific Ant tasks referencing Spring beans implementing the +SLC interfaces. The properties of these beans can be overridden at +runtime in the Ant scripts. +
+SLC Ant also provides a tree-based implementation of the SLC structure +which allows to uniquely identify and reference the various actions. + +

Installation

+The structure will be first defined by the directory tree where the Ant +files are stored. In order to define the root of this tree, you need to +place in the root directory an +SLC Ant root file +(default name: slcRoot.properties). +
+In this root file you can define a configuration directory and a work +directory (default values are provided if they are not explicitly set). +
+Additional properties can then be defined in files stored under the +configuration directory. +
+For details about the configuration and the various properties, please +refer to {@link org.argeo.slc.ant.SlcAntConfig}. + +

Running SLC Ant

+SLC Ant can be run either via pure Ant scripts or programmatically using +{@link org.argeo.slc.ant.AntRegistryUtil}. In both cases, make sure that +SLC and its dependencies are in the classpath (Spring (always), logging +system such as log4j, Hibernate, etc.). + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java new file mode 100644 index 000000000..f0eae3fd0 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java @@ -0,0 +1,24 @@ +package org.argeo.slc.ant.spring; + +import org.springframework.context.ApplicationContext; + +import org.apache.tools.ant.Task; + +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.core.process.SlcExecution; + +/** Abstract Ant task providing access to a Spring context. */ +public abstract class AbstractSpringTask extends Task { + + /** Gets the related Spring context. */ + protected ApplicationContext getContext() { + return (ApplicationContext) getProject().getReference( + AntConstants.REF_ROOT_CONTEXT); + } + + /** Gets the related slc execution or null if not is registered. */ + protected SlcExecution getSlcExecution() { + return (SlcExecution) getProject().getReference( + AntConstants.REF_SLC_EXECUTION); + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java new file mode 100644 index 000000000..7c270eef4 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java @@ -0,0 +1,37 @@ +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 list = new Vector(); + + /** Creates override sub tag. */ + public OverrideArg createOverride() { + OverrideArg overrideArg = new OverrideArg(); + list.add(overrideArg); + return overrideArg; + } + + /** Gets as list of objects. */ + public List getAsObjectList(List originalList) { + if (originalList != null && originalList.size() != list.size()) { + throw new SlcException("Cannot merge lists of different sizes."); + } + + List objectList = new Vector(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; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java new file mode 100644 index 000000000..6f53994fe --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java @@ -0,0 +1,97 @@ +package org.argeo.slc.ant.spring; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; + +import org.argeo.slc.core.SlcException; + +public class MapArg { + private List entries = new Vector(); + private Map map = new TreeMap(); + + public EntryArg createEntry() { + EntryArg arg = new EntryArg(); + entries.add(arg); + return arg; + } + + public Map getAsObjectMap(Map originalMap) { + Map objectMap = new TreeMap(); + for (EntryArg arg : entries) { + String key = arg.getKey(); + + if (objectMap.containsKey(key)) { + throw new SlcException("Key '" + key + "' already set."); + } + + if (originalMap != null && originalMap.containsKey(key) + && arg.getOverrideArg() != null) + arg.getOverrideArg().setOriginal(originalMap.get(key)); + + objectMap.put(key, arg.getObject()); + + } + return objectMap; + } + + /** + * Returns a cached reference if it was already called. This reference could + * have been modified externally and thus not anymore be in line with the + * configuration. + */ + public Map getMap() { + if (map.size() == 0) + map = getAsObjectMap(null); + return map; + } + + public static class EntryArg { + private String key; + private Object valueStr; + private OverrideArg overrideArg; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Object getObject() { + if (overrideArg != null) { + return overrideArg.getObject(); + } else if (valueStr != null) { + return valueStr; + } else { + throw new BuildException("Value not set."); + } + } + + public void setValue(String value) { + check(); + this.valueStr = value; + } + + public OverrideArg createOverride() { + check(); + overrideArg = new OverrideArg(); + return overrideArg; + } + + private void check() { + if (valueStr != null || overrideArg != null) { + throw new BuildException("Value already set"); + } + } + + public OverrideArg getOverrideArg() { + return overrideArg; + } + + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java new file mode 100644 index 000000000..645b59204 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java @@ -0,0 +1,103 @@ +package org.argeo.slc.ant.spring; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.BuildException; + +/** Ant type allowing to override bean properties. */ +public class OverrideArg extends SpringArg { + private final static Log log = LogFactory.getLog(OverrideArg.class); + + private String name; + private Object value; + private ListArg overrideList; + private MapArg overrideMap; + + private Boolean merge = false; + + /** The name of the property to override. */ + public String getName() { + return name; + } + + /** Sets the name. */ + public void setName(String name) { + this.name = name; + } + + /** Both value and bean cannot be set. */ + public void setValue(String value) { + checkValueAlreadySet(); + this.value = value; + } + + @Override + public void setBean(String bean) { + checkValueAlreadySet(); + super.setBean(bean); + } + + /** Creates override list sub tag. */ + public ListArg createList() { + checkValueAlreadySet(); + overrideList = new ListArg(); + return overrideList; + } + + public MapArg createMap() { + checkValueAlreadySet(); + overrideMap = new MapArg(); + return overrideMap; + } + + /** + * The related object: the value if a value had been set or an instance of + * the bean if not. + */ + public Object getObject() { + if (value != null) { + if (log.isTraceEnabled()) + log.trace(this + "\t: Returns override object as value"); + return value; + } else if (getBean() != null + || getAntref() != null + // works on original if no collection is defined + || (getOriginal() != null && overrideList == null && overrideMap == null)) { + if (log.isTraceEnabled()) + log.trace(this + "\t: Returns override object as instance"); + return getInstance(); + } else if (overrideList != null) { + if (log.isTraceEnabled()) + log.trace(this + "\t: Returns override object as list"); + return overrideList.getAsObjectList((List) getOriginal()); + } else if (overrideMap != null) { + if (log.isTraceEnabled()) + log.trace(this + "\t: Returns override object as map"); + return overrideMap + .getAsObjectMap((Map) getOriginal()); + } else { + throw new BuildException("Value or bean not set."); + } + } + + protected void checkValueAlreadySet() { + super.checkValueAlreadySet(); + if (value != null || overrideList != null || overrideMap != null) { + if (!getMerge()) { + throw new BuildException("Value already set."); + } + } + } + + public Boolean getMerge() { + return merge; + } + + public void setMerge(Boolean merge) { + this.merge = merge; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java new file mode 100644 index 000000000..3f3bb3c1d --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java @@ -0,0 +1,163 @@ +package org.argeo.slc.ant.spring; + +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.types.DataType; +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.core.SlcException; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; + +/** Abstract Ant type wrapping a Spring bean. */ +public class SpringArg extends DataType { + private final static Log log = LogFactory.getLog(SpringArg.class); + + private List overrides = new Vector(); + + private String bean; + private String antref; + /** + * Reference to the original object, used to merge overrides. this object + * will be modified. + */ + private T original; + + // cache bean instance to avoid reading it twice if it is a prototype + private T instance = null; + + /** The name of the underlying bean, as set through the attribute. */ + public String getBean() { + return bean; + } + + /** Setter for the bean name. */ + public void setBean(String bean) { + checkValueAlreadySet(); + this.bean = bean; + } + + public String getAntref() { + return antref; + } + + /** Sets a reference to an ant data type. */ + public void setAntref(String antref) { + checkValueAlreadySet(); + this.antref = antref; + } + + /** + * Retrieve the instance of the bean, and sets the overridden properties. + * The value is cached. + */ + public T getInstance() { + if (instance == null) { + if (log.isTraceEnabled()) + log.trace(this + "\t: Creates instance"); + + if (bean != null) { + instance = (T) getContext().getBean(bean); + if (instance == null) + throw new SlcException("No object found for Spring bean " + + bean); + } else if (antref != null) { + instance = (T) getProject().getReference(antref); + if (instance == null) + throw new SlcException("No object found for Ant reference " + + antref); + } else if (original != null) { + instance = original; + } else { + throw new SlcException( + "Don't know how to retrieve bean instance"); + } + + setOverridenProperties(instance); + + // FIXME: why are we doing this? Could not find any object using it + if (instance instanceof InitializingBean) { + try { + ((InitializingBean) instance).afterPropertiesSet(); + } catch (Exception e) { + throw new SlcException("Could not initialize bean", e); + } + } + } else { + if (log.isTraceEnabled()) + log.trace(this + "\t: Returns cached instance"); + } + return instance; + } + + protected void setOverridenProperties(Object obj) { + BeanWrapper wrapper = new BeanWrapperImpl(obj); + for (OverrideArg override : overrides) { + if (override.getName() == null) { + throw new SlcException( + "The name of the property to override has to be set."); + } + + if (log.isTraceEnabled()) + log.trace(this + "\t: Overrides property " + override.getName() + + " with " + override); + + if (override.getMerge() == true) { + // if override is marked as merged retrieve the value and set is + // as original + override.setOriginal(wrapper.getPropertyValue(override + .getName())); + } + wrapper.setPropertyValue(override.getName(), override.getObject()); + } + + } + + /** Creates an override subtag. */ + public OverrideArg createOverride() { + OverrideArg propertyArg = new OverrideArg(); + overrides.add(propertyArg); + return propertyArg; + } + + /** The related Spring application context. */ + protected ApplicationContext getContext() { + return (ApplicationContext) getProject().getReference( + AntConstants.REF_ROOT_CONTEXT); + } + + protected void checkValueAlreadySet() { + if (antref != null || bean != null || original != null) { + throw new SlcException("Instance value already defined."); + } + } + + public void setOriginal(T original) { + checkValueAlreadySet(); + this.original = original; + } + + public T getOriginal() { + return original; + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(getClass().getSimpleName()); + if (bean != null) { + buf.append("#bean=").append(bean); + } else if (antref != null) { + buf.append("#antref=").append(antref); + } else if (original != null) { + buf.append("#orig=").append(original.hashCode()); + } else { + buf.append("#noid"); + } + buf.append("#").append(hashCode()); + return buf.toString(); + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java new file mode 100644 index 000000000..a7d88f254 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java @@ -0,0 +1,51 @@ +package org.argeo.slc.ant.spring; + +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.BuildException; + +public class SpringRegister extends AbstractSpringTask { + private static final Log log = LogFactory.getLog(SpringRegister.class); + + private List beans = new Vector(); + + @Override + public void execute() throws BuildException { + for (BeanArg bean : beans) { + Object instance = bean.getInstance(); + if (bean.getAntid() != null) { + getProject().addReference(bean.getAntid(), instance); + } else { + if (bean.getAntref() != null) { + log + .warn("Cannot register beans with antref (Ant reference " + + bean.getAntref() + ")"); + } else { + getProject().addReference(bean.getBean(), instance); + } + } + } + } + + public BeanArg createObject() { + BeanArg bean = new BeanArg(); + beans.add(bean); + return bean; + } + + protected static class BeanArg extends SpringArg { + private String antid; + + public String getAntid() { + return antid; + } + + public void setAntid(String antid) { + this.antid = antid; + } + + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html new file mode 100644 index 000000000..6d141d993 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html @@ -0,0 +1,6 @@ + + + +Integration of Spring in Ant. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java new file mode 100644 index 000000000..134b2c150 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java @@ -0,0 +1,160 @@ +package org.argeo.slc.ant.structure; + +import java.util.List; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Target; +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.ant.spring.AbstractSpringTask; +import org.argeo.slc.ant.spring.SpringArg; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.structure.tree.TreeSPath; + +/** Ant task that can be registered within a structure. */ +public abstract class SAwareTask extends AbstractSpringTask { + private String path; + private TreeSPath treeSPath; + private final List sAwareArgs = new Vector(); + + private StructureElementArg structureElementArg; + + @Override + public void init() throws BuildException { + StructureRegistry registry = getRegistry(); + Target target = getOwningTarget(); + + TreeSPath targetPath = createTargetPath(target); + SimpleSElement targetElement = (SimpleSElement) registry + .getElement(createTargetPath(target)); + + if (targetElement == null) { + targetElement = new SimpleSElement(target.getDescription(), + ""); + registry.register(targetPath, targetElement); + } + } + + /** + * Includes this arg in the checks for propagation of structure related + * information. + */ + protected void addSAwareArg(SpringArg arg) { + sAwareArgs.add(arg); + } + + @Override + /** + * Called by Ant at runtime. Decides whether to call the actions depending + * of the mode of the underlying structure registry. + * + * @see #executeActions + * @see StructureRegistry + */ + public final void execute() throws BuildException { + if (path == null) { + // register the task in the structure + TreeSPath targetPath = createTargetPath(getOwningTarget()); + TreeSPath taskPath = targetPath.createChild(getTaskName() + + targetPath.listChildren(getRegistry()).size()); + + treeSPath = taskPath; + } else { + treeSPath = new TreeSPath(path); + } + + if (getRegistry().getElement(treeSPath) == null) { + // No structure element registered. + if (structureElementArg != null) { + getRegistry().register(treeSPath, + structureElementArg.getStructureElement()); + } else { + if (getDescription() != null) { + getRegistry().register(treeSPath, + new SimpleSElement(getDescription())); + } + } + } + + // notify registered args + for (SpringArg arg : sAwareArgs) { + Object obj = arg.getInstance(); + + if (obj instanceof StructureAware) { + StructureAware sAwareT = (StructureAware) obj; + sAwareT.notifyCurrentPath(getRegistry(), treeSPath); + } + } + + // execute depending on the registry mode + String mode = getRegistry().getMode(); + if (mode.equals(StructureRegistry.ALL)) { + executeActions(mode); + } else if (mode.equals(StructureRegistry.ACTIVE)) { + List activePaths = getRegistry().getActivePaths(); + + if (activePaths.contains(treeSPath)) { + if (activePaths.contains(treeSPath)) { + executeActions(mode); + } + } + } + + } + + /** Actions to be executed by the implementor. */ + protected abstract void executeActions(String mode); + + public T getBean(String beanName) { + return (T) getContext().getBean(beanName); + } + + /** Create a reference to an external structure element. */ + public StructureElementArg createStructureElement() { + if (structureElementArg != null) + throw new SlcException("Arg already set."); + structureElementArg = new StructureElementArg(); + return structureElementArg; + } + + /** Gets the underlying structure registry. */ + protected StructureRegistry getRegistry() { + return (StructureRegistry) getProject().getReference( + AntConstants.REF_STRUCTURE_REGISTRY); + } + + /** Creates the treeSPath for a given Ant target. */ + protected static TreeSPath createTargetPath(Target target) { + TreeSPath projectPath = (TreeSPath) target.getProject().getReference( + AntConstants.REF_PROJECT_PATH); + return projectPath.createChild(target.getName()); + } + + /** Gets the treeSPath under which this task is registered. */ + public TreeSPath getTreeSPath() { + return treeSPath; + } + + public String getLabel() { + String description = super.getDescription(); + if (description == null) { + return ""; + } else { + return description; + } + } + + public void setPath(String path) { + this.path = path; + } +} + +class StructureElementArg extends SpringArg { + public StructureElement getStructureElement() { + return (StructureElement) getInstance(); + } +} \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html new file mode 100644 index 000000000..99e45d335 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html @@ -0,0 +1,6 @@ + + + +Integration of SLC Structure in Ant. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java new file mode 100644 index 000000000..7915b1a42 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java @@ -0,0 +1,102 @@ +package org.argeo.slc.ant.test; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.tools.ant.types.DataType; + +import org.argeo.slc.ant.spring.MapArg; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.test.context.ContextAware; +import org.argeo.slc.core.test.context.ContextUtils; +import org.argeo.slc.core.test.context.ParentContextAware; + +public class ParentContextType extends DataType implements ParentContextAware { + private MapArg values = null; + private MapArg expectedValues = null; + + private String contextAnyFlag = DEFAULT_ANY_FLAG; + private String contextSkipFlag = DEFAULT_SKIP_FLAG; + + private String basedon = null; + + private List children = new Vector(); + + public MapArg createValues() { + values = new MapArg(); + return values; + } + + public MapArg createExpectedValues() { + expectedValues = new MapArg(); + return expectedValues; + } + + public void addChildContext(ContextAware contextAware) { + children.add(contextAware); + } + + public Collection getChildContexts() { + return children; + } + + public String getContextAnyFlag() { + return contextAnyFlag; + } + + public void setContextAnyFlag(String contextAnyFlag) { + this.contextAnyFlag = contextAnyFlag; + } + + public String getContextSkipFlag() { + return contextSkipFlag; + } + + public void setContextSkipFlag(String contextSkipFlag) { + this.contextSkipFlag = contextSkipFlag; + } + + public Map getExpectedValues() { + if (expectedValues == null) + expectedValues = new MapArg(); + if (basedon != null) { + Map map = getBaseContext().getExpectedValues(); + ContextUtils.putNotContained(expectedValues.getMap(), map); + } + return expectedValues.getMap(); + } + + public Map getValues() { + if (values == null) + values = new MapArg(); + if (basedon != null) { + Map map = getBaseContext().getValues(); + ContextUtils.putNotContained(values.getMap(), map); + } + return values.getMap(); + } + + private ParentContextType getBaseContext() { + return (ParentContextType) getProject().getReference(basedon); + } + + public void setValues(Map values) { + throw new SlcException("Cannot override values map."); + } + + public void setUpdateValues(Map overrideValues) { + getValues().putAll(overrideValues); + } + + public void setUpdateExpectedValues( + Map overrideExpectedValues) { + getExpectedValues().putAll(overrideExpectedValues); + } + + public void setBasedon(String basedon) { + this.basedon = basedon; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java new file mode 100644 index 000000000..7aab47597 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java @@ -0,0 +1,40 @@ +package org.argeo.slc.ant.test; + +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.ant.spring.SpringArg; +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.test.TestResult; + +/** Ant tasks closing a given result. */ +public class SlcCloseTestResultTask extends SAwareTask { + private final static Log log = LogFactory + .getLog(SlcCloseTestResultTask.class); + + public List> results = new Vector>(); + + @Override + public void executeActions(String mode) { + if (!mode.equals(StructureRegistry.READ)) { + for (SpringArg result : results) { + try { + result.getInstance().close(); + } catch (RuntimeException e) { + log.error("Could not close result " + + (result.getBean() != null ? result.getBean() + : result.getAntref()), e); + } + } + } + } + + public SpringArg createResult() { + SpringArg result = new SpringArg(); + results.add(result); + return result; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java new file mode 100644 index 000000000..75877625d --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java @@ -0,0 +1,40 @@ +package org.argeo.slc.ant.test; + +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.test.TestReport; +import org.argeo.slc.core.test.TestResult; + +/** Ant tasks generating a report. */ +public class SlcReportTask extends SAwareTask { + private String result; + private String report; + + @Override + public void executeActions(String mode) { + if (!mode.equals(StructureRegistry.READ)) { + TestResult testResult = null; + if (result != null) { + testResult = (TestResult) getContext().getBean(result); + } + TestReport testReport = (TestReport) getContext().getBean(report); + if (testReport instanceof StructureAware) { + ((StructureAware) testReport).notifyCurrentPath(getRegistry(), + null); + } + testReport.generateTestReport(testResult); + } + } + + /** Sets the bean name of the result to close. */ + public void setResult(String bean) { + this.result = bean; + } + + /** Sets the bean name of the report to generate. */ + public void setReport(String report) { + this.report = report; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java new file mode 100644 index 000000000..66444f17e --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java @@ -0,0 +1,165 @@ +package org.argeo.slc.ant.test; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tools.ant.BuildException; +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.ant.spring.SpringArg; +import org.argeo.slc.ant.structure.SAwareTask; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.ExecutableTestRun; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.core.test.SimpleTestRun; +import org.argeo.slc.core.test.TestData; +import org.argeo.slc.core.test.TestDefinition; +import org.argeo.slc.core.test.TestResult; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.TestStatus; +import org.argeo.slc.core.test.WritableTestRun; +import org.argeo.slc.spring.SpringUtils; +import org.springframework.beans.BeansException; + +/** Ant task wrapping a test run. */ +public class SlcTestTask extends SAwareTask { + private Log log = LogFactory.getLog(SlcTestTask.class); + + private String testRunBean = null; + + private SpringArg testDefinitionArg; + private SpringArg testDataArg; + private SpringArg deployedSystemArg; + private SpringArg testResultArg; + + @Override + public void executeActions(String mode) throws BuildException { + // find test run + final String testRunBeanT; + if (testRunBean != null) { + testRunBeanT = testRunBean; + } else { + testRunBeanT = getProject().getProperty( + AntConstants.DEFAULT_TEST_RUN_PROPERTY); + } + WritableTestRun testRun = null; + + if (testRunBeanT != null) { + try { + testRun = (WritableTestRun) getContext().getBean(testRunBeanT); + if (log.isTraceEnabled()) + log.trace("Load test run bean from bean name " + + testRunBeanT); + } catch (BeansException e) { + // silent, will try defaults + } + } + + if (testRun == null) { + testRun = loadSingleFromContext(WritableTestRun.class); + if (testRun == null) { + testRun = new SimpleTestRun(); + log.trace("Created default simple test run"); + } else { + if (log.isTraceEnabled()) + log.trace("Load test run from scanning Spring context"); + } + } + + // set overridden references + if (testDataArg != null) { + testRun.setTestData(testDataArg.getInstance()); + log.trace("Overrides test data"); + } + + if (testDefinitionArg != null) { + testRun.setTestDefinition(testDefinitionArg.getInstance()); + log.trace("Overrides test definition"); + } + + if (deployedSystemArg != null) { + testRun.setDeployedSystem(deployedSystemArg.getInstance()); + log.trace("Overrides deployed system"); + } + + if (testResultArg != null) { + testRun.setTestResult(testResultArg.getInstance()); + log.trace("Overrides test result"); + } + + // notify path to test result + TestResult result = testRun.getTestResult(); + if (result == null) { + result = loadSingleFromContext(TestResult.class); + if (result == null) { + result = new SimpleTestResult(); + log.warn("Created default simple test result"); + } else { + if (log.isTraceEnabled()) + log.trace("Load test result from scanning Spring context"); + } + testRun.setTestResult(result); + } + + SlcExecution slcExecution = getSlcExecution(); + testRun.notifySlcExecution(slcExecution); + + if (result != null && result instanceof StructureAware) { + ((StructureAware) result).notifyCurrentPath( + getRegistry(), getTreeSPath()); + } + + try { + ((ExecutableTestRun) testRun).execute(); + } catch (RuntimeException e) { + if (result != null) { + SimpleResultPart errorPart = new SimpleResultPart( + TestStatus.ERROR, + "Unexpected exception when running test", e); + result.addResultPart(errorPart); + } + throw e; + } + } + + /** + * The bean name of the test run to use. If not set the default is used. + * + * @see SlcAntConfig + */ + public void setTestRun(String testRunBean) { + this.testRunBean = testRunBean; + } + + /** Creates sub tag. */ + public SpringArg createTestDefinition() { + testDefinitionArg = new SpringArg(); + // only test definitions can add to path + addSAwareArg(testDefinitionArg); + return testDefinitionArg; + } + + /** Creates sub tag. */ + public SpringArg createTestData() { + testDataArg = new SpringArg(); + return testDataArg; + } + + /** Creates sub tag. */ + public SpringArg createDeployedSystem() { + deployedSystemArg = new SpringArg(); + return deployedSystemArg; + } + + /** Creates sub tag. */ + public SpringArg createTestResult() { + testResultArg = new SpringArg(); + return testResultArg; + } + + protected T loadSingleFromContext(Class clss) { + return SpringUtils.loadSingleFromContext(getContext(), clss); + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html new file mode 100644 index 000000000..179159b39 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html @@ -0,0 +1,6 @@ + + + +Integration of SLC Test in Ant. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java new file mode 100644 index 000000000..7b28123c4 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java @@ -0,0 +1,34 @@ +package org.argeo.slc.ant.unit; + +import junit.framework.TestCase; + +import org.argeo.slc.ant.AntExecutionContext; +import org.argeo.slc.cli.DefaultSlcRuntime; +import org.argeo.slc.runtime.SlcExecutionOutput; + +public abstract class AntSlcApplicationTestCase extends TestCase implements + SlcExecutionOutput { + + /** To be overriden */ + public void postExecution(AntExecutionContext executionContext) { + + } + + protected String getRootDir() { + return System.getProperty("slc.rootDir", "src/main/slc/root"); + } + + protected String getAbsoluteScript(String relative) { + return getRootDir() + '/' + relative; + } + + protected void execute(String relativeScript) { + execute(relativeScript, null); + } + + protected void execute(String relativeScript, String targets) { + new DefaultSlcRuntime().executeScript( + getAbsoluteScript(relativeScript), targets, this); + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java new file mode 100644 index 000000000..bf6c0b603 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java @@ -0,0 +1,37 @@ +package org.argeo.slc.ant.unit; + +import java.io.File; +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 + implements SlcExecutionOutput { + protected void execute(String scriptPath) { + AntSlcApplication slcApp = new AntSlcApplication(); + slcApp.setRootDir(new FileSystemResource(new File("src/test/resources") + .getAbsolutePath() + + File.separator)); + slcApp.setWorkDir(new File(System.getProperty("java.io.tmpdir"))); + slcApp.setParentContext(getContext()); + + SlcExecution slcExecution = new SlcExecution(); + slcExecution.setUuid(UUID.randomUUID().toString()); + slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_FILE, + scriptPath); + slcExecution.setUser("user"); + + slcApp.execute(slcExecution, null, null, this); + } + + /** to be overridden */ + public void postExecution(AntExecutionContext executionContext) { + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java new file mode 100644 index 000000000..841a82301 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java @@ -0,0 +1,229 @@ +package org.argeo.slc.cli; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.ant.AntExecutionContext; +import org.argeo.slc.ant.AntSlcApplication; +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.runtime.SlcExecutionOutput; +import org.argeo.slc.spring.SpringUtils; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; + +public class DefaultSlcRuntime { + private final static Log log = LogFactory.getLog(DefaultSlcRuntime.class); + + public final static String SLC_ROOT_FILE_NAME = "slcRoot.properties"; + + /** + * Simplified execution with default runtime, default target, and no + * properties/reference arguments. + * + * @param script + * path to the script + * @param executionOutput + * output + * + * @see #executeScript(String, String, String, Properties, Map, + * SlcExecutionOutput) + */ + public void executeScript(String script, + SlcExecutionOutput executionOutput) { + executeScript(null, script, null, null, null, executionOutput); + } + + /** + * Simplified execution with default runtime, and no properties/reference + * arguments. + * + * @param script + * path to the script + * @param targets + * comma separated list of targets + * @param executionOutput + * output + * @see #executeScript(String, String, String, Properties, Map, + * SlcExecutionOutput) + */ + public void executeScript(String script, String targets, + SlcExecutionOutput executionOutput) { + executeScript(null, script, targets, null, null, executionOutput); + } + + public void executeScript(String runtime, String script, String targets, + Properties properties, Map references, + SlcExecutionOutput executionOutput) { + + Resource scriptRes = findScript(script); + Resource slcRootFile = findSlcRootFile(scriptRes); + if (slcRootFile == null) + throw new SlcException( + "Could not find any SLC root file, " + + "please configure one at the root of your scripts hierarchy."); + + SlcExecution slcExecution = createSlcExecution(runtime, slcRootFile, + scriptRes, targets); + + AntSlcApplication application = getApplication(slcRootFile); + application.execute(slcExecution, properties, references, + executionOutput); + } + + protected Resource findScript(String scriptStr) { + Resource scriptRes; + if (new File(scriptStr).exists()) { + scriptRes = new FileSystemResource(scriptStr); + } else { + scriptRes = new DefaultResourceLoader(SlcMain.class + .getClassLoader()).getResource(scriptStr); + } + return scriptRes; + } + + protected SlcExecution createSlcExecution(String runtimeStr, + Resource slcRootFile, Resource script, String targets) { + SlcExecution slcExecution = new SlcExecution(); + slcExecution.setUuid(UUID.randomUUID().toString()); + try { + slcExecution.setHost(InetAddress.getLocalHost().getHostName()); + } catch (UnknownHostException e) { + slcExecution.setHost(SlcExecution.UNKOWN_HOST); + } + + slcExecution.setType(AntConstants.EXECTYPE_SLC_ANT); + + slcExecution.setUser(System.getProperty("user.name")); + + if (runtimeStr != null) + slcExecution.getAttributes().put(AntConstants.EXECATTR_RUNTIME, + runtimeStr); + String scriptRelativePath = SpringUtils.extractRelativePath(SpringUtils + .getParent(slcRootFile), script); + + slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_FILE, + scriptRelativePath); + if (targets != null) + slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_TARGETS, + targets); + + slcExecution.setStatus(SlcExecution.STATUS_SCHEDULED); + return slcExecution; + } + + protected AntSlcApplication getApplication(Resource slcRootFile) { + AntSlcApplication application = new AntSlcApplication(); + InputStream inRootFile = null; + try { + // Remove basedir property in order to avoid conflict with Maven + // if (all.containsKey("basedir")) + // all.remove("basedir"); + + inRootFile = slcRootFile.getInputStream(); + Properties rootProps = loadFile(inRootFile); + + Resource confDir = null; + File workDir = null; + // Root dir + final Resource rootDir = SpringUtils.getParent(slcRootFile); + + // Conf dir + String confDirStr = rootProps + .getProperty(AntConstants.CONF_DIR_PROPERTY); + if (confDirStr != null) + confDir = new DefaultResourceLoader(application.getClass() + .getClassLoader()).getResource(confDirStr); + + if (confDir == null || !confDir.exists()) { + // confDir = rootDir.createRelative("../conf"); + confDir = SpringUtils.getParent(rootDir) + .createRelative("conf/"); + } + + // Work dir + String workDirStr = rootProps + .getProperty(AntConstants.WORK_DIR_PROPERTY); + if (workDirStr != null) { + workDir = new File(workDirStr); + } + + if (workDir == null || !workDir.exists()) { + try { + File rootDirAsFile = rootDir.getFile(); + workDir = new File(rootDirAsFile.getParent() + + File.separator + "work").getCanonicalFile(); + } catch (IOException e) { + workDir = new File(System.getProperty("java.io.tmpdir") + + File.separator + "slcExecutions" + File.separator + + slcRootFile.getURL().getPath()); + log.debug("Root dir is not a file: " + e.getMessage() + + ", creating work dir in temp: " + workDir); + } + workDir.mkdirs(); + } + + application.setConfDir(confDir); + application.setRootDir(rootDir); + application.setWorkDir(workDir); + + return application; + } catch (IOException e) { + throw new SlcException( + "Could not prepare SLC application for root file " + + slcRootFile, e); + } finally { + IOUtils.closeQuietly(inRootFile); + } + } + + /** + * Recursively scans directories downwards until it find a file name as + * defined by {@link #SLC_ROOT_FILE_NAME}. + */ + protected Resource findSlcRootFile(Resource currDir) { + if (log.isTraceEnabled()) + log.trace("Look for SLC root file in " + currDir); + + try { + Resource slcRootFile = currDir.createRelative(SLC_ROOT_FILE_NAME); + if (slcRootFile.exists()) { + if (log.isDebugEnabled()) + log.debug("Found SLC root file: " + slcRootFile); + return slcRootFile; + } else { + String currPath = currDir.getURL().getPath(); + if (currPath.equals("/") || currPath.equals("")) { + return null; + } else { + return findSlcRootFile(SpringUtils.getParent(currDir)); + } + } + } catch (IOException e) { + throw new SlcException("Problem when looking in SLC root file in " + + currDir, e); + } + } + + /** Loads the content of a file as Properties. */ + private Properties loadFile(InputStream in) { + Properties p = new Properties(); + try { + p.load(in); + } catch (IOException e) { + throw new SlcException("Cannot read SLC root file", e); + } + return p; + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java new file mode 100644 index 000000000..cf52581c8 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java @@ -0,0 +1,232 @@ +package org.argeo.slc.cli; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.ant.AntConstants; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.logging.Log4jUtils; + +public class SlcMain { + public enum Mode { + single, agent + } + + private static Log log = null; + + private final static String BOOTSTRAP_LOG4J_CONFIG = "org/argeo/slc/cli/bootstrapLog4j.properties"; + + private final static Option modeOpt = OptionBuilder.withLongOpt("mode") + .withArgName("mode").hasArg().withDescription( + "SLC execution mode, one of: " + listModeValues()).create( + 'm'); + + private final static Option propertyOpt = OptionBuilder.withLongOpt( + "property").withArgName("prop1=val1,prop2=val2").hasArgs() + .withValueSeparator(',').withDescription( + "use value for given property").create('p'); + + private final static Option propertiesOpt = OptionBuilder.withLongOpt( + "properties").withArgName("properties file").hasArgs() + .withValueSeparator(',').withDescription( + "load properties from file (-p has priority)").create('P'); + + private final static Option scriptOpt = OptionBuilder.withLongOpt("script") + .withArgName("script").hasArg().withDescription( + "SLC script to execute").create('s'); + + private final static Option targetsOpt = OptionBuilder.withLongOpt( + "targets").withArgName("targets").hasArg().withDescription( + "Targets to execute").create('t'); + + private final static Option runtimeOpt = OptionBuilder.withLongOpt( + "runtime").withArgName("runtime").hasArg().withDescription( + "Runtime to use, either a full path or relative to slc app conf dir: " + + "/runtime//.xml").create('r'); + + private final static Options options; + + private final static String commandName = "slc"; + + static { + options = new Options(); + options.addOption(modeOpt); + options.addOption(scriptOpt); + options.addOption(targetsOpt); + options.addOption(propertyOpt); + options.addOption(propertiesOpt); + options.addOption(runtimeOpt); + } + + public static void main(String[] args) { + Mode mode = null; + Properties properties = new Properties(); + String script = null; + String targets = null; + String runtimeStr = null; + + try { + + CommandLineParser clParser = new GnuParser(); + CommandLine cl = clParser.parse(options, args); + + // Mode + String modeStr = cl.getOptionValue(modeOpt.getOpt()); + if (modeStr == null) { + mode = Mode.single; + } else { + try { + mode = Mode.valueOf(modeStr); + } catch (IllegalArgumentException e) { + throw new SlcException("Unrecognized mode '" + modeStr + + "'", e); + } + } + + // Script + if (mode.equals(Mode.single)) { + if (!cl.hasOption(scriptOpt.getOpt())) + throw new SlcException("Mode " + Mode.single + + " requires option '" + scriptOpt.getLongOpt() + + "'"); + script = cl.getOptionValue(scriptOpt.getOpt()); + + // Targets + if (cl.hasOption(targetsOpt.getOpt())) + targets = cl.getOptionValue(targetsOpt.getOpt()); + } + + // Properties + if (cl.hasOption(propertiesOpt.getOpt())) { + for (String propertyFile : cl.getOptionValues(propertiesOpt + .getOpt())) { + loadPropertyFile(properties, propertyFile); + } + } + if (cl.hasOption(propertyOpt.getOpt())) { + for (String property : cl.getOptionValues(propertyOpt.getOpt())) { + addProperty(properties, property); + } + } + + // Runtime + if (cl.hasOption(runtimeOpt.getOpt())) { + runtimeStr = cl.getOptionValue(runtimeOpt.getOpt()); + } + } catch (ParseException e) { + System.err.println("Problem with command line arguments. " + + e.getMessage()); + badExit(); + } catch (SlcException e) { + System.err.println(e.getMessage()); + badExit(); + } catch (Exception e) { + System.err.println("Unexpected exception when bootstrapping."); + e.printStackTrace(); + badExit(); + } + + // Initializes logging and log arguments + initLogging(properties); + if (log.isDebugEnabled()) { + log.debug("Mode: " + mode); + if (runtimeStr != null) + log.debug("Runtime: " + runtimeStr); + log.debug("User properties: " + properties); + if (script != null) + log.debug("Script: " + script); + if (targets != null) + log.debug("Targets: " + targets); + } + + // Execution + if (mode.equals(Mode.single)) { + try { + DefaultSlcRuntime runtime = new DefaultSlcRuntime(); + runtime.executeScript(runtimeStr, script, targets, properties, + null, null); + //System.exit(0); + } catch (SlcException e) { + log.error("SLC client terminated with an error: ", e); + System.exit(1); + } + } + } + + public static void printUsage() { + new HelpFormatter().printHelp(commandName, options, true); + } + + private static String listModeValues() { + StringBuffer buf = new StringBuffer(""); + for (Mode mode : Mode.values()) { + buf.append(mode).append(", "); + } + String str = buf.toString(); + // unsafe, but there will be at least one value in the enum + return str.substring(0, str.length() - 2); + } + + protected static void addProperty(Properties properties, String property) { + int eqIndex = property.indexOf('='); + if (eqIndex == 0) + throw new SlcException("Badly formatted property " + property); + + if (eqIndex > 0) { + String key = property.substring(0, eqIndex); + String value = property.substring(eqIndex + 1); + properties.setProperty(key, value); + + } else { + properties.setProperty(property, "true"); + } + } + + protected static void loadPropertyFile(Properties properties, + String propertyFile) { + FileInputStream in = null; + try { + in = new FileInputStream(propertyFile); + properties.load(in); + } catch (Exception e) { + throw new SlcException("Could not load proeprty file " + + propertyFile); + } finally { + IOUtils.closeQuietly(in); + } + } + + private static void initLogging(Properties userProperties) { + System.setProperty("log4j.defaultInitOverride", "true"); + + // Add log4j user properties to System properties + for (Object obj : userProperties.keySet()) { + String key = obj.toString(); + if (key.startsWith("log4j.")) { + System.setProperty(key, userProperties.getProperty(key)); + } + } + Log4jUtils.initLog4j(System.getProperty("log4j.configuration", + "classpath:" + BOOTSTRAP_LOG4J_CONFIG)); + log = LogFactory.getLog(SlcMain.class); + + } + + private static void badExit() { + printUsage(); + System.exit(1); + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java new file mode 100644 index 000000000..ee471cce3 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java @@ -0,0 +1,7 @@ +package org.argeo.slc.lib.detached; + +import org.argeo.slc.core.test.context.DefaultContextTestData; + +public class DetachedTestData extends DefaultContextTestData { + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java new file mode 100644 index 000000000..becb4f8ce --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java @@ -0,0 +1,144 @@ +package org.argeo.slc.lib.detached; + +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.tree.TreeSRelatedHelper; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.TestDefinition; +import org.argeo.slc.core.test.TestResult; +import org.argeo.slc.core.test.TestRun; +import org.argeo.slc.core.test.TestStatus; +import org.argeo.slc.core.test.context.ContextUtils; +import org.argeo.slc.detached.DetachedAnswer; +import org.argeo.slc.detached.DetachedClient; +import org.argeo.slc.detached.DetachedRequest; +import org.argeo.slc.detached.DetachedStep; +import org.argeo.slc.detached.ui.UiStep; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanReference; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +public class DetachedTestDefinition extends TreeSRelatedHelper implements + TestDefinition, BeanNameAware, BeanFactoryAware, InitializingBean { + private final static Log log = LogFactory + .getLog(DetachedTestDefinition.class); + + private DetachedStep step; + private DetachedClient client; + + // Spring properties + private String testDefBeanName = null; + private BeanDefinitionRegistry beanDefinitionRegistry = null; + private String stepRef = null; + + public void execute(TestRun testRun) { + // Look for step bean name + String stepBeanNameT = null; + if (this.stepRef == null && step != null) { + if (step instanceof UiStep) { + stepBeanNameT = ((UiStep) step).getBeanName(); + } else { + // Introspects bean factory in order to find step bean name + BeanDefinition thisBeanDef = beanDefinitionRegistry + .getBeanDefinition(testDefBeanName); + PropertyValue propValue = thisBeanDef.getPropertyValues() + .getPropertyValue("step"); + Object stepBeanRef = propValue.getValue(); + BeanReference ref = (BeanReference) stepBeanRef; + stepBeanNameT = ref.getBeanName(); + } + } else if (this.stepRef != null) { + stepBeanNameT = this.stepRef; + } + + // Execute + DetachedRequest request = new DetachedRequest(); + request.setPath(getBasePath().toString()); + request.setUuid(UUID.randomUUID().toString()); + request.setRef(stepBeanNameT); + + DetachedTestData testData = testRun.getTestData(); + if (testData != null) { + Map values = testData.getValues(); + Properties inputParameters = new Properties(); + inputParameters.putAll(values);// TODO: check conversions to string + request.setProperties(inputParameters); + } + + try { + client.sendRequest(request); + } catch (Exception e) { + throw new SlcException("Could not send request for step " + + stepBeanNameT, e); + } + + try { + DetachedAnswer answer = client.receiveAnswer(); + if (answer.getStatus() == DetachedAnswer.ERROR) + throw new SlcException("Error when executing step " + + answer.getUuid() + ": " + answer.getLog()); + else + log.info("Received answer for '" + request.getRef() + "' (" + + answer.getStatusAsString() + "):" + answer.getLog()); + + if (testData != null) { + Properties outputParameters = answer.getProperties(); + for (Object key : outputParameters.keySet()) + testData.getValues().put(key.toString(), + outputParameters.get(key)); + } + } catch (Exception e) { + throw new SlcException("Could not receive answer #" + + request.getUuid() + " for step " + stepBeanNameT, e); + } + + if (testData != null) { + ContextUtils.compareReachedExpected(testData, testRun + .getTestResult(), this); + } else { + ((TestResult)testRun.getTestResult()).addResultPart( + new SimpleResultPart(TestStatus.PASSED, "Step " + + stepBeanNameT + " executed successfully")); + } + } + + public void setBeanName(String name) { + this.testDefBeanName = name; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + if (beanFactory instanceof BeanDefinitionRegistry) + beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory; + else + throw new BeanInitializationException( + "Require BeanDefinitionRegistry"); + } + + public void afterPropertiesSet() throws Exception { + } + + public void setStep(DetachedStep step) { + this.step = step; + } + + public void setClient(DetachedClient client) { + this.client = client; + } + + public void setStepRef(String stepBeanName) { + this.stepRef = stepBeanName; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java new file mode 100644 index 000000000..799b4739c --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java @@ -0,0 +1,68 @@ +package org.argeo.slc.lib.detached; + +import java.io.IOException; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.detached.DetachedAnswer; +import org.argeo.slc.detached.DetachedCommunication; +import org.argeo.slc.detached.DetachedException; +import org.argeo.slc.detached.DetachedRequest; +import org.argeo.slc.detached.DetachedXmlConverter; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.XmlMappingException; +import org.springframework.xml.validation.XmlValidator; +import org.xml.sax.InputSource; + +public class DetachedXmlConverterSpring implements DetachedXmlConverter { + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + public void marshallCommunication(DetachedCommunication detCom, + Result result) { + if (detCom instanceof DetachedRequest) { + marshallRequest((DetachedRequest) detCom, result); + } else if (detCom instanceof DetachedAnswer) { + marshallAnswer((DetachedAnswer) detCom, result); + } else { + throw new DetachedException("Unkown communication type " + + detCom.getClass()); + } + } + + public DetachedCommunication unmarshallCommunication(Source source) { + try { + return (DetachedCommunication) unmarshaller.unmarshal(source); + } catch (Exception e) { + throw new SlcException("Could not unmarshall", e); + } + } + + public void marshallRequest(DetachedRequest request, Result result) { + try { + marshaller.marshal(request, result); + } catch (Exception e) { + throw new SlcException("Could not marshall", e); + } + } + + public void marshallAnswer(DetachedAnswer answer, Result result) { + try { + marshaller.marshal(answer, result); + } catch (Exception e) { + throw new SlcException("Could not marshall", e); + } + } + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java new file mode 100644 index 000000000..744aa2c9e --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java @@ -0,0 +1,73 @@ +package org.argeo.slc.maven; + +import java.io.File; +import java.net.URL; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.ant.AntRunner; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.deploy.DeployEnvironment; + +public class MavenDeployEnvironment {/*implements DeployEnvironment { + private static final Log log = LogFactory + .getLog(MavenDeployEnvironment.class); + private MavenManager mavenManager; + + public void unpackTo(Object packg, File targetLocation, + Map filter) { + File packageLocation; + String type = null; + String removeRootDir = "enabled"; + if (packg instanceof MavenFile) { + packageLocation = mavenManager + .getPackageLocation((MavenFile) packg); + type = ((MavenFile) packg).getType(); + } else if (packg instanceof File) { + packageLocation = (File) packg; + // TODO: type based on extension + } else { + throw new SlcException("Unrecognized package type " + + packg.getClass()); + } + if (log.isDebugEnabled()) { + log.debug("Unpack " + packageLocation + " of type " + type + " to " + + targetLocation); + } + + try { + File tempDir = new File("/tmp/" + UUID.randomUUID().toString()); + tempDir.mkdirs(); + targetLocation.mkdirs(); + Properties props = new Properties(); + props.setProperty("dest", targetLocation.getAbsolutePath()); + props.setProperty("src", packageLocation.getAbsolutePath()); + props.setProperty("tempDir", tempDir.getAbsolutePath()); + props.setProperty("removeRootDir", removeRootDir); + + URL antUrl = getClass().getClassLoader().getResource( + "org/argeo/slc/support/deploy/ant/build.xml"); + + if (type == null || type.equals("zip")) { + new AntRunner(antUrl, "deployZip", props).run(); + } else if (type.equals("tar.gz")) { + new AntRunner(antUrl, "deployTarGz", props).run(); + } else { + throw new SlcException("Unknow package type " + type); + } + } catch (SlcException e) { + throw e; + } catch (Exception e) { + throw new SlcException("Cannot unpack package " + packg + " to " + + targetLocation, e); + } + } + + public void setMavenManager(MavenManager mavenManager) { + this.mavenManager = mavenManager; + } +*/ +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java new file mode 100644 index 000000000..31c6385a6 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java @@ -0,0 +1,63 @@ +package org.argeo.slc.maven; + +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeploymentData; + +public class MavenFile implements Distribution, DeploymentData { + private String groupId; + private String artifactId; + private String version; + private String type; + private String classifier; + + private String distributionId; + + public String getDistributionId() { + return distributionId; + } + + public void setDistributionId(String distributionId) { + this.distributionId = distributionId; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getClassifier() { + return classifier; + } + + public void setClassifier(String classifier) { + this.classifier = classifier; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java new file mode 100644 index 000000000..9908c3b8b --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java @@ -0,0 +1,104 @@ +package org.argeo.slc.maven; + +import java.io.File; +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.maven.artifact.Artifact; +//import org.apache.maven.artifact.repository.ArtifactRepository; +//import org.apache.maven.embedder.MavenEmbedder; +//import org.apache.maven.embedder.MavenEmbedderException; + +import org.argeo.slc.core.SlcException; + +public class MavenManager {/* FIXME + private final Log log = LogFactory.getLog(getClass()); + + private String localRepositoryPath; + + private ArtifactRepository localRepository; + private List remoteRepositoriesInternal; + private List remoteRepositories = new Vector(); + + private MavenEmbedder mavenEmbedder; + + public void init() { + try { + mavenEmbedder = new MavenEmbedder(); + mavenEmbedder.setOffline(true); + mavenEmbedder.setClassLoader(Thread.currentThread() + .getContextClassLoader()); + mavenEmbedder.start(); + + mavenEmbedder.setLocalRepositoryDirectory(new File( + localRepositoryPath)); + + localRepository = mavenEmbedder.getLocalRepository(); + + remoteRepositoriesInternal = new Vector(); + for (RemoteRepository remoteRepository : remoteRepositories) { + + ArtifactRepository repository = mavenEmbedder.createRepository( + remoteRepository.getUrl(), remoteRepository.getId()); + remoteRepositoriesInternal.add(repository); + } + + } catch (Exception e) { + throw new SlcException("Cannot initialize Maven manager", e); + } + } + + private Artifact resolve(MavenFile mavenDistribution) { + try { + Artifact artifact; + if (mavenDistribution.getClassifier() == null) { + artifact = mavenEmbedder.createArtifact(mavenDistribution + .getGroupId(), mavenDistribution.getArtifactId(), + mavenDistribution.getVersion(), + Artifact.SCOPE_PROVIDED, mavenDistribution.getType()); + } else { + artifact = mavenEmbedder.createArtifactWithClassifier( + mavenDistribution.getGroupId(), mavenDistribution + .getArtifactId(), mavenDistribution + .getVersion(), mavenDistribution.getType(), + mavenDistribution.getClassifier()); + } + + mavenEmbedder.resolve(artifact, remoteRepositoriesInternal, + localRepository); + + return artifact; + } catch (Exception e) { + throw new SlcException("Cannot resolve artifact.", e); + } + } + + public File getPackageLocation(MavenFile mavenDistribution) { + return resolve(mavenDistribution).getFile(); + } + + public void destroy() { + try { + if (mavenEmbedder != null) { + mavenEmbedder.stop(); + } + } catch (MavenEmbedderException e) { + log.error("Cannot destroy Maven manager", e); + } + } + + public void setLocalRepositoryPath(String localRepositoryPath) { + this.localRepositoryPath = localRepositoryPath; + } + + public List getRemoteRepositories() { + return remoteRepositories; + } + + public void setRemoteRepositories(List remoteRepositories) { + this.remoteRepositories = remoteRepositories; + } +*/ +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java new file mode 100644 index 000000000..cbf027c74 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java @@ -0,0 +1,23 @@ +package org.argeo.slc.maven; + +public class RemoteRepository { + private String id; + private String url; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java new file mode 100644 index 000000000..05861d940 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java @@ -0,0 +1,88 @@ +package org.argeo.slc.ws.client; + +import java.io.IOException; + +import javax.xml.transform.Source; + +import org.springframework.ws.client.WebServiceClientException; +import org.springframework.ws.client.WebServiceIOException; +import org.springframework.ws.client.support.interceptor.ClientInterceptor; +import org.springframework.ws.context.MessageContext; +import org.springframework.xml.validation.XmlValidator; +import org.xml.sax.SAXParseException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ValidatingClientInterceptor implements ClientInterceptor { + private final static Log log = LogFactory + .getLog(ValidatingClientInterceptor.class); + + private Boolean validateRequest = true; + private Boolean validateResponse = false; + private XmlValidator validator = null; + + public boolean handleFault(MessageContext messageContext) + throws WebServiceClientException { + return true; + } + + public boolean handleRequest(MessageContext messageContext) + throws WebServiceClientException { + if (validateRequest) { + if (messageContext.getRequest() == null) + return true; + + Source source = messageContext.getRequest().getPayloadSource(); + try { + return validate(source); + } catch (IOException e) { + throw new WebServiceIOException("Cannot validate request", e); + } + } else { + return true; + } + } + + public boolean handleResponse(MessageContext messageContext) + throws WebServiceClientException { + if (validateResponse) { + if (messageContext.getResponse() == null) + return true; + + Source source = messageContext.getResponse().getPayloadSource(); + try { + return validate(source); + } catch (IOException e) { + throw new WebServiceIOException("Cannot validate response", e); + } + } else { + return true; + } + } + + protected boolean validate(Source source) throws IOException { + SAXParseException[] exceptions = validator.validate(source); + if (exceptions.length != 0) { + for (SAXParseException ex : exceptions) { + log.error(ex.getMessage()); + } + return false; + } else { + return true; + } + } + + public void setValidateRequest(Boolean validateRequest) { + this.validateRequest = validateRequest; + } + + public void setValidateResponse(Boolean validateResponse) { + this.validateResponse = validateResponse; + } + + public void setValidator(XmlValidator validator) { + this.validator = validator; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java new file mode 100644 index 000000000..43ad31306 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java @@ -0,0 +1,84 @@ +package org.argeo.slc.ws.client; + +import java.util.Iterator; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.soap.SoapFaultDetail; +import org.springframework.ws.soap.SoapFaultDetailElement; +import org.springframework.ws.soap.client.SoapFaultClientException; +import org.springframework.xml.transform.StringResult; +import org.w3c.dom.Node; + +public abstract class WebServiceUtils { + private final static Log log = LogFactory.getLog(WebServiceUtils.class); + + public static Object marshalSendAndReceiveSafe(WebServiceTemplate template, + Object req) { + try { + Object resp = marshalSendAndReceive(template, req); + return resp; + } catch (Exception e) { + log.error("Cannot send web servicerequest: " + e.getMessage()); + if (log.isDebugEnabled()) { + log.debug("Webservice exception details: ", e); + } + return null; + } + } + + public static Object marshalSendAndReceive(WebServiceTemplate template, + Object req) { + if (log.isTraceEnabled()) { + try { + StringResult result = new StringResult(); + template.getMarshaller().marshal(req, result); + log.trace("About to send " + result); + } catch (Exception e) { + log.error("Cannot marshall " + req + " for logging", e); + } + } + Object resp = template.marshalSendAndReceive(req); + return resp; + } + + public static void manageSoapException(SoapFaultClientException e) { + log + .error("WS root cause: " + + e.getSoapFault().getFaultStringOrReason()); + if (log.isTraceEnabled()) { + StringBuffer stack = new StringBuffer(""); + SoapFaultDetail detail = e.getSoapFault().getFaultDetail(); + if (detail != null) { + Iterator it = (Iterator) detail + .getDetailEntries(); + while (it.hasNext()) { + SoapFaultDetailElement elem = it.next(); + if (elem.getName().getLocalPart().equals("StackElement")) { + Source source = elem.getSource(); + if (source instanceof DOMSource) { + Node node = ((DOMSource) source).getNode(); + // stack.append(node.getTextContent()).append('\n'); + stack + .append( + node.getChildNodes().item(0) + .getNodeValue()).append( + '\n'); + } + } + } + + if (stack.length() > 0) + log.error("WS root cause stack: " + stack); + } + } + } + + private WebServiceUtils() { + + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java new file mode 100644 index 000000000..21bcf978a --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java @@ -0,0 +1,118 @@ +package org.argeo.slc.ws.process; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionNotifier; +import org.argeo.slc.core.process.SlcExecutionStep; +import org.argeo.slc.msg.process.SlcExecutionRequest; +import org.argeo.slc.msg.process.SlcExecutionStatusRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; +import org.argeo.slc.ws.client.WebServiceUtils; +import org.springframework.ws.client.WebServiceIOException; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.soap.client.SoapFaultClientException; + +public class WebServiceSlcExecutionNotifier implements SlcExecutionNotifier { + private WebServiceTemplate template; + + private Log log = LogFactory.getLog(getClass()); + + private Boolean cannotConnect = false; + + public void newExecution(SlcExecution slcExecution) { + if (cannotConnect) + return; + + SlcExecutionRequest req = new SlcExecutionRequest(); + req.setSlcExecution(slcExecution); + try { + WebServiceUtils.marshalSendAndReceive(template, req); + if (log.isTraceEnabled()) + log.trace("Notified creation of slc execution " + + slcExecution.getUuid()); + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void updateExecution(SlcExecution slcExecution) { + if (cannotConnect) + return; + + SlcExecutionRequest req = new SlcExecutionRequest(); + req.setSlcExecution(slcExecution); + try { + WebServiceUtils.marshalSendAndReceive(template, req); + if (log.isTraceEnabled()) + log.trace("Notified update of slc execution " + + slcExecution.getUuid()); + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void updateStatus(SlcExecution slcExecution, String oldStatus, + String newStatus) { + if (cannotConnect) + return; + + SlcExecutionStatusRequest req = new SlcExecutionStatusRequest( + slcExecution.getUuid(), newStatus); + try { + WebServiceUtils.marshalSendAndReceive(template, req); + if (log.isTraceEnabled()) + log.trace("Notified status update of slc execution " + + slcExecution.getUuid()); + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void addSteps(SlcExecution slcExecution, + List additionalSteps) { + if (cannotConnect) + return; + + SlcExecutionStepsRequest req = new SlcExecutionStepsRequest(); + req.setSlcExecutionUuid(slcExecution.getUuid()); + req.setSteps(additionalSteps); + if (log.isTraceEnabled()) { + for (SlcExecutionStep step : additionalSteps) { + log.trace("Step " + step.getUuid() + ": " + step.logAsString()); + } + } + + try { + WebServiceUtils.marshalSendAndReceive(template, req); + if (log.isTraceEnabled()) + log.trace("Added steps to slc execution " + + slcExecution.getUuid()); + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void setTemplate(WebServiceTemplate template) { + this.template = template; + } + + protected void manageIoException(WebServiceIOException e) { + if (!cannotConnect) { + log.error("Cannot connect to " + template.getDefaultUri() + + ". Won't try again.", e); + cannotConnect = true; + } + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java new file mode 100644 index 000000000..eba0b1517 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java @@ -0,0 +1,109 @@ +package org.argeo.slc.ws.test.tree; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.test.TestResultListener; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.tree.TreeTestResult; +import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest; +import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest; +import org.argeo.slc.msg.test.tree.ResultPartRequest; +import org.argeo.slc.ws.client.WebServiceUtils; +import org.springframework.ws.client.WebServiceIOException; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.soap.client.SoapFaultClientException; + +public class WebServiceTreeTestResultNotifier implements + TestResultListener { + private WebServiceTemplate template; + private Boolean onlyOnClose = false; + + private Log log = LogFactory.getLog(getClass()); + + private Boolean cannotConnect = false; + + public void resultPartAdded(TreeTestResult testResult, + TestResultPart testResultPart) { + if (onlyOnClose) + return; + + if (cannotConnect) + return; + + try { + if (testResult.getResultParts().size() == 1 + && testResult.getResultParts().values().iterator().next() + .getParts().size() == 1) { + CreateTreeTestResultRequest req = new CreateTreeTestResultRequest( + testResult); + + if (log.isDebugEnabled()) + log.debug("Send create result request for result " + + testResult.getUuid()); + + WebServiceUtils.marshalSendAndReceive(template, req); + } else { + ResultPartRequest req = new ResultPartRequest(testResult); + + if (log.isDebugEnabled()) + log.debug("Send result parts for result " + + testResult.getUuid()); + + WebServiceUtils.marshalSendAndReceive(template, req); + } + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void close(TreeTestResult testResult) { + if (cannotConnect) + return; + + try { + if (onlyOnClose) { + CreateTreeTestResultRequest req = new CreateTreeTestResultRequest( + testResult); + + if (log.isDebugEnabled()) + log.debug("Send create result request for result " + + testResult.getUuid()); + + WebServiceUtils.marshalSendAndReceive(template, req); + } else { + CloseTreeTestResultRequest req = new CloseTreeTestResultRequest( + testResult); + + if (log.isDebugEnabled()) + log.debug("Send close result request for result " + + testResult.getUuid()); + + WebServiceUtils.marshalSendAndReceive(template, req); + + } + } catch (SoapFaultClientException e) { + WebServiceUtils.manageSoapException(e); + } catch (WebServiceIOException e) { + manageIoException(e); + } + } + + public void setTemplate(WebServiceTemplate template) { + this.template = template; + } + + public void setOnlyOnClose(Boolean onlyOnClose) { + this.onlyOnClose = onlyOnClose; + } + + protected void manageIoException(WebServiceIOException e) { + if (!cannotConnect) { + log.error("Cannot connect to " + template.getDefaultUri() + + ". Won't try again.", e); + cannotConnect = true; + } + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF b/runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..d445f26aa --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,124 @@ +Manifest-Version: 1.0 +Export-Package: org.argeo.slc.ws.client;uses:="org.springframework.ws. + client.core,org.springframework.oxm,org.apache.commons.logging,org.sp + ringframework.ws,org.springframework.ws.soap,org.springframework.ws.c + ontext,org.springframework.xml.transform,org.springframework.ws.clien + t,javax.xml.transform.dom,org.w3c.dom,org.springframework.xml.validat + ion,javax.xml.namespace,org.xml.sax,javax.xml.transform,org.springfra + mework.ws.soap.client,org.springframework.ws.client.support.intercept + or";version="0.11.2.SNAPSHOT",org.argeo.slc.ws.client.spring;version= + "0.11.2.SNAPSHOT",org.argeo.slc.ant.detached;uses:="org.argeo.slc.ant + .spring,org.apache.commons.logging,org.argeo.slc.core,org.argeo.slc.s + pring,org.springframework.context,org.argeo.slc.detached,org.argeo.sl + c.ant.structure,org.springframework.beans.factory";version="0.11.2.SN + APSHOT",org.argeo.slc.ws.test.tree;uses:="org.springframework.ws.clie + nt.core,org.apache.commons.logging,org.argeo.slc.msg.test.tree,org.ar + geo.slc.ws.client,org.springframework.ws.soap.client,org.springframew + ork.ws.client,org.argeo.slc.core.test.tree,org.argeo.slc.core.test";v + ersion="0.11.2.SNAPSHOT",org.argeo.slc.maven;uses:="org.argeo.slc.cor + e.build,org.argeo.slc.core.deploy";version="0.11.2.SNAPSHOT",org.arge + o.slc.ant.structure;uses:="org.argeo.slc.core.structure,org.argeo.slc + .ant.spring,org.argeo.slc.core,org.springframework.context,org.apache + .tools.ant,org.argeo.slc.core.structure.tree";version="0.11.2.SNAPSHO + T",org.argeo.slc.ant.unit;uses:="org.argeo.slc.ant,junit.framework,or + g.argeo.slc.unit,org.argeo.slc.runtime,org.argeo.slc.cli,org.springfr + amework.core.io,org.springframework.context,org.argeo.slc.core.proces + s";version="0.11.2.SNAPSHOT",org.argeo.slc.ant.deploy;uses:="org.arge + o.slc.ant.spring,org.apache.commons.logging,org.argeo.slc.core,org.ar + geo.slc.core.build,org.springframework.context,org.argeo.slc.core.dep + loy,org.argeo.slc.ant.structure,org.apache.tools.ant";version="0.11.2 + .SNAPSHOT",org.argeo.slc.ant.spring;uses:="org.apache.commons.logging + ,org.argeo.slc.core,org.springframework.beans,org.apache.tools.ant.ty + pes,org.springframework.context,org.argeo.slc.core.process,org.apache + .tools.ant,org.springframework.beans.factory";version="0.11.2.SNAPSHO + T",org.argeo.slc.ant;uses:="org.apache.commons.logging,org.apache.log + 4j,org.springframework.context.support,org.apache.log4j.spi,org.sprin + gframework.beans.factory.config,org.springframework.beans.factory.sup + port,org.argeo.slc.core.structure,org.argeo.slc.core,org.apache.tools + .ant.util,org.apache.commons.io,org.argeo.slc.core.process,org.argeo. + slc.core.structure.tree,org.springframework.beans.factory,org.apache. + tools.ant.helper,org.springframework.util,org.springframework.core.io + ,org.springframework.context,org.argeo.slc.logging,org.springframewor + k.beans.factory.xml,org.apache.tools.ant,org.argeo.slc.runtime";versi + on="0.11.2.SNAPSHOT",org.argeo.slc.lib.detached;uses:="org.springfram + ework.oxm,org.apache.commons.logging,org.argeo.slc.detached.ui,org.sp + ringframework.beans,org.argeo.slc.detached,org.springframework.beans. + factory.config,org.argeo.slc.core.test,org.springframework.beans.fact + ory.support,org.argeo.slc.core,org.argeo.slc.core.test.context,javax. + xml.transform,org.argeo.slc.core.structure.tree,org.springframework.b + eans.factory";version="0.11.2.SNAPSHOT",org.argeo.slc.ws.process;uses + :="org.springframework.ws.client.core,org.apache.commons.logging,org. + argeo.slc.ws.client,org.springframework.ws.client,org.springframework + .ws.soap.client,org.argeo.slc.core.process,org.argeo.slc.msg.process" + ;version="0.11.2.SNAPSHOT",org.argeo.slc.cli;uses:="org.apache.common + s.logging,org.apache.commons.cli,org.springframework.core.io,org.arge + o.slc.logging,org.argeo.slc.ant,org.argeo.slc.core,org.argeo.slc.spri + ng,org.argeo.slc.runtime,org.apache.commons.io,org.argeo.slc.core.pro + cess";version="0.11.2.SNAPSHOT",org.argeo.slc.ant.test;uses:="org.apa + che.commons.logging,org.springframework.beans,org.springframework.con + text,org.argeo.slc.ant.structure,org.apache.tools.ant,org.argeo.slc.c + ore.test,org.argeo.slc.core.structure,org.argeo.slc.ant.spring,org.ar + geo.slc.core,org.argeo.slc.core.test.context,org.argeo.slc.spring,org + .apache.tools.ant.types,org.argeo.slc.core.deploy,org.argeo.slc.core. + process,org.argeo.slc.core.structure.tree,org.springframework.beans.f + actory";version="0.11.2.SNAPSHOT",org.argeo.slc.support.deploy.ant;ve + rsion="0.11.2.SNAPSHOT" +Tool: Bnd-0.0.255 +Bundle-Name: Argeo SLC Agent +Created-By: 1.6.0 (Sun Microsystems Inc.) +Bundle-Vendor: Argeo +Bundle-Version: 0.11.2.SNAPSHOT +Bundle-ManifestVersion: 2 +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-Description: SLC Distribution +Import-Package: javax.xml.namespace;version="1.3",javax.xml.transform; + version="1.3",javax.xml.transform.dom;version="1.3",junit.framework;v + ersion="3.8",org.apache.commons.cli;resolution:=optional;version="1.1 + ",org.apache.commons.io;version="1.4",org.apache.commons.logging;vers + ion="1.1",org.apache.log4j;version="1.2",org.apache.log4j.spi;version + ="1.2",org.apache.tools.ant;version="1.7",org.apache.tools.ant.helper + ;version="1.7",org.apache.tools.ant.types;version="1.7",org.apache.to + ols.ant.util;version="1.7",org.argeo.slc.ant;version="0.11.2.SNAPSHOT + ",org.argeo.slc.ant.deploy;version="0.11.2.SNAPSHOT",org.argeo.slc.an + t.detached;version="0.11.2.SNAPSHOT",org.argeo.slc.ant.spring;version + ="0.11.2.SNAPSHOT",org.argeo.slc.ant.structure;version="0.11.2.SNAPSH + OT",org.argeo.slc.ant.test;version="0.11.2.SNAPSHOT",org.argeo.slc.an + t.unit;version="0.11.2.SNAPSHOT",org.argeo.slc.cli;version="0.11.2.SN + APSHOT",org.argeo.slc.core;version="0.11.2.SNAPSHOT",org.argeo.slc.co + re.build;version="0.11.2.SNAPSHOT",org.argeo.slc.core.deploy;version= + "0.11.2.SNAPSHOT",org.argeo.slc.core.process;version="0.11.2.SNAPSHOT + ",org.argeo.slc.core.structure;version="0.11.2.SNAPSHOT",org.argeo.sl + c.core.structure.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.core.te + st;version="0.11.2.SNAPSHOT",org.argeo.slc.core.test.context;version= + "0.11.2.SNAPSHOT",org.argeo.slc.core.test.spring;version="0.11.2.SNAP + SHOT",org.argeo.slc.core.test.tree;version="0.11.2.SNAPSHOT",org.arge + o.slc.detached;version="0.11.2.SNAPSHOT",org.argeo.slc.detached.ui;ve + rsion="0.11.2.SNAPSHOT",org.argeo.slc.lib.detached;version="0.11.2.SN + APSHOT",org.argeo.slc.logging;version="0.11.2.SNAPSHOT",org.argeo.slc + .maven;version="0.11.2.SNAPSHOT",org.argeo.slc.msg.process;version="0 + .11.2.SNAPSHOT",org.argeo.slc.msg.test.tree;version="0.11.2.SNAPSHOT" + ,org.argeo.slc.runtime;version="0.11.2.SNAPSHOT",org.argeo.slc.spring + ;version="0.11.2.SNAPSHOT",org.argeo.slc.support.deploy.ant;version=" + 0.11.2.SNAPSHOT",org.argeo.slc.unit;version="0.11.2.SNAPSHOT",org.arg + eo.slc.ws.client;version="0.11.2.SNAPSHOT",org.argeo.slc.ws.client.sp + ring;version="0.11.2.SNAPSHOT",org.argeo.slc.ws.process;version="0.11 + .2.SNAPSHOT",org.argeo.slc.ws.test.tree;version="0.11.2.SNAPSHOT",org + .springframework.beans;version="2.5.6.A",org.springframework.beans.fa + ctory;version="2.5.6.A",org.springframework.beans.factory.config;vers + ion="2.5.6.A",org.springframework.beans.factory.support;version="2.5. + 6.A",org.springframework.beans.factory.xml;version="2.5.6.A",org.spri + ngframework.context;version="2.5.6.A",org.springframework.context.sup + port;version="2.5.6.A",org.springframework.core.io;version="2.5.6.A", + org.springframework.oxm;version="1.5.5.A",org.springframework.util;ve + rsion="2.5.6.A",org.springframework.ws;version="1.5.5.A",org.springfr + amework.ws.client;version="1.5.5.A",org.springframework.ws.client.cor + e;version="1.5.5.A",org.springframework.ws.client.support.interceptor + ;version="1.5.5.A",org.springframework.ws.context;version="1.5.5.A",o + rg.springframework.ws.soap;version="1.5.5.A",org.springframework.ws.s + oap.client;version="1.5.5.A",org.springframework.xml.transform;versio + n="1.5.5.A",org.springframework.xml.validation;version="1.5.5.A",org. + w3c.dom;version="1.3",org.xml.sax;version="1.3" +Bundle-SymbolicName: org.argeo.slc.agent +Bundle-DocURL: http://www.argeo.org +Originally-Created-By: 1.6.0 (Sun Microsystems Inc.) + diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties new file mode 100644 index 000000000..c13c36f80 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties @@ -0,0 +1,23 @@ +log4j.rootLogger=WARN, console, file + +## Levels +log4j.logger.org.argeo=INFO + +## Ant (Ant error logging is to verbose) +log4j.logger.org.apache.tools.ant.UnknownElement=OFF +log4j.logger.org.apache.tools.ant.Target=OFF +log4j.logger.org.apache.tools.ant.Project=OFF + +## Appenders +# console uses PatternLayout. +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + +# file uses PatternLayout +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=${slc.workDir}/log/slcApp.log +log4j.appender.file.MaxFileSize=1MB +log4j.appender.file.MaxBackupIndex=5 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties new file mode 100644 index 000000000..ac489bf81 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties @@ -0,0 +1,8 @@ +# Tasks +slc.test=org.argeo.slc.ant.test.SlcTestTask +slc.deploy=org.argeo.slc.ant.deploy.SlcDeployTask +slc.manager=org.argeo.slc.ant.deploy.SlcManagerTask +slc.closeResult=org.argeo.slc.ant.test.SlcCloseTestResultTask +slc.report=org.argeo.slc.ant.test.SlcReportTask +slc.register=org.argeo.slc.ant.spring.SpringRegister +slc.detached=org.argeo.slc.ant.detached.SlcDetachedTask diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties new file mode 100644 index 000000000..0cb3b2c46 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties @@ -0,0 +1,2 @@ +# Types +slc.context=org.argeo.slc.ant.test.ParentContextType diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties new file mode 100644 index 000000000..7dcc3fd59 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties @@ -0,0 +1,13 @@ +log4j.rootLogger=WARN, console + +## Levels +log4j.logger.org.argeo=INFO + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml new file mode 100644 index 000000000..ce8eb432c --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml @@ -0,0 +1,53 @@ + + + +]> + + + Mapping of SLC detached types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml new file mode 100644 index 000000000..41e994d97 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + classpath:org/argeo/slc/lib/detached/castor.xml + + + + + + + + + + + + + diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml new file mode 100644 index 000000000..693f5ecb9 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml new file mode 100644 index 000000000..7e9df7d2d --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + http://localhost:9090/org.argeo.slc.webapp/slcService/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt b/runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt new file mode 100644 index 000000000..f414460db --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt @@ -0,0 +1 @@ +Argeo SLC Site \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java new file mode 100644 index 000000000..59987600e --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java @@ -0,0 +1,55 @@ +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 children = new Vector(); + private Map map = new TreeMap(); + + 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 getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java new file mode 100644 index 000000000..d49521a31 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java @@ -0,0 +1,64 @@ +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"); + } + +} diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java new file mode 100644 index 000000000..5a58f1f95 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java @@ -0,0 +1,11 @@ +package org.argeo.slc.ant; + +import org.argeo.slc.ant.unit.MinimalAntClasspathTestCase; + +public class SlcAntTest extends MinimalAntClasspathTestCase { + // private Log log = LogFactory.getLog(getClass()); + + public void testSimpleRun() { + execute("/org/argeo/slc/ant/build.xml"); + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java new file mode 100644 index 000000000..0425ce088 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java @@ -0,0 +1,142 @@ +package org.argeo.slc.lib.detached; + +import java.util.Enumeration; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.detached.DetachedAnswer; +import org.argeo.slc.detached.DetachedRequest; +import org.argeo.slc.detached.DetachedXmlConverter; +import org.argeo.slc.detached.DetachedXmlConverterCompat; +import org.argeo.slc.unit.AbstractSpringTestCase; +import org.argeo.slc.unit.UnitXmlUtils; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.validation.XmlValidator; + +public class DetachedCastorTest extends AbstractSpringTestCase { + private final Log log = LogFactory.getLog(getClass()); + + private DetachedXmlConverter converter = null; + private XmlValidator validator = null; + private DetachedXmlConverter converterCompat = null; + + public void setUp() { + converter = getBean("slcDefault.detached.xmlConverterCastor"); + validator = getBean("slcDefault.detached.xml.xsdValidator"); + converterCompat = new DetachedXmlConverterCompat(); + } + + public void testRequest() throws Exception { + DetachedRequest request = createTestRequest(); + + StringResult result = new StringResult(); + converter.marshallCommunication(request, result); + String xml = result.toString(); + log.debug(xml + "\n"); + + UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml)); + DetachedRequest requestUnm = (DetachedRequest) converter + .unmarshallCommunication(new StringSource(xml)); + assertDetachedRequest(request, requestUnm); + } + + public void testRequestCompat() throws Exception { + DetachedRequest request = createTestRequest(); + + StringResult result = new StringResult(); + converter.marshallCommunication(request, result); + String xml = result.toString(); + log.debug(xml + "\n"); + + UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml)); + DetachedRequest requestUnm = (DetachedRequest) converterCompat + .unmarshallCommunication(new StringSource(xml)); + assertDetachedRequest(request, requestUnm); + } + + public void testAnswer() throws Exception { + DetachedAnswer answer = createTestAnswer(); + StringResult result = new StringResult(); + converter.marshallCommunication(answer, result); + String xml = result.toString(); + log.debug(xml + "\n"); + + UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml)); + DetachedAnswer answerUnm = (DetachedAnswer) converter + .unmarshallCommunication(new StringSource(xml)); + assertDetachedAnswer(answer, answerUnm); + } + + public void testAnswerCompat() throws Exception { + DetachedAnswer answer = createTestAnswer(); + StringResult result = new StringResult(); + converterCompat.marshallCommunication(answer, result); + String xml = result.toString(); + log.debug(xml + "\n"); + + UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml)); + DetachedAnswer answerUnm = (DetachedAnswer) converter + .unmarshallCommunication(new StringSource(xml)); + assertDetachedAnswer(answer, answerUnm); + } + + public static DetachedRequest createTestRequest() { + DetachedRequest request = new DetachedRequest(); + request.setUuid("12345"); + request.setPath("/root/test"); + request.setRef("testRef"); + Properties properties = new Properties(); + properties.setProperty("key1", "value1"); + properties.setProperty("key2", "value2"); + request.setProperties(properties); + return request; + } + + public static DetachedAnswer createTestAnswer() { + DetachedAnswer answer = new DetachedAnswer(); + answer.setUuid("12345"); + answer.setStatus(DetachedAnswer.PROCESSED); + answer.setLog("my log\nline break."); + Properties properties = new Properties(); + properties.setProperty("key1", "value1"); + properties.setProperty("key2", "value2"); + answer.setProperties(properties); + return answer; + } + + public static void assertDetachedRequest(DetachedRequest expected, + DetachedRequest reached) { + assertEquals(expected.getUuid(), reached.getUuid()); + assertEquals(expected.getPath(), reached.getPath()); + assertEquals(expected.getRef(), reached.getRef()); + Properties expectedProps = expected.getProperties(); + Properties reachedProps = reached.getProperties(); + assertEquals(expectedProps.size(), reachedProps.size()); + Enumeration keys = expectedProps.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + assertTrue(reachedProps.containsKey(key)); + assertEquals(expectedProps.getProperty(key), reachedProps + .getProperty(key)); + } + } + + public static void assertDetachedAnswer(DetachedAnswer expected, + DetachedAnswer reached) { + assertEquals(expected.getUuid(), reached.getUuid()); + assertEquals(expected.getStatus(), reached.getStatus()); + assertEquals(expected.getLog(), reached.getLog()); + Properties expectedProps = expected.getProperties(); + Properties reachedProps = reached.getProperties(); + assertEquals(expectedProps.size(), reachedProps.size()); + Enumeration keys = expectedProps.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + assertTrue(reachedProps.containsKey(key)); + assertEquals(expectedProps.getProperty(key), reachedProps + .getProperty(key)); + } + } +} diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties b/runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties new file mode 100644 index 000000000..a583c59fa --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties @@ -0,0 +1,21 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=WARN, console + +## Levels +# Slc +log4j.logger.org.argeo=DEBUG + +# Castor +log4j.logger.org.exolab.castor=WARN + +# Spring +log4j.logger.org.springframework=WARN + +## Appenders +# A1 is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml new file mode 100644 index 000000000..c9c391182 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml new file mode 100644 index 000000000..6ff9b8522 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml new file mode 100644 index 000000000..35de7be94 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml new file mode 100644 index 000000000..67f889ab5 --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml new file mode 100644 index 000000000..56da88a8b --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml @@ -0,0 +1,42 @@ + + + + + + + + + + toto + + + toto + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml new file mode 100644 index 000000000..88d6483cb --- /dev/null +++ b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml @@ -0,0 +1,7 @@ + + + + +