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