--- /dev/null
+package org.argeo.slc.detached;
+
+public interface DetachedAdminCommand {
+
+}
public class DetachedAnswer implements DetachedCommunication {
static final long serialVersionUID = 1l;
+ public static int UNKOWN = -1;
public static int PROCESSED = 0;
public static int ERROR = 1;
public static int SKIPPED = 2;
+ public static int CLOSED_SESSION = 10;
private Properties properties = new Properties();
- private int status;
+ private int status = UNKOWN;
private String log;
private String uuid;
}
- public DetachedAnswer(DetachedRequest request, String message) {
+ public DetachedAnswer(DetachedRequest request) {
uuid = request.getUuid();
+ }
+
+ public DetachedAnswer(DetachedRequest request, String message) {
+ this(request);
log = message;
status = PROCESSED;
}
package org.argeo.slc.detached;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.detached.admin.CloseSession;
+import org.argeo.slc.detached.admin.OpenSession;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class DetachedExecutionServerImpl implements DetachedExecutionServer {
+ private final static Log log = LogFactory
+ .getLog(DetachedExecutionServerImpl.class);
+
private final DetachedContextImpl detachedContext;
+ private final List sessions;
+
+ private int skipCount = 0;
private BundleContext bundleContext;
private DetachedDriver driver;
public DetachedExecutionServerImpl() {
detachedContext = new DetachedContextImpl();
+ sessions = new Vector();
}
public DetachedAnswer executeStep(DetachedRequest request) {
+ DetachedAnswer answer = null;
try {
DetachedStep step = null;
- // Find step
+ // Find action
ServiceReference[] refs = bundleContext.getAllServiceReferences(
StaticRefProvider.class.getName(), null);
+ Object obj = null;
for (int i = 0; i < refs.length; i++) {
StaticRefProvider provider = (StaticRefProvider) bundleContext
.getService(refs[i]);
- Object obj = provider.getStaticRef(request.getRef());
+ obj = provider.getStaticRef(request.getRef());
if (obj != null) {
- step = (DetachedStep) obj;
break;
}
}
- if (step == null)
- throw new DetachedException("Could not find step with ref "
+ if (obj == null)
+ throw new DetachedException("Could not find action with ref "
+ + request.getRef());
+
+ // Execute actions
+ if (obj instanceof DetachedStep) {
+ if (getCurrentSession() == null)
+ throw new DetachedException("No open session.");
+
+ StringBuffer skippedLog = new StringBuffer();
+ boolean execute = true;
+ if (getPreviousSession() != null
+ && !getPreviousSession().isClosed()) {
+ if (getCurrentSession().getDoItAgainPolicy().equals(
+ DetachedSession.SKIP_UNTIL_ERROR)) {
+ // Skip execution of already successful steps
+ if (getPreviousSession().getAnswers().size() > skipCount) {
+ DetachedAnswer previousAnswer = (DetachedAnswer) getPreviousSession()
+ .getAnswers().get(skipCount);
+ DetachedRequest previousRequest = (DetachedRequest) getPreviousSession()
+ .getRequests().get(skipCount);
+ // Check paths
+ if (!previousRequest.getPath().equals(
+ request.getPath())) {
+ String msg = "New request is not consistent with previous path. previousPath="
+ + previousRequest.getPath()
+ + ", newPath="
+ + request.getPath()
+ + "\n";
+ skippedLog.append(msg);
+ log.warn(msg);
+ }
+
+ if (previousAnswer.getStatus() != DetachedAnswer.ERROR) {
+ execute = false;
+ }
+ } else {
+ // went further as skip count, doing nothing.
+ }
+ }
+ }
+
+ if (execute) {
+ step = (DetachedStep) obj;
+ answer = step.execute(detachedContext, request);
+ } else {
+ skippedLog.append("Skipped path " + request.getPath()
+ + " (skipCount=" + skipCount + ")");
+ answer = new DetachedAnswer(request);
+ answer.setStatus(DetachedAnswer.SKIPPED);
+ answer.setLog(skippedLog.toString());
+ }
+
+ } else if (obj instanceof DetachedAdminCommand) {
+ if (obj instanceof OpenSession) {
+ if (getCurrentSession() != null)
+ throw new DetachedException(
+ "There is already an open session #"
+ + getCurrentSession().getUuid());
+ sessions.add(((OpenSession) obj).execute(request,
+ bundleContext));
+ answer = new DetachedAnswer(request, "Session #"
+ + getCurrentSession().getUuid() + " open.");
+ } else if (obj instanceof CloseSession) {
+ if (getCurrentSession() == null)
+ throw new DetachedException(
+ "There is no open session to close");
+ answer = new DetachedAnswer(request, "Session #"
+ + getCurrentSession().getUuid() + " closed.");
+ answer.setStatus(DetachedAnswer.CLOSED_SESSION);
+ }
+ }
+
+ if (answer == null)
+ throw new DetachedException("Unknown action type "
+ + obj.getClass() + " for action with ref "
+ request.getRef());
- return step.execute(detachedContext, request);
} catch (DetachedException e) {
- throw e;
+ answer = new DetachedAnswer(request);
+ answer.setStatus(DetachedAnswer.ERROR);
+ answer.setLog(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new DetachedException(
"Unexpected exception while executing request " + request,
e);
}
+ getCurrentSession().getRequests().add(request);
+ getCurrentSession().getAnswers().add(answer);
+ return answer;
+ }
+
+ protected final DetachedSession getCurrentSession() {
+ if (sessions.size() == 0) {
+ return null;
+ } else {
+ DetachedSession session = (DetachedSession) sessions.get(sessions
+ .size() - 1);
+ List answers = session.getAnswers();
+ if (answers.size() > 0) {
+ DetachedAnswer lastAnswer = (DetachedAnswer) answers
+ .get(answers.size() - 1);
+ if (lastAnswer.getStatus() == DetachedAnswer.ERROR
+ || lastAnswer.getStatus() == DetachedAnswer.CLOSED_SESSION)
+ return null;
+ }
+ return session;
+ }
+ }
+
+ protected final DetachedSession getPreviousSession() {
+ if (sessions.size() < 2)
+ return null;
+ else
+ return (DetachedSession) sessions.get(sessions.size() - 2);
}
public void init(BundleContext bundleContext) {
private String uuid;
private Properties properties = new Properties();
private String ref;
- private String path;
+ private String path = "";
+
+ public DetachedRequest() {
+
+ }
+
+ public DetachedRequest(String uuid) {
+ this.uuid = uuid;
+ }
public Properties getProperties() {
return properties;
--- /dev/null
+package org.argeo.slc.detached;
+
+import java.util.List;
+import java.util.Vector;
+
+public class DetachedSession {
+ public final static String PROP_DO_IT_AGAIN_POLICY = "slc.detached.doItAgainPolicy";
+ public final static String SKIP_UNTIL_ERROR = "skipUntilError";
+ public final static String REPLAY = "replay";
+
+ private String uuid = null;
+ private List requests = new Vector();
+ private List answers = new Vector();
+ private String doItAgainPolicy = SKIP_UNTIL_ERROR;
+
+ public boolean isClosed() {
+ if (answers.size() > 0) {
+ DetachedAnswer answer = (DetachedAnswer) answers
+ .get(answers.size() - 1);
+ return answer.getStatus() == DetachedAnswer.CLOSED_SESSION;
+ } else {
+ return false;
+ }
+ }
+
+ public String getDoItAgainPolicy() {
+ return doItAgainPolicy;
+ }
+
+ public void setDoItAgainPolicy(String doItAgainPolicy) {
+ this.doItAgainPolicy = doItAgainPolicy;
+ }
+
+ public List getRequests() {
+ return requests;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public List getAnswers() {
+ return answers;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.detached.admin;
+
+import org.argeo.slc.detached.DetachedAdminCommand;
+
+public class CloseSession implements DetachedAdminCommand {
+
+}
--- /dev/null
+package org.argeo.slc.detached.admin;
+
+import java.util.Properties;
+
+import org.argeo.slc.detached.DetachedAdminCommand;
+import org.argeo.slc.detached.DetachedRequest;
+import org.argeo.slc.detached.DetachedSession;
+import org.osgi.framework.BundleContext;
+
+public class OpenSession implements DetachedAdminCommand {
+
+ public DetachedSession execute(DetachedRequest request,
+ BundleContext bundleContext) {
+ DetachedSession session = new DetachedSession();
+ session.setUuid(Long.toString(System.currentTimeMillis()));
+
+ Properties props = request.getProperties();
+ if (props.containsKey(DetachedSession.PROP_DO_IT_AGAIN_POLICY))
+ session.setDoItAgainPolicy(props
+ .getProperty(DetachedSession.PROP_DO_IT_AGAIN_POLICY));
+
+ return session;
+ }
+}
private File processedAnswersDir;
public synchronized DetachedRequest receiveRequest() throws Exception {
- return (DetachedRequest) receiveFile(requestsDir, processedRequestsDir);
+ DetachedRequest request = (DetachedRequest) receiveFile(requestsDir,
+ processedRequestsDir);
+ log.debug("Received detached request #" + request.getUuid()
+ + " for ref '" + request.getRef() + "', path="
+ + request.getPath());
+ return request;
}
public void sendAnswer(DetachedAnswer answer) throws Exception {
sendFile(answersDir, answer);
+ log.debug("Sent detached answer #" + answer.getUuid());
}
public DetachedAnswer receiveAnswer() throws Exception {
- return (DetachedAnswer) receiveFile(answersDir, processedAnswersDir);
+ DetachedAnswer answer = (DetachedAnswer) receiveFile(answersDir,
+ processedAnswersDir);
+ log.debug("Received detached answer #" + answer.getUuid());
+ return answer;
}
public void sendRequest(DetachedRequest request) throws Exception {
sendFile(requestsDir, request);
+ log.debug("Sent detached request #" + request.getUuid()
+ + " for ref '" + request.getRef() + "', path="
+ + request.getPath());
}
protected void sendFile(File dir, DetachedCommunication detCom)
Manifest-Version: 1.0\r
-Export-Package: org.argeo.slc.detached;uses:="org.springframework.bean\r
- s.factory.support,org.apache.commons.logging,org.springframework.cont\r
- ext.support,org.springframework.core.io,org.osgi.framework,org.spring\r
- framework.beans.factory.xml,org.springframework.context,org.springfra\r
- mework.beans.factory",org.argeo.slc.detached.drivers;uses:="org.argeo\r
- .slc.detached"\r
+Export-Package: org.argeo.slc.detached.admin;uses:="org.osgi.framework\r
+ ,org.argeo.slc.detached",org.argeo.slc.detached;uses:="org.apache.com\r
+ mons.logging,org.springframework.context.support,org.springframework.\r
+ core.io,org.springframework.context,org.springframework.beans.factory\r
+ .xml,org.springframework.beans.factory.support,org.argeo.slc.detached\r
+ .admin,org.osgi.framework,org.springframework.beans.factory",org.arge\r
+ o.slc.detached.drivers;uses:="org.apache.commons.logging,org.argeo.sl\r
+ c.detached,org.springframework.beans.factory"\r
Built-By: mbaudier\r
Tool: Bnd-0.0.255\r
Bundle-Name: Argeo SLC Detached\r
Bundle-Vendor: Argeo\r
Build-Jdk: 1.6.0\r
Bundle-Version: 0.11.1.SNAPSHOT\r
-Bnd-LastModified: 1222787012918\r
+Bnd-LastModified: 1222949081084\r
Bundle-ManifestVersion: 2\r
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt\r
Bundle-Description: SLC Distribution\r
Import-Package: org.apache.commons.logging,org.argeo.slc.detached,org.\r
- argeo.slc.detached.drivers,org.osgi.framework,org.springframework.bea\r
- ns.factory,org.springframework.beans.factory.support,org.springframew\r
- ork.beans.factory.xml,org.springframework.context,org.springframework\r
- .context.support,org.springframework.core.io\r
+ argeo.slc.detached.admin,org.argeo.slc.detached.drivers,org.osgi.fram\r
+ ework,org.springframework.beans.factory,org.springframework.beans.fac\r
+ tory.support,org.springframework.beans.factory.xml,org.springframewor\r
+ k.context,org.springframework.context.support,org.springframework.cor\r
+ e.io\r
Bundle-SymbolicName: org.argeo.slc.detached\r
Bundle-DocURL: http://www.argeo.org\r
Originally-Created-By: Apache Maven Bundle Plugin\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+ <bean id="slcDefault.detached.admin.openSession"
+ class="org.argeo.slc.detached.admin.OpenSession">
+ </bean>
+
+ <bean id="slcDefault.detached.admin.closeSession"
+ class="org.argeo.slc.detached.admin.CloseSession">
+ </bean>
+ <!--
+ <bean id="jemmyTest" class="org.argeo.slc.jemmytest.DummyStep">
+ </bean>
+
+ <bean id="slcDefault.detached.admin.openSession"
+ class="org.argeo.slc.detached.DetachedExecutionServerImpl">
+ <property name="driver" ref="driver" />
+ </bean>
+
+ <bean id="driver"
+ class="org.argeo.slc.detached.drivers.FileDriver">
+ <property name="baseDir" value="file:${slc.workDir}/detached" />
+ </bean>
+ -->
+</beans>
\ No newline at end of file