2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.detached
.admin
;
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
;
30 * Wraps low-level access to a {@link BundleContext}. Hacked from the related
31 * class in org.argeo.slc.support.osgi.
33 class MinimalBundlesManager
implements FrameworkListener
{
34 private final static Log log
= LogFactory
35 .getLog(MinimalBundlesManager
.class);
37 private final BundleContext bundleContext
;
39 private long defaultTimeout
= 10000l;
40 private final Object refreshedPackageSem
= new Object();
42 public MinimalBundlesManager(BundleContext bundleContext
) {
43 this.bundleContext
= bundleContext
;
44 bundleContext
.addFrameworkListener(this);
47 protected void finalize() throws Throwable
{
48 bundleContext
.removeFrameworkListener(this);
52 * @see #upgradeSynchronous(Bundle[])
54 public void upgradeSynchronous(Bundle bundle
) {
55 upgradeSynchronous(new Bundle
[] { bundle
});
59 * Stop the active bundles, update them, refresh them and restart the
60 * initially active bundles. All synchronously.
62 public void upgradeSynchronous(Bundle
[] bundles
) {
64 // State (ACTIVE or other) before upgrading
65 int[] initialStates
= new int[bundles
.length
];
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
]);
76 for (int i
= 0; i
< bundles
.length
; ++i
) {
77 updateSynchronous(bundles
[i
]);
80 // refresh the bundles
81 refreshSynchronous(bundles
);
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
]);
88 String filter
= "(Bundle-SymbolicName="
89 + bundles
[i
].getSymbolicName() + ")";
90 // Wait for application context to be ready
91 // TODO: use service tracker
93 getServiceRefSynchronous(
94 "org.springframework.context.ApplicationContext",
97 // in case of exception, catch and go on
99 log
.error("getServiceRefSynchronous failed", e
);
103 } catch (Exception e
) {
104 throw new RuntimeException("Cannot update bundles", e
);
108 /** Updates bundle synchronously. */
109 protected void updateSynchronous(Bundle bundle
) throws BundleException
{
111 boolean waiting
= true;
113 long begin
= System
.currentTimeMillis();
115 int state
= bundle
.getState();
116 if (state
== Bundle
.INSTALLED
|| state
== Bundle
.ACTIVE
117 || state
== Bundle
.RESOLVED
)
121 if (System
.currentTimeMillis() - begin
> defaultTimeout
)
122 throw new RuntimeException("Update of bundle "
123 + bundle
.getSymbolicName()
124 + " timed out. Bundle state = " + bundle
.getState());
127 if (log
.isDebugEnabled())
128 log
.debug("Bundle " + bundle
.getSymbolicName() + " updated.");
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
)
138 boolean waiting
= true;
140 long begin
= System
.currentTimeMillis();
142 if (bundle
.getState() == Bundle
.ACTIVE
)
146 if (System
.currentTimeMillis() - begin
> defaultTimeout
)
147 throw new RuntimeException("Start of bundle "
148 + bundle
.getSymbolicName()
149 + " timed out. Bundle state = " + bundle
.getState());
152 if (log
.isDebugEnabled())
153 log
.debug("Bundle " + bundle
.getSymbolicName() + " started.");
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
)
163 boolean waiting
= true;
165 long begin
= System
.currentTimeMillis();
167 if (bundle
.getState() != Bundle
.ACTIVE
168 && bundle
.getState() != Bundle
.STOPPING
)
172 if (System
.currentTimeMillis() - begin
> defaultTimeout
)
173 throw new RuntimeException("Stop of bundle "
174 + bundle
.getSymbolicName()
175 + " timed out. Bundle state = " + bundle
.getState());
178 if (log
.isDebugEnabled())
179 log
.debug("Bundle " + bundle
.getSymbolicName() + " stopped.");
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
);
190 synchronized (refreshedPackageSem
) {
192 refreshedPackageSem
.wait(defaultTimeout
);
193 } catch (InterruptedException e
) {
198 if (log
.isDebugEnabled())
199 log
.debug("Bundles refreshed.");
202 public void frameworkEvent(FrameworkEvent event
) {
203 if (event
.getType() == FrameworkEvent
.PACKAGES_REFRESHED
) {
204 synchronized (refreshedPackageSem
) {
205 refreshedPackageSem
.notifyAll();
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();
218 sfs
= bundleContext
.getServiceReferences(clss
, filter
);
224 if (System
.currentTimeMillis() - begin
> defaultTimeout
)
225 throw new RuntimeException("Search of services " + clss
226 + " with filter " + filter
+ " timed out.");
232 protected void sleep(long ms
) {
235 } catch (InterruptedException e
) {