]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java
Move unit tests
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.equinox / src / main / java / org / argeo / slc / equinox / ExecutionCommandProvider.java
1 package org.argeo.slc.equinox;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.argeo.slc.SlcException;
6 import org.argeo.slc.execution.ExecutionFlowDescriptor;
7 import org.argeo.slc.execution.ExecutionModule;
8 import org.eclipse.osgi.framework.console.CommandInterpreter;
9 import org.eclipse.osgi.framework.console.CommandProvider;
10 import org.osgi.framework.Bundle;
11 import org.osgi.framework.BundleContext;
12 import org.osgi.framework.BundleException;
13 import org.osgi.framework.FrameworkEvent;
14 import org.osgi.framework.FrameworkListener;
15 import org.osgi.framework.InvalidSyntaxException;
16 import org.osgi.framework.ServiceReference;
17 import org.osgi.service.packageadmin.PackageAdmin;
18 import org.springframework.beans.factory.InitializingBean;
19 import org.springframework.context.ApplicationContext;
20 import org.springframework.osgi.context.BundleContextAware;
21
22 public class ExecutionCommandProvider implements CommandProvider,
23 BundleContextAware, FrameworkListener, InitializingBean {
24 private final static Log log = LogFactory
25 .getLog(ExecutionCommandProvider.class);
26
27 private Long defaultTimeout = 10000l;
28
29 private BundleContext bundleContext;
30
31 private String lastModuleName = null;
32 private String lastExecutionName = null;
33
34 private final Object refreshedPackageSem = new Object();
35
36 /** @deprecated Use slc command instead. */
37 public Object _slc_exec(CommandInterpreter ci) {
38 return _slc(ci);
39 }
40
41 public Object _slc(CommandInterpreter ci) {
42 // TODO: check version
43 String firstArg = ci.nextArgument();
44 if (firstArg == null) {
45 if (lastModuleName != null) {
46 String cmd = "slc " + lastModuleName + " " + lastExecutionName;
47 if (log.isDebugEnabled())
48 log.debug("Execute again last command: " + cmd);
49 return ci.execute(cmd);
50 } else {
51 ci.execute("help");
52 throw new SlcException("Command not properly formatted");
53 }
54 }
55 String executionName = ci.nextArgument();
56
57 String moduleName = null;
58
59 // First check whether we have a bundleId
60 Long bundleId = null;
61 try {
62 bundleId = Long.parseLong(firstArg);
63 } catch (NumberFormatException e) {
64 // silent
65 }
66
67 // Look for bundle names containing pattern
68 Bundle bundle = null;
69 if (bundleId != null) {
70 bundle = bundleContext.getBundle(bundleId);
71 } else {
72 for (Bundle b : bundleContext.getBundles()) {
73 if (b.getSymbolicName().contains(firstArg)) {
74 bundle = b;
75 break;
76 }
77 }
78 }
79
80 if (bundle != null) {
81 moduleName = bundle.getSymbolicName();
82 lastModuleName = moduleName;
83 lastExecutionName = executionName;
84 } else {
85 log
86 .warn("Could not find any execution module matching these requirements.");
87 return null;
88 }
89
90 // Find module
91 ExecutionModule module = null;
92 ServiceReference serviceRef = null;
93 try {
94 stopSynchronous(bundle);
95 updateSynchronous(bundle);
96 // Refresh in case there are fragments
97 refreshSynchronous(bundle);
98 startSynchronous(bundle);
99
100 String filter = "(Bundle-SymbolicName=" + moduleName + ")";
101 // Wait for application context to be ready
102 getServiceRefSynchronous(ApplicationContext.class.getName(), filter);
103
104 if (log.isDebugEnabled())
105 log.debug("Bundle " + bundle.getSymbolicName()
106 + " ready to be used at latest version.");
107
108 ServiceReference[] sfs = getServiceRefSynchronous(
109 ExecutionModule.class.getName(), filter);
110
111 if (sfs.length > 1)
112 log
113 .warn("More than one execution module service found in module "
114 + moduleName);
115
116 if (sfs.length > 0) {
117 serviceRef = sfs[0];
118 module = (ExecutionModule) bundleContext.getService(serviceRef);
119 }
120
121 if (module != null) {
122 ExecutionFlowDescriptor descriptor = new ExecutionFlowDescriptor();
123 descriptor.setName(executionName);
124 module.execute(descriptor);
125 log.info("Executed " + executionName + " from " + moduleName);
126 }
127
128 } catch (Exception e) {
129 throw new SlcException("Cannot find or update module.", e);
130 } finally {
131 if (serviceRef != null)
132 bundleContext.ungetService(serviceRef);
133 }
134
135 return "COMMAND COMPLETED";
136 }
137
138 public String getHelp() {
139 StringBuffer buf = new StringBuffer();
140 buf.append("---SLC Execution Commands---\n");
141 buf
142 .append("\tslc (<id>|<segment of bsn>) <execution bean> - execute an execution flow (without arg, execute last)\n");
143 return buf.toString();
144
145 }
146
147 /** Updates bundle synchronously. */
148 protected void updateSynchronous(Bundle bundle) throws BundleException {
149 // int originalState = bundle.getState();
150 bundle.update();
151 boolean waiting = true;
152
153 long begin = System.currentTimeMillis();
154 do {
155 int state = bundle.getState();
156 if (state == Bundle.INSTALLED || state == Bundle.ACTIVE
157 || state == Bundle.RESOLVED)
158 waiting = false;
159
160 sleep(100);
161 if (System.currentTimeMillis() - begin > defaultTimeout)
162 throw new SlcException("Update of bundle "
163 + bundle.getSymbolicName()
164 + " timed out. Bundle state = " + bundle.getState());
165 } while (waiting);
166
167 if (log.isTraceEnabled())
168 log.debug("Bundle " + bundle.getSymbolicName() + " updated.");
169 }
170
171 /** Starts bundle synchronously. Does nothing if already started. */
172 protected void startSynchronous(Bundle bundle) throws BundleException {
173 int originalState = bundle.getState();
174 if (originalState == Bundle.ACTIVE)
175 return;
176
177 bundle.start();
178 boolean waiting = true;
179
180 long begin = System.currentTimeMillis();
181 do {
182 if (bundle.getState() == Bundle.ACTIVE)
183 waiting = false;
184
185 sleep(100);
186 if (System.currentTimeMillis() - begin > defaultTimeout)
187 throw new SlcException("Start of bundle "
188 + bundle.getSymbolicName()
189 + " timed out. Bundle state = " + bundle.getState());
190 } while (waiting);
191
192 if (log.isTraceEnabled())
193 log.debug("Bundle " + bundle.getSymbolicName() + " started.");
194 }
195
196 /** Stops bundle synchronously. Does nothing if already started. */
197 protected void stopSynchronous(Bundle bundle) throws BundleException {
198 int originalState = bundle.getState();
199 if (originalState != Bundle.ACTIVE)
200 return;
201
202 bundle.stop();
203 boolean waiting = true;
204
205 long begin = System.currentTimeMillis();
206 do {
207 if (bundle.getState() != Bundle.ACTIVE
208 && bundle.getState() != Bundle.STOPPING)
209 waiting = false;
210
211 sleep(100);
212 if (System.currentTimeMillis() - begin > defaultTimeout)
213 throw new SlcException("Stop of bundle "
214 + bundle.getSymbolicName()
215 + " timed out. Bundle state = " + bundle.getState());
216 } while (waiting);
217
218 if (log.isTraceEnabled())
219 log.debug("Bundle " + bundle.getSymbolicName() + " stopped.");
220 }
221
222 /** Refresh bundle synchronously. Does nothing if already started. */
223 protected void refreshSynchronous(Bundle bundle) throws BundleException {
224 ServiceReference packageAdminRef = bundleContext
225 .getServiceReference(PackageAdmin.class.getName());
226 PackageAdmin packageAdmin = (PackageAdmin) bundleContext
227 .getService(packageAdminRef);
228 Bundle[] bundles = { bundle };
229 packageAdmin.refreshPackages(bundles);
230
231 synchronized (refreshedPackageSem) {
232 try {
233 refreshedPackageSem.wait(defaultTimeout);
234 } catch (InterruptedException e) {
235 // silent
236 }
237 }
238
239 if (log.isTraceEnabled())
240 log.debug("Bundle " + bundle.getSymbolicName() + " refreshed.");
241 }
242
243 public void frameworkEvent(FrameworkEvent event) {
244 if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
245 synchronized (refreshedPackageSem) {
246 refreshedPackageSem.notifyAll();
247 }
248 }
249 }
250
251 protected ServiceReference[] getServiceRefSynchronous(String clss,
252 String filter) throws InvalidSyntaxException {
253 if (log.isTraceEnabled())
254 log.debug("Filter: '" + filter + "'");
255 ServiceReference[] sfs = null;
256 boolean waiting = true;
257 long begin = System.currentTimeMillis();
258 do {
259 sfs = bundleContext.getServiceReferences(clss, filter);
260
261 if (sfs != null)
262 waiting = false;
263
264 sleep(100);
265 if (System.currentTimeMillis() - begin > defaultTimeout)
266 throw new SlcException("Search of services " + clss
267 + " with filter " + filter + " timed out.");
268 } while (waiting);
269
270 return sfs;
271 }
272
273 protected void sleep(long ms) {
274 try {
275 Thread.sleep(ms);
276 } catch (InterruptedException e) {
277 // silent
278 }
279 }
280
281 public void setBundleContext(BundleContext bundleContext) {
282 this.bundleContext = bundleContext;
283 }
284
285 public void afterPropertiesSet() throws Exception {
286 bundleContext.addFrameworkListener(this);
287 }
288
289 public void setDefaultTimeout(Long defaultTimeout) {
290 this.defaultTimeout = defaultTimeout;
291 }
292
293 }