]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedExecutionServerImpl.java
Move org.argeo.slc.detached
[gpl/argeo-slc.git] / runtime / org.argeo.slc.detached / src / main / java / org / argeo / slc / detached / DetachedExecutionServerImpl.java
1 package org.argeo.slc.detached;
2
3 import java.util.List;
4 import java.util.Vector;
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.argeo.slc.detached.admin.CloseSession;
9 import org.argeo.slc.detached.admin.OpenSession;
10 import org.osgi.framework.BundleContext;
11 import org.osgi.framework.ServiceReference;
12 import org.springframework.context.ApplicationContext;
13 import org.springframework.osgi.context.BundleContextAware;
14
15 public class DetachedExecutionServerImpl implements DetachedExecutionServer,
16 BundleContextAware {
17 private final static Log log = LogFactory
18 .getLog(DetachedExecutionServerImpl.class);
19
20 private final DetachedContextImpl detachedContext;
21 private final List sessions;
22
23 private int skipCount = 1;// start skipCount at 1 since the first step is
24 // always an open session
25
26 private BundleContext bundleContext;
27
28 public DetachedExecutionServerImpl() {
29 detachedContext = new DetachedContextImpl();
30 sessions = new Vector();
31 }
32
33 public synchronized DetachedAnswer executeRequest(DetachedRequest request) {
34 DetachedAnswer answer = null;
35 try {
36 // Find action
37 ServiceReference[] refs = bundleContext.getAllServiceReferences(
38 ApplicationContext.class.getName(), null);
39 Object obj = null;
40 for (int i = 0; i < refs.length; i++) {
41 ApplicationContext appContext = (ApplicationContext) bundleContext
42 .getService(refs[i]);
43 try {
44 obj = appContext.getBean(request.getRef());
45 } catch (Exception e) {
46 // silent
47 if (log.isTraceEnabled())
48 log.trace("Could not find ref " + request.getRef(), e);
49 }
50 if (obj != null) {
51 break;
52 }
53 }
54
55 if (obj == null)
56 throw new DetachedException("Could not find action with ref "
57 + request.getRef());
58
59 // Execute actions
60 if (obj instanceof DetachedStep) {
61 answer = processStep((DetachedStep) obj, request);
62
63 } else if (obj instanceof DetachedAdminCommand) {
64 answer = processAdminCommand((DetachedAdminCommand) obj,
65 request);
66 }
67
68 if (answer == null) {
69 throw new DetachedException("Unknown action type "
70 + obj.getClass() + " for action with ref "
71 + request.getRef());
72 }
73 } catch (Exception e) {
74 answer = new DetachedAnswer(request);
75 answer.setStatus(DetachedAnswer.ERROR);
76 answer.setLog(e.getMessage());
77 }
78 getCurrentSession().getRequests().add(request);
79 getCurrentSession().getAnswers().add(answer);
80 if (log.isDebugEnabled())
81 log.debug("Processed '" + request.getRef() + "' (status="
82 + answer.getStatusAsString() + ", path="
83 + request.getPath() + ")");
84 return answer;
85 }
86
87 protected DetachedAnswer processStep(DetachedStep obj,
88 DetachedRequest request) {
89 DetachedAnswer answer;
90 if (getCurrentSession() == null)
91 throw new DetachedException("No open session.");
92
93 StringBuffer skippedLog = new StringBuffer();
94 boolean execute = true;
95 if (getPreviousSession() != null && !getPreviousSession().isClosed()) {
96 if (getCurrentSession().getDoItAgainPolicy().equals(
97 DetachedSession.SKIP_UNTIL_ERROR)) {
98 // Skip execution of already successful steps
99 if (getPreviousSession().getAnswers().size() > skipCount) {
100 DetachedAnswer previousAnswer = (DetachedAnswer) getPreviousSession()
101 .getAnswers().get(skipCount);
102 DetachedRequest previousRequest = (DetachedRequest) getPreviousSession()
103 .getRequests().get(skipCount);
104 // Check paths
105 if (!previousRequest.getPath().equals(request.getPath())) {
106 String msg = "New request is not consistent with previous path. previousPath="
107 + previousRequest.getPath()
108 + ", newPath="
109 + request.getPath() + "\n";
110 skippedLog.append(msg);
111 log.warn(msg);
112 }
113
114 if (previousAnswer.getStatus() != DetachedAnswer.ERROR) {
115 execute = false;
116 String msg = "Skipped path " + request.getPath()
117 + " (skipCount=" + skipCount + ")";
118 skippedLog.append(msg);
119 log.info(msg);
120 skipCount++;
121 } else {
122 log
123 .info("Path "
124 + request.getPath()
125 + " was previously in error, executing it again."
126 + " (skipCount=" + skipCount
127 + "). Reset skip count to 1");
128 skipCount = 1;
129 }
130 } else {
131 // went further as skip count, doing nothing.
132 }
133 }
134 }
135
136 if (execute) {
137 DetachedStep step = (DetachedStep) obj;
138 answer = step.execute(detachedContext, request);
139 } else {
140 answer = new DetachedAnswer(request);
141 answer.setStatus(DetachedAnswer.SKIPPED);
142 answer.setLog(skippedLog.toString());
143 }
144 return answer;
145 }
146
147 protected DetachedAnswer processAdminCommand(DetachedAdminCommand obj,
148 DetachedRequest request) {
149 DetachedAnswer answer;
150 if (obj instanceof OpenSession) {
151 if (getCurrentSession() != null)
152 throw new DetachedException(
153 "There is already an open session #"
154 + getCurrentSession().getUuid());
155 sessions.add(((OpenSession) obj).execute(request, bundleContext));
156 answer = new DetachedAnswer(request, "Session #"
157 + getCurrentSession().getUuid() + " open.");
158 } else if (obj instanceof CloseSession) {
159 if (getCurrentSession() == null)
160 throw new DetachedException("There is no open session to close");
161 answer = new DetachedAnswer(request, "Session #"
162 + getCurrentSession().getUuid() + " closed.");
163 answer.setStatus(DetachedAnswer.CLOSED_SESSION);
164 } else {
165 answer = null;
166 }
167 return answer;
168 }
169
170 protected final DetachedSession getCurrentSession() {
171 if (sessions.size() == 0) {
172 return null;
173 } else {
174 DetachedSession session = (DetachedSession) sessions.get(sessions
175 .size() - 1);
176 List answers = session.getAnswers();
177 if (answers.size() > 0) {
178 DetachedAnswer lastAnswer = (DetachedAnswer) answers
179 .get(answers.size() - 1);
180 if (lastAnswer.getStatus() == DetachedAnswer.ERROR
181 || lastAnswer.getStatus() == DetachedAnswer.CLOSED_SESSION)
182 return null;
183 }
184 return session;
185 }
186 }
187
188 protected final DetachedSession getPreviousSession() {
189 if (sessions.size() < 2)
190 return null;
191 else
192 return (DetachedSession) sessions.get(sessions.size() - 2);
193 }
194
195 public void setBundleContext(BundleContext bundleContext) {
196 this.bundleContext = bundleContext;
197 }
198
199 }