</plugin>
</plugins>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.slc.dep</groupId>
+ <artifactId>org.argeo.slc.dep.server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
</profile>
<profile>
<id>server_mysql</id>
${basedir}/../../server/org.argeo.slc.siteserver/bundles;in=*
</slc.osgi.bundles>
<slc.osgi.start>
- org.argeo.dep.osgi.catalina.start,
org.springframework.osgi.extender,
- org.springframework.osgi.web.extender,
- org.springframework.osgi.samples.simplewebapp,
- org.argeo.slc.server.activemq,
+ org.argeo.slc.server.main,
org.argeo.slc.server.hsqldb,
- org.argeo.slc.server.hibernate,
- org.argeo.slc.server.services,
- org.argeo.slc.server.jms,
- org.argeo.slc.webapp,
org.argeo.slc.ria,
org.argeo.slc.agent
- </slc.osgi.start>
+ </slc.osgi.start>
</systemProperties>
</configuration>
<executions>
import org.argeo.slc.SlcException;
import org.argeo.slc.msg.MsgHandler;
import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;
import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest;
import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
public Object handleMsg(Object msg) {
if (msg instanceof SlcExecution)
slcExecutionService.newExecution((SlcExecution) msg);
+ else if (msg instanceof SlcExecutionStepsRequest)
+ slcExecutionService.addSteps((SlcExecutionStepsRequest) msg);
else if (msg instanceof SlcExecutionStatusRequest)
slcExecutionService.updateStatus((SlcExecutionStatusRequest) msg);
else if (msg instanceof CreateTreeTestResultRequest)
import org.argeo.slc.SlcException;
import org.argeo.slc.dao.process.SlcExecutionDao;
import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;
import org.argeo.slc.process.SlcExecution;
+import org.argeo.slc.process.SlcExecutionStep;
import org.argeo.slc.services.process.SlcExecutionService;
public class SlcExecutionServiceImpl implements SlcExecutionService {
slcExecutionDao.create(slcExecutionMsg);
} else {
- if (log.isTraceEnabled())
- log.trace("Updating SLC execution #"
- + slcExecutionMsg.getUuid());
-
- slcExecutionDao.merge(slcExecutionMsg);
+ throw new SlcException(
+ "There is already an SlcExecution registered with id "
+ + slcExecutionMsg.getUuid());
+ // if (log.isTraceEnabled())
+ // log.trace("Updating SLC execution #"
+ // + slcExecutionMsg.getUuid());
+ //
+ // slcExecutionDao.merge(slcExecutionMsg);
}
}
slcExecution.setStatus(msg.getNewStatus());
+ if (msg.getNewStatus().equals(SlcExecution.STATUS_FINISHED))
+ slcExecution.getSteps().add(
+ new SlcExecutionStep(SlcExecutionStep.TYPE_END,
+ "Process finished."));
+
if (log.isTraceEnabled())
log.trace("Updating status for SLC execution #"
- + slcExecution.getUuid());
+ + slcExecution.getUuid() + " to status "
+ + msg.getNewStatus());
slcExecutionDao.update(slcExecution);
}
+
+ public void addSteps(SlcExecutionStepsRequest msg) {
+ slcExecutionDao.addSteps(msg.getSlcExecutionUuid(), msg.getSteps());
+ }
+
}
import org.argeo.slc.services.test.TestManagerService;\r
import org.argeo.slc.test.TestRunDescriptor;\r
\r
-/** Implementation of complex operations impacting the underlying data. */\r
+/**\r
+ * Implementation of complex operations impacting the underlying data.\r
+ */\r
public class TestManagerServiceImpl implements TestManagerService {\r
private Log log = LogFactory.getLog(getClass());\r
\r
.getTestResultUuid());\r
}\r
} else {\r
- log\r
- .trace("ResultUUID="\r
- + testRunDescriptor.getTestResultUuid());\r
+ if (log.isTraceEnabled())\r
+ log.trace("ResultUUID="\r
+ + testRunDescriptor.getTestResultUuid());\r
addResultToCollection("default", testRunDescriptor\r
.getTestResultUuid());\r
}\r
}\r
\r
public void addResultToCollection(String collectionId, String resultUuid) {\r
+ // TODO: improve collections\r
TreeTestResultCollection ttrc = treeTestResultCollectionDao\r
.getTestResultCollection(collectionId);\r
if (ttrc == null) {\r
treeTestResultDao.create(treeTestResult);\r
\r
registerTestRunDescriptor(msg.getTestRunDescriptor());\r
+\r
+ // FIXME: temporary hack before better collection management is found\r
+ if (msg.getTestRunDescriptor() == null) {\r
+ addResultToCollection("default", treeTestResult.getUuid());\r
+ }\r
}\r
\r
public void addResultPart(ResultPartRequest msg) {\r
package org.argeo.slc.services.process;
import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;
import org.argeo.slc.process.SlcExecution;
public interface SlcExecutionService {
public void newExecution(SlcExecution slcExecutionMsg);
+
public void updateStatus(SlcExecutionStatusRequest msg);
+
+ public void addSteps(SlcExecutionStepsRequest msg);
}
import org.apache.commons.logging.LogFactory;\r
import org.argeo.slc.msg.MsgConstants;\r
import org.argeo.slc.process.SlcExecution;\r
+import org.argeo.slc.process.SlcExecutionStep;\r
import org.argeo.slc.runtime.SlcAgent;\r
import org.argeo.slc.runtime.SlcAgentFactory;\r
import org.argeo.slc.services.process.SlcExecutionService;\r
.unmarshal(source);\r
\r
slcExecution.setStatus(SlcExecution.STATUS_SCHEDULED);\r
+ slcExecution.getSteps().add(\r
+ new SlcExecutionStep(SlcExecutionStep.TYPE_START,\r
+ "Process started from the Web UI"));\r
slcExecutionService.newExecution(slcExecution);\r
\r
SlcAgent agent = agentFactory.getAgent(agentId);\r
import java.util.Map;\r
\r
public interface ExecutionContext {\r
+ public final static String VAR_PROCESS_ID = "slcVar.process.id";\r
+ public final static String VAR_EXECUTION_CONTEXT_ID = "slcVar.executionContext.id";\r
+ public final static String VAR_FLOW_ID = "slcVar.flow.id";\r
+ public final static String VAR_FLOW_NAME = "slcVar.flow.name";\r
\r
/**\r
* @param name\r
\r
import java.io.Serializable;\r
import java.util.ArrayList;\r
+import java.util.Date;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.TreeMap;\r
private String status = STATUS_NONE;\r
private Map<String, String> attributes = new TreeMap<String, String>();\r
\r
+ /** TODO: Synchronize */\r
private List<SlcExecutionStep> steps = new ArrayList<SlcExecutionStep>();\r
private List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();\r
\r
}\r
\r
public SlcExecutionStep currentStep() {\r
- if (steps.size() > 0)\r
- return steps.get(steps.size() - 1);\r
- else\r
- return null;\r
+ synchronized (steps) {\r
+ if (steps.size() > 0)\r
+ return steps.get(steps.size() - 1);\r
+ else\r
+ return null;\r
+ }\r
}\r
\r
@Override\r
buf.append(" attributes=").append(attributes);\r
return buf.toString();\r
}\r
+\r
+ public Date getStartDate() {\r
+ synchronized (steps) {\r
+ if (steps.size() == 0)\r
+ return null;\r
+ else\r
+ return steps.get(0).getBegin();\r
+ }\r
+ }\r
+\r
+ public Date getEndDate() {\r
+ if (!status.equals(STATUS_FINISHED) && !status.equals(STATUS_ERROR))\r
+ return null;\r
+\r
+ synchronized (steps) {\r
+ if (steps.size() == 0)\r
+ return null;\r
+ else\r
+ return steps.get(steps.size() - 1).getBegin();\r
+ }\r
+ }\r
}\r
\r
import java.io.IOException;\r
import java.io.StringReader;\r
-import java.io.StringWriter;\r
import java.util.ArrayList;\r
import java.util.Date;\r
import java.util.List;\r
import org.apache.commons.io.IOUtils;\r
\r
public class SlcExecutionStep {\r
+ public final static String TYPE_START = "START";\r
+ public final static String TYPE_END = "END";\r
+ public final static String TYPE_PHASE_START = "PHASE_START";\r
+ public final static String TYPE_PHASE_END = "PHASE_END";\r
public final static String TYPE_LOG = "LOG";\r
\r
- private String uuid;\r
+ private String uuid = UUID.randomUUID().toString();\r
private String type;\r
- private Date begin;\r
+ private Date begin = new Date();\r
private List<String> logLines = new ArrayList<String>();\r
\r
/** Empty constructor */\r
public SlcExecutionStep() {\r
}\r
\r
+ /** Creates a step of type LOG. */\r
public SlcExecutionStep(String log) {\r
- this.type = TYPE_LOG;\r
- this.begin = new Date();\r
- this.uuid = UUID.randomUUID().toString();\r
+ this(TYPE_LOG, log);\r
+ }\r
+\r
+ /** Creates a step of the given type. */\r
+ public SlcExecutionStep(String type, String log) {\r
+ this.type = type;\r
addLog(log);\r
}\r
\r
this.logLines = logLines;\r
}\r
\r
- public String logAsString() {\r
- StringWriter writer = new StringWriter();\r
- String log = writer.toString();\r
- IOUtils.closeQuietly(writer);\r
- return log;\r
- }\r
-\r
+ @SuppressWarnings(value = { "unchecked" })\r
public void addLog(String log) {\r
if (log == null)\r
return;\r
import javax.jms.Destination;
-import org.argeo.slc.SlcException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.argeo.slc.UnsupportedException;
import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;
import org.argeo.slc.process.SlcExecution;
import org.argeo.slc.process.SlcExecutionNotifier;
import org.argeo.slc.process.SlcExecutionStep;
+import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
public class JmsSlcExecutionNotifier implements SlcExecutionNotifier {
+ private final static Log log = LogFactory
+ .getLog(JmsSlcExecutionNotifier.class);
private JmsTemplate jmsTemplate;
private Destination executionEventDestination;
- //private Destination updateStatusDestination;
+
+ // private Destination updateStatusDestination;
public void updateStatus(SlcExecution slcExecution, String oldStatus,
String newStatus) {
SlcExecutionStatusRequest req = new SlcExecutionStatusRequest(
slcExecution.getUuid(), newStatus);
- jmsTemplate.convertAndSend(executionEventDestination, req);
+ convertAndSend(req);
}
public void addSteps(SlcExecution slcExecution,
List<SlcExecutionStep> additionalSteps) {
- throw new UnsupportedException();
+ SlcExecutionStepsRequest req = new SlcExecutionStepsRequest(
+ slcExecution.getUuid(), additionalSteps);
+ convertAndSend(req);
}
public void newExecution(SlcExecution slcExecution) {
this.jmsTemplate = jmsTemplate;
}
- public void setExecutionEventDestination(Destination executionEventDestination) {
+ public void setExecutionEventDestination(
+ Destination executionEventDestination) {
this.executionEventDestination = executionEventDestination;
}
-
-
-// public void setUpdateStatusDestination(Destination updateStatusDestination) {
-// this.updateStatusDestination = updateStatusDestination;
-// }
-
+ protected void convertAndSend(Object req) {
+ try {
+ jmsTemplate.convertAndSend(executionEventDestination, req);
+ } catch (JmsException e) {
+ log.warn("Send request " + req.getClass() + " to server: "
+ + e.getMessage());
+ if (log.isTraceEnabled())
+ log.debug("Original error.", e);
+ }
+ }
}
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.test.TestResultListener;
import org.argeo.slc.test.TestResultPart;
+import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
public class JmsTreeTestResultListener implements TreeTestResultListener {
private Destination executionEventDestination;
- // private Destination createDestination;
- // private Destination addResultPartDestination;
- // private Destination closeDestination;
-
public void resultPartAdded(TreeTestResult testResult,
TestResultPart testResultPart) {
if (onlyOnClose)
jmsTemplate.convertAndSend(executionEventDestination, req);
}
+ } catch (JmsException e) {
+ log.warn("Could not notify result part to server: "
+ + e.getMessage());
+ if (log.isTraceEnabled())
+ log.debug("Original error.", e);
} catch (Exception e) {
throw new SlcException("Could not notify to JMS", e);
}
jmsTemplate.convertAndSend(executionEventDestination, req);
}
+ } catch (JmsException e) {
+ log.warn("Could not notify result close to server: "
+ + e.getMessage());
+ if (log.isTraceEnabled())
+ log.debug("Original error.", e);
} catch (Exception e) {
throw new SlcException("Could not notify to JMS", e);
}
req.setAttachment((SimpleAttachment) attachment);
jmsTemplate.convertAndSend(executionEventDestination, req);
+ } catch (JmsException e) {
+ log
+ .warn("Could not notify attachment to server: "
+ + e.getMessage());
+ if (log.isTraceEnabled())
+ log.debug("Original error.", e);
} catch (Exception e) {
throw new SlcException("Could not notify to JMS", e);
}
<map-to ns-uri="http://argeo.org/projects/slc/schemas"
ns-prefix="slc" />
<field name="slcExecutionUuid" />
- <field name="steps" collection="vector"
+ <field name="steps" collection="arraylist"
type="org.argeo.slc.process.SlcExecutionStep">
<bind-xml auto-naming="deriveByClass" location="steps" />
</field>
<property name="type" column="TYPE" />\r
<property name="status" column="STATUS" />\r
\r
- <list name="steps" cascade="all" table="SLC_EXECUTIONS_STEPS">\r
+ <list name="steps" cascade="all" table="SLC_EXECUTIONS_STEPS"\r
+ lazy="false">\r
<cache usage="read-write" />\r
<key column="SLC_EXECUTION_ID" />\r
<list-index column="INDX" />\r
- <one-to-many
- class="org.argeo.slc.process.SlcExecutionStep" />
+ <one-to-many class="org.argeo.slc.process.SlcExecutionStep" />
</list>
<map name="attributes" table="SLC_EXEC_ATTRS_MAP" cascade="all"
import java.util.List;
import java.util.Map;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.argeo.slc.SlcException;
import org.argeo.slc.core.structure.tree.TreeSPath;
import org.argeo.slc.core.structure.tree.TreeSRegistry;
public class DefaultExecutionFlow implements ExecutionFlow, InitializingBean,
BeanNameAware, StructureAware<TreeSPath>, ResourceLoaderAware {
- private final static Log log = LogFactory
- .getLog(DefaultExecutionFlow.class);
-
private final ExecutionSpec executionSpec;
private String name = null;
private Map<String, Object> parameters = new HashMap<String, Object>();
import org.argeo.slc.process.RealizedFlow;
import org.argeo.slc.process.SlcExecution;
import org.argeo.slc.process.SlcExecutionNotifier;
-import org.springframework.util.Assert;
+import org.argeo.slc.process.SlcExecutionStep;
public class DefaultModulesManager implements ExecutionModulesManager {
private final static Log log = LogFactory
private List<ExecutionModule> executionModules = new ArrayList<ExecutionModule>();
private List<SlcExecutionNotifier> slcExecutionNotifiers = new ArrayList<SlcExecutionNotifier>();
+ private ThreadGroup processesThreadGroup = new ThreadGroup("Processes");
protected ExecutionModule getExecutionModule(String moduleName,
String version) {
String moduleName, String version) {
ExecutionModule module = getExecutionModule(moduleName, version);
- if(module==null)
- throw new SlcException("Module "+moduleName+" ("+version+") not found");
+ if (module == null)
+ throw new SlcException("Module " + moduleName + " (" + version
+ + ") not found");
return module.getDescriptor();
}
}
public void process(SlcExecution slcExecution) {
- new ProcessThread(slcExecution).start();
+ new ProcessThread(processesThreadGroup, slcExecution).start();
}
protected void dispatchUpdateStatus(SlcExecution slcExecution,
}
}
+ protected synchronized void dispatchAddStep(SlcExecution slcExecution,
+ SlcExecutionStep step) {
+ slcExecution.getSteps().add(step);
+ List<SlcExecutionStep> steps = new ArrayList<SlcExecutionStep>();
+ steps.add(step);
+ for (Iterator<SlcExecutionNotifier> it = slcExecutionNotifiers
+ .iterator(); it.hasNext();) {
+ it.next().addSteps(slcExecution, steps);
+ }
+ }
+
public void setSlcExecutionNotifiers(
List<SlcExecutionNotifier> slcExecutionNotifiers) {
this.slcExecutionNotifiers = slcExecutionNotifiers;
}
+ /** Thread of the SLC Process, starting the sub executions. */
private class ProcessThread extends Thread {
- private final SlcExecution slcExecution;
+ private final SlcExecution slcProcess;
+ private final ThreadGroup processThreadGroup;
private final List<RealizedFlow> flowsToProcess = new ArrayList<RealizedFlow>();
- public ProcessThread(SlcExecution slcExecution) {
- this.slcExecution = slcExecution;
+ public ProcessThread(ThreadGroup processesThreadGroup,
+ SlcExecution slcExecution) {
+ super(processesThreadGroup, "SLC Process #"
+ + slcExecution.getUuid());
+ this.slcProcess = slcExecution;
+ processThreadGroup = new ThreadGroup("SLC Process #"
+ + slcExecution.getUuid() + " thread group");
}
public void run() {
- log.info("\n##\n## Process SLC Execution " + slcExecution
- + "\n##\n");
+ log.info("\n##\n## Process SLC Execution " + slcProcess + "\n##\n");
// FIXME: hack to let the SlcExecution be registered on server
try {
// silent
}
- slcExecution.setStatus(SlcExecution.STATUS_RUNNING);
- dispatchUpdateStatus(slcExecution, SlcExecution.STATUS_SCHEDULED,
+ slcProcess.setStatus(SlcExecution.STATUS_RUNNING);
+ dispatchUpdateStatus(slcProcess, SlcExecution.STATUS_SCHEDULED,
SlcExecution.STATUS_RUNNING);
- flowsToProcess.addAll(slcExecution.getRealizedFlows());
+ flowsToProcess.addAll(slcProcess.getRealizedFlows());
while (flowsToProcess.size() > 0) {
RealizedFlow flow = flowsToProcess.remove(0);
}
}
- slcExecution.setStatus(SlcExecution.STATUS_RUNNING);
- dispatchUpdateStatus(slcExecution, SlcExecution.STATUS_RUNNING,
+ slcProcess.setStatus(SlcExecution.STATUS_FINISHED);
+ dispatchUpdateStatus(slcProcess, SlcExecution.STATUS_RUNNING,
SlcExecution.STATUS_FINISHED);
- /*
- * for (RealizedFlow flow : slcExecution.getRealizedFlows()) {
- * ExecutionModule module = getExecutionModule(flow.getModuleName(),
- * flow.getModuleVersion()); if (module != null) { ExecutionThread
- * thread = new ExecutionThread(flow .getFlowDescriptor(), module);
- * thread.start(); } else { throw new
- * SlcException("ExecutionModule " + flow.getModuleName() +
- * ", version " + flow.getModuleVersion() + " not found."); } }
- */
}
public synchronized void flowCompleted() {
notifyAll();
}
+
+ public SlcExecution getSlcProcess() {
+ return slcProcess;
+ }
+
+ public ThreadGroup getProcessThreadGroup() {
+ return processThreadGroup;
+ }
}
+ /** Thread of a single execution */
private class ExecutionThread extends Thread {
private final ExecutionFlowDescriptor executionFlowDescriptor;
private final ExecutionModule executionModule;
public ExecutionThread(ProcessThread processThread,
ExecutionFlowDescriptor executionFlowDescriptor,
ExecutionModule executionModule) {
- super("SLC Execution #" /* + executionContext.getUuid() */);
+ super(processThread.getProcessThreadGroup(), "Flow "
+ + executionFlowDescriptor.getName());
this.executionFlowDescriptor = executionFlowDescriptor;
this.executionModule = executionModule;
this.processThread = processThread;
}
public void run() {
+ dispatchAddStep(processThread.getSlcProcess(),
+ new SlcExecutionStep(SlcExecutionStep.TYPE_PHASE_START,
+ "Flow " + executionFlowDescriptor.getName()));
+
try {
executionModule.execute(executionFlowDescriptor);
} catch (Exception e) {
// TODO: re-throw exception ?
- log.error("Execution "/* + executionContext.getUuid() */
- + " failed.", e);
+ String msg = "Execution of flow "
+ + executionFlowDescriptor.getName() + " failed.";
+ log.error(msg, e);
+ dispatchAddStep(processThread.getSlcProcess(),
+ new SlcExecutionStep(msg + " " + e.getMessage()));
} finally {
processThread.flowCompleted();
+ dispatchAddStep(processThread.getSlcProcess(),
+ new SlcExecutionStep(SlcExecutionStep.TYPE_PHASE_END,
+ "Flow " + executionFlowDescriptor.getName()));
}
}
}
String osgiInstanceArea = System.getProperty("osgi.instance.area");
String osgiInstanceAreaDefault = System
.getProperty("osgi.instance.area.default");
- String tempDir = System.getProperty("java.io.tmpdir");
if (osgiInstanceArea != null) {
// within OSGi with -data specified
}
public File getFile(String relativePath) {
- Assert.notNull(executionContext, "execution context is null");
if (withExecutionSubdirectory) {
+ Assert.notNull(executionContext, "execution context is null");
String path = baseDir.getPath() + File.separator
+ sdf().format(executionContext.getCreationDate())
+ executionContext.getUuid();
return prefixDatePattern;
}
+ /** Default is true. */
public void setWithExecutionSubdirectory(Boolean withExecutionSubdirectory) {
this.withExecutionSubdirectory = withExecutionSubdirectory;
}
import org.argeo.slc.execution.ExecutionSpecAttribute;
public class MapExecutionContext implements ExecutionContext {
+
private final static Log log = LogFactory.getLog(MapExecutionContext.class);
private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
public MapExecutionContext() {
uuid = UUID.randomUUID().toString();
+ variables.put(VAR_EXECUTION_CONTEXT_ID, uuid);
}
public void addVariables(
public void enterFlow(ExecutionFlow executionFlow) {
ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
stack.push(runtime);
+ variables.put(VAR_FLOW_ID, runtime.getUuid());
+ variables.put(VAR_FLOW_NAME, runtime.getExecutionFlow().getName());
if (log.isDebugEnabled())
log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
package org.argeo.slc.core.execution.tasks;
import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.exec.LogOutputStream;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.exec.ShutdownHookProcessDestroyer;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.slc.SlcException;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRelatedHelper;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.structure.StructureAware;
+import org.argeo.slc.test.TestResult;
+import org.argeo.slc.test.TestStatus;
+import org.springframework.core.io.Resource;
/** Execute and OS system call. */
-public class SystemCall implements Runnable {
+public class SystemCall extends TreeSRelatedHelper implements Runnable,
+ StructureAware<TreeSPath> {
private final Log log = LogFactory.getLog(getClass());
private String execDir;
private String stdErrLogLevel = "ERROR";
private String stdOutLogLevel = "INFO";
+ private Resource stdOutFile = null;
+ private Resource stdErrFile = null;
+
private Map<String, List<Object>> osCommands = new HashMap<String, List<Object>>();
private Map<String, String> osCmds = new HashMap<String, String>();
private Map<String, String> environmentVariables = new HashMap<String, String>();
private Long watchdogTimeout = 24 * 60 * 60 * 1000l;
+ private TestResult testResult;
+
public void run() {
+ // Log writers
+ final Writer stdOutWriter;
+ final Writer stdErrWriter;
+ if (stdOutFile != null) {
+ stdOutWriter = createWriter(stdOutFile);
+ } else
+ stdOutWriter = null;
+ if (stdErrFile != null) {
+ stdErrWriter = createWriter(stdErrFile);
+ } else {
+ if (stdOutFile != null) {
+ stdErrWriter = createWriter(stdOutFile);
+ } else
+ stdErrWriter = null;
+ }
+
try {
if (log.isTraceEnabled()) {
log.debug("os.name=" + System.getProperty("os.name"));
Executor executor = new DefaultExecutor();
executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout));
+
PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(
new LogOutputStream() {
protected void processLine(String line, int level) {
log(stdOutLogLevel, line);
+ if (stdOutWriter != null)
+ appendLineToFile(stdOutWriter, line);
}
}, new LogOutputStream() {
protected void processLine(String line, int level) {
log(stdErrLogLevel, line);
+ if (stdErrWriter != null)
+ appendLineToFile(stdErrWriter, line);
}
}, null);
executor.setStreamHandler(pumpStreamHandler);
if (log.isDebugEnabled())
log.debug("Process " + commandLine
+ " properly completed.");
+ if (testResult != null) {
+ forwardPath(testResult, null);
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.PASSED, "Process " + commandLine
+ + " properly completed."));
+ }
}
public void onProcessFailed(ExecuteException e) {
- throw new SlcException("Process " + commandLine
- + " failed.", e);
+ if (testResult != null) {
+ forwardPath(testResult, null);
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.ERROR, "Process " + commandLine
+ + " failed.", e));
+ } else {
+ throw new SlcException("Process " + commandLine
+ + " failed.", e);
+ }
}
};
executeResultHandler);
} catch (Exception e) {
throw new SlcException("Could not execute command " + cmd, e);
+ } finally {
+ IOUtils.closeQuietly(stdOutWriter);
+ IOUtils.closeQuietly(stdErrWriter);
}
}
throw new SlcException("Unknown log level " + logLevel);
}
+ protected void appendLineToFile(Writer writer, String line) {
+ try {
+ writer.append(line).append('\n');
+ } catch (IOException e) {
+ log.error("Cannot write to log file", e);
+ }
+ }
+
+ protected Writer createWriter(Resource target) {
+ FileWriter writer = null;
+ try {
+ File file = target.getFile();
+ writer = new FileWriter(file, true);
+ } catch (IOException e) {
+ log.error("Cannot create log file " + target, e);
+ IOUtils.closeQuietly(writer);
+ }
+ return writer;
+ }
+
public void setCmd(String command) {
this.cmd = command;
}
this.watchdogTimeout = watchdogTimeout;
}
+ public void setStdOutFile(Resource stdOutFile) {
+ this.stdOutFile = stdOutFile;
+ }
+
+ public void setStdErrFile(Resource stdErrFile) {
+ this.stdErrFile = stdErrFile;
+ }
+
+ public void setTestResult(TestResult testResult) {
+ this.testResult = testResult;
+ }
+
}
package org.argeo.slc.core.structure.tree;\r
\r
import org.argeo.slc.core.structure.SimpleSElement;\r
+import org.argeo.slc.structure.StructureAware;\r
import org.argeo.slc.structure.StructureElement;\r
import org.argeo.slc.structure.StructureRegistry;\r
\r
/**\r
- * Provides default implementations of some methods of <code>TreeSRelated</code>.\r
+ * Provides default implementations of some methods of <code>TreeSRelated</code>\r
+ * .\r
*/\r
public abstract class TreeSRelatedHelper implements TreeSRelated {\r
private TreeSPath basePath;\r
private StructureRegistry<TreeSPath> registry;\r
\r
+ // private ThreadLocal<TreeSPath> basePath = new ThreadLocal<TreeSPath>();\r
+ // private ThreadLocal<StructureRegistry<TreeSPath>> registry = new\r
+ // ThreadLocal<StructureRegistry<TreeSPath>>();\r
+\r
public TreeSPath getBasePath() {\r
return basePath;\r
}\r
\r
public void notifyCurrentPath(StructureRegistry<TreeSPath> registry,\r
TreeSPath path) {\r
- basePath = path;\r
+ this.basePath = path;\r
this.registry = registry;\r
}\r
\r
return new SimpleSElement(key);\r
}\r
\r
+ /**\r
+ * Checks wether the object is {@link StructureAware} and forward path and\r
+ * registry. null safe for both arguments.\r
+ */\r
+ @SuppressWarnings(value = { "unchecked" })\r
+ protected void forwardPath(Object obj, String childName) {\r
+ if (obj == null)\r
+ return;\r
+\r
+ if (obj instanceof StructureAware && basePath != null) {\r
+ TreeSPath path;\r
+ if (childName != null)\r
+ path = basePath.createChild(childName);\r
+ else\r
+ path = basePath;\r
+\r
+ ((StructureAware<TreeSPath>) obj).notifyCurrentPath(registry, path);\r
+ }\r
+ }\r
+\r
}\r
package org.argeo.slc.msg.process;\r
\r
+import java.util.ArrayList;\r
import java.util.List;\r
import java.util.Vector;\r
\r
\r
public class SlcExecutionStepsRequest {\r
private String slcExecutionUuid;\r
- private List<SlcExecutionStep> steps = new Vector<SlcExecutionStep>();\r
+ private List<SlcExecutionStep> steps = new ArrayList<SlcExecutionStep>();\r
\r
public SlcExecutionStepsRequest() {\r
\r
assertNotNull(reached);\r
assertEquals(expected.getUuid(), reached.getUuid());\r
assertEquals(expected.getType(), reached.getType());\r
- assertEquals(expected.logAsString(), reached.logAsString());\r
assertDateSec(expected.getBegin(), reached.getBegin());\r
}\r
\r
--- /dev/null
+Manifest-Version: 1.0\r
+Bundle-SymbolicName: org.argeo.slc.server.main\r
+Bundle-Version: 0.11.4.SNAPSHOT\r
+Bundle-Name: SLC Server Main\r
+Require-Bundle: org.argeo.slc.server,\r
+ org.argeo.slc.specs,\r
+ org.argeo.slc.support.simple\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bundle id="spring.osgi.web.extender" symbolic-name="org.springframework.osgi.web.extender"
+ action="start" />
+ <bundle id="catalina" symbolic-name="org.argeo.dep.osgi.catalina.start"
+ action="start" />
+ <bundle id="activemq" symbolic-name="org.argeo.slc.server.activemq"
+ action="start" />
+ <bundle id="hibernate" symbolic-name="org.argeo.slc.server.hibernate"
+ action="start" />
+ <bundle id="services" symbolic-name="org.argeo.slc.server.services"
+ action="start" />
+ <bundle id="jms" symbolic-name="org.argeo.slc.server.jms"
+ action="start" />
+ <bundle id="webapp" symbolic-name="org.argeo.slc.webapp" action="start" />
+</beans:beans>
\ No newline at end of file