package org.argeo.slc.detached;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.List;
import java.util.Vector;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.slc.detached.admin.CloseSession;
import org.springframework.context.ApplicationContext;
import org.springframework.osgi.context.BundleContextAware;
+/** Default implementation of a detached server. */
public class DetachedExecutionServerImpl implements DetachedExecutionServer,
BundleContextAware {
private final static Log log = LogFactory
}
public synchronized DetachedAnswer executeRequest(DetachedRequest request) {
+ log.info("Received request " + request);
+
DetachedAnswer answer = null;
try {
// Find action
} catch (Exception e) {
answer = new DetachedAnswer(request);
answer.setStatus(DetachedAnswer.ERROR);
- answer.setLog(e.getMessage());
+ StringWriter writer = new StringWriter();
+ e.printStackTrace(new PrintWriter(writer));
+ answer.setLog(writer.toString());
+ IOUtils.closeQuietly(writer);
+ }
+
+ // Case where current session is unexpectly null
+ if (getCurrentSession() == null) {
+ log
+ .error("CURRENT SESSION IS NULL."
+ + " Detached status is inconsistent dumping sessions history:");
+ log.error(dumpSessionsHistory(request, answer));
+ if (answer != null) {
+ answer.setStatus(DetachedAnswer.ERROR);
+ answer
+ .addToLog("CURRENT SESSION IS NULL."
+ + " Detached status is inconsistent, see detached log for more details.");
+ return answer;
+ } else {
+ throw new DetachedException(
+ "Answer is null. Cannot return it. See log for more details.");
+ }
+
}
+
getCurrentSession().getRequests().add(request);
getCurrentSession().getAnswers().add(answer);
- if (log.isDebugEnabled())
- log.debug("Processed '" + request.getRef() + "' (status="
- + answer.getStatusAsString() + ", path="
- + request.getPath() + ")");
+ log.info("Sent answer " + answer);
return answer;
}
- protected DetachedAnswer processStep(DetachedStep obj,
+ protected synchronized DetachedAnswer processStep(DetachedStep obj,
DetachedRequest request) {
DetachedAnswer answer;
if (getCurrentSession() == null)
if (execute) {
DetachedStep step = (DetachedStep) obj;
+ // Actually execute the step
answer = step.execute(detachedContext, request);
} else {
answer = new DetachedAnswer(request);
return answer;
}
- protected DetachedAnswer processAdminCommand(DetachedAdminCommand obj,
- DetachedRequest request) {
+ protected synchronized DetachedAnswer processAdminCommand(
+ DetachedAdminCommand obj, DetachedRequest request) {
DetachedAnswer answer;
if (obj instanceof OpenSession) {
- if (getCurrentSession() != null)
- throw new DetachedException(
- "There is already an open session #"
- + getCurrentSession().getUuid());
+ if (getCurrentSession() != null) {
+ // TODO: better understand why there is sometimes two open
+ // sessions sent.
+ log.warn("There is already an open session #"
+ + getCurrentSession().getUuid() + ". Closing it...");
+ DetachedAnswer answerT = new DetachedAnswer(
+ request,
+ "Session #"
+ + getCurrentSession().getUuid()
+ + " forcibly closed. THIS ANSWER WAS NOT SENT BACK.");
+ answerT.setStatus(DetachedAnswer.CLOSED_SESSION);
+ getCurrentSession().getAnswers().add(answerT);
+ }
sessions.add(((OpenSession) obj).execute(request, bundleContext));
answer = new DetachedAnswer(request, "Session #"
+ getCurrentSession().getUuid() + " open.");
return answer;
}
- protected final DetachedSession getCurrentSession() {
+ /**
+ * Returns the current session based on the list of previous sessions.
+ *
+ * @return the current session or null if there is no session yet defined or
+ * if the last registered session is null or in error.
+ */
+ protected synchronized final DetachedSession getCurrentSession() {
if (sessions.size() == 0) {
return null;
} else {
}
}
- protected final DetachedSession getPreviousSession() {
+ protected synchronized String dumpSessionsHistory(
+ DetachedRequest requestCurrent, DetachedAnswer answerCurrent) {
+ StringBuffer buf = new StringBuffer("## SESSIONS HISTORY DUMP\n");
+ buf.append("# CURRENT\n");
+ buf.append("Current session: ").append(getCurrentSession())
+ .append('\n');
+ buf.append("Current request: ").append(requestCurrent).append('\n');
+ buf.append("Current answer: ").append(answerCurrent).append('\n');
+ buf.append("Skip count: ").append(skipCount).append('\n');
+
+ buf.append("# SESSIONS\n");
+ for (int i = 0; i < sessions.size(); i++) {
+ DetachedSession session = (DetachedSession) sessions.get(i);
+ buf.append(i).append(". ").append(session).append('\n');
+ List requests = session.getRequests();
+ List answers = session.getAnswers();
+ for (int j = 0; j < requests.size(); j++) {
+ DetachedRequest request = (DetachedRequest) requests.get(j);
+ buf.append('\t').append(j).append(". ").append(request).append(
+ '\n');
+ if (answers.size() > j) {
+ DetachedAnswer answer = (DetachedAnswer) answers.get(j);
+ buf.append('\t').append(j).append(". ").append(answer)
+ .append('\n');
+ }
+ }
+ }
+
+ buf.append("# DETACHED CONTEXT\n");
+ buf.append(detachedContext).append('\n');
+
+ return buf.toString();
+ }
+
+ protected synchronized final DetachedSession getPreviousSession() {
if (sessions.size() < 2)
return null;
else