]> git.argeo.org Git - gpl/argeo-slc.git/blob - legacy/runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/admin/MinimalBundlesManager.java
Clean up directories
[gpl/argeo-slc.git] / legacy / runtime / org.argeo.slc.detached / src / main / java / org / argeo / slc / detached / admin / MinimalBundlesManager.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.detached.admin;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.osgi.framework.Bundle;
21 import org.osgi.framework.BundleContext;
22 import org.osgi.framework.BundleException;
23 import org.osgi.framework.FrameworkEvent;
24 import org.osgi.framework.FrameworkListener;
25 import org.osgi.framework.InvalidSyntaxException;
26 import org.osgi.framework.ServiceReference;
27 import org.osgi.service.packageadmin.PackageAdmin;
28
29 /**
30 * Wraps low-level access to a {@link BundleContext}. Hacked from the related
31 * class in org.argeo.slc.support.osgi.
32 */
33 class MinimalBundlesManager implements FrameworkListener {
34 private final static Log log = LogFactory
35 .getLog(MinimalBundlesManager.class);
36
37 private final BundleContext bundleContext;
38
39 private long defaultTimeout = 10000l;
40 private final Object refreshedPackageSem = new Object();
41
42 public MinimalBundlesManager(BundleContext bundleContext) {
43 this.bundleContext = bundleContext;
44 bundleContext.addFrameworkListener(this);
45 }
46
47 protected void finalize() throws Throwable {
48 bundleContext.removeFrameworkListener(this);
49 }
50
51 /**
52 * @see #upgradeSynchronous(Bundle[])
53 */
54 public void upgradeSynchronous(Bundle bundle) {
55 upgradeSynchronous(new Bundle[] { bundle });
56 }
57
58 /**
59 * Stop the active bundles, update them, refresh them and restart the
60 * initially active bundles. All synchronously.
61 */
62 public void upgradeSynchronous(Bundle[] bundles) {
63 try {
64 // State (ACTIVE or other) before upgrading
65 int[] initialStates = new int[bundles.length];
66
67 // store initial state and stop active bundles
68 for (int i = 0; i < bundles.length; ++i) {
69 initialStates[i] = bundles[i].getState();
70 if (initialStates[i] == Bundle.ACTIVE) {
71 stopSynchronous(bundles[i]);
72 }
73 }
74
75 // update the bundles
76 for (int i = 0; i < bundles.length; ++i) {
77 updateSynchronous(bundles[i]);
78 }
79
80 // refresh the bundles
81 refreshSynchronous(bundles);
82
83 // restart the bundles that were ACTIVE before upgrading
84 for (int i = 0; i < bundles.length; ++i) {
85 if (initialStates[i] == Bundle.ACTIVE) {
86 startSynchronous(bundles[i]);
87
88 String filter = "(Bundle-SymbolicName="
89 + bundles[i].getSymbolicName() + ")";
90 // Wait for application context to be ready
91 // TODO: use service tracker
92 try {
93 getServiceRefSynchronous(
94 "org.springframework.context.ApplicationContext",
95 filter);
96 }
97 // in case of exception, catch and go on
98 catch (Exception e) {
99 log.error("getServiceRefSynchronous failed", e);
100 }
101 }
102 }
103 } catch (Exception e) {
104 throw new RuntimeException("Cannot update bundles", e);
105 }
106 }
107
108 /** Updates bundle synchronously. */
109 protected void updateSynchronous(Bundle bundle) throws BundleException {
110 bundle.update();
111 boolean waiting = true;
112
113 long begin = System.currentTimeMillis();
114 do {
115 int state = bundle.getState();
116 if (state == Bundle.INSTALLED || state == Bundle.ACTIVE
117 || state == Bundle.RESOLVED)
118 waiting = false;
119
120 sleep(100);
121 if (System.currentTimeMillis() - begin > defaultTimeout)
122 throw new RuntimeException("Update of bundle "
123 + bundle.getSymbolicName()
124 + " timed out. Bundle state = " + bundle.getState());
125 } while (waiting);
126
127 if (log.isDebugEnabled())
128 log.debug("Bundle " + bundle.getSymbolicName() + " updated.");
129 }
130
131 /** Starts bundle synchronously. Does nothing if already started. */
132 protected void startSynchronous(Bundle bundle) throws BundleException {
133 int originalState = bundle.getState();
134 if (originalState == Bundle.ACTIVE)
135 return;
136
137 bundle.start();
138 boolean waiting = true;
139
140 long begin = System.currentTimeMillis();
141 do {
142 if (bundle.getState() == Bundle.ACTIVE)
143 waiting = false;
144
145 sleep(100);
146 if (System.currentTimeMillis() - begin > defaultTimeout)
147 throw new RuntimeException("Start of bundle "
148 + bundle.getSymbolicName()
149 + " timed out. Bundle state = " + bundle.getState());
150 } while (waiting);
151
152 if (log.isDebugEnabled())
153 log.debug("Bundle " + bundle.getSymbolicName() + " started.");
154 }
155
156 /** Stops bundle synchronously. Does nothing if already started. */
157 protected void stopSynchronous(Bundle bundle) throws BundleException {
158 int originalState = bundle.getState();
159 if (originalState != Bundle.ACTIVE)
160 return;
161
162 bundle.stop();
163 boolean waiting = true;
164
165 long begin = System.currentTimeMillis();
166 do {
167 if (bundle.getState() != Bundle.ACTIVE
168 && bundle.getState() != Bundle.STOPPING)
169 waiting = false;
170
171 sleep(100);
172 if (System.currentTimeMillis() - begin > defaultTimeout)
173 throw new RuntimeException("Stop of bundle "
174 + bundle.getSymbolicName()
175 + " timed out. Bundle state = " + bundle.getState());
176 } while (waiting);
177
178 if (log.isDebugEnabled())
179 log.debug("Bundle " + bundle.getSymbolicName() + " stopped.");
180 }
181
182 /** Refresh bundle synchronously. Does nothing if already started. */
183 protected void refreshSynchronous(Bundle[] bundles) throws BundleException {
184 ServiceReference packageAdminRef = bundleContext
185 .getServiceReference(PackageAdmin.class.getName());
186 PackageAdmin packageAdmin = (PackageAdmin) bundleContext
187 .getService(packageAdminRef);
188 packageAdmin.refreshPackages(bundles);
189
190 synchronized (refreshedPackageSem) {
191 try {
192 refreshedPackageSem.wait(defaultTimeout);
193 } catch (InterruptedException e) {
194 // silent
195 }
196 }
197
198 if (log.isDebugEnabled())
199 log.debug("Bundles refreshed.");
200 }
201
202 public void frameworkEvent(FrameworkEvent event) {
203 if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
204 synchronized (refreshedPackageSem) {
205 refreshedPackageSem.notifyAll();
206 }
207 }
208 }
209
210 public ServiceReference[] getServiceRefSynchronous(String clss,
211 String filter) throws InvalidSyntaxException {
212 if (log.isTraceEnabled())
213 log.trace("Filter: '" + filter + "'");
214 ServiceReference[] sfs = null;
215 boolean waiting = true;
216 long begin = System.currentTimeMillis();
217 do {
218 sfs = bundleContext.getServiceReferences(clss, filter);
219
220 if (sfs != null)
221 waiting = false;
222
223 sleep(100);
224 if (System.currentTimeMillis() - begin > defaultTimeout)
225 throw new RuntimeException("Search of services " + clss
226 + " with filter " + filter + " timed out.");
227 } while (waiting);
228
229 return sfs;
230 }
231
232 protected void sleep(long ms) {
233 try {
234 Thread.sleep(ms);
235 } catch (InterruptedException e) {
236 // silent
237 }
238 }
239
240 }