KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > internal > core > StartLevelManager


1 /*******************************************************************************
2  * Copyright (c) 2003, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.internal.core;
13
14 import java.io.IOException JavaDoc;
15 import java.security.*;
16 import java.util.*;
17 import org.eclipse.osgi.framework.debug.Debug;
18 import org.eclipse.osgi.framework.eventmgr.*;
19 import org.eclipse.osgi.service.resolver.*;
20 import org.eclipse.osgi.util.NLS;
21 import org.osgi.framework.*;
22
23 /**
24  * StartLevel service implementation for the OSGi specification.
25  *
26  * Framework service which allows management of framework and bundle startlevels.
27  *
28  * This class also acts as the StartLevel service factory class, providing StartLevel objects
29  * to those requesting org.osgi.service.startlevel.StartLevel service.
30  *
31  * If present, there will only be a single instance of this service
32  * registered in the framework.
33  */

34 // TODO there is no need to use ServiceFactory anymore (bug 184275)
35
public class StartLevelManager implements EventDispatcher, EventListener, ServiceFactory {
36
37     protected static Framework framework;
38     protected static EventManager eventManager;
39     protected static EventListeners startLevelListeners;
40
41     /** The framework beginning startlevel. Default is 1 */
42     protected int frameworkBeginningStartLevel = 1;
43
44     /** The initial bundle start level for newly installed bundles */
45     protected int initialBundleStartLevel = 1;
46     // default value is 1 for compatibility mode
47

48     /** The currently active framework start level */
49     private static int activeSL = 0;
50
51     /** An object used to lock the active startlevel while it is being referenced */
52     private static final Object JavaDoc lock = new Object JavaDoc();
53
54     volatile private boolean settingStartLevel = false;
55
56     private StartLevelImpl implementation;
57
58     /** This constructor is called by the Framework */
59     protected StartLevelManager(Framework framework) {
60         StartLevelManager.framework = framework;
61     }
62
63     protected void initialize() {
64         initialBundleStartLevel = framework.adaptor.getInitialBundleStartLevel();
65
66         // Set Framework Beginning Start Level Property
67
String JavaDoc value = framework.getProperty(Constants.OSGI_FRAMEWORKBEGINNINGSTARTLEVEL);
68         if (value == null) {
69             value = Constants.DEFAULT_STARTLEVEL;
70         } else {
71             try {
72                 if (Integer.parseInt(value) <= 0) {
73                     System.err.println(NLS.bind(Msg.PROPERTIES_INVALID_FW_STARTLEVEL, Constants.DEFAULT_STARTLEVEL));
74                     value = Constants.DEFAULT_STARTLEVEL;
75                 }
76             } catch (NumberFormatException JavaDoc nfe) {
77                 System.err.println(NLS.bind(Msg.PROPERTIES_INVALID_FW_STARTLEVEL, Constants.DEFAULT_STARTLEVEL));
78                 value = Constants.DEFAULT_STARTLEVEL;
79             }
80         }
81         framework.setProperty(Constants.OSGI_FRAMEWORKBEGINNINGSTARTLEVEL, value);
82         frameworkBeginningStartLevel = Integer.parseInt(value);
83
84         // create an event manager and a start level listener
85
eventManager = new EventManager("Start Level Event Dispatcher"); //$NON-NLS-1$
86
startLevelListeners = new EventListeners();
87         startLevelListeners.addListener(this, this);
88     }
89
90     protected void cleanup() {
91         eventManager.close();
92         eventManager = null;
93         startLevelListeners.removeAllListeners();
94         startLevelListeners = null;
95     }
96
97     /**
98      * Return the initial start level value that is assigned
99      * to a Bundle when it is first installed.
100      *
101      * @return The initial start level value for Bundles.
102      * @see #setInitialBundleStartLevel
103      */

104     public int getInitialBundleStartLevel() {
105         return initialBundleStartLevel;
106     }
107
108     /**
109      * Return the initial start level used when the framework is started.
110      *
111      * @return The framework start level.
112      */

113     public int getFrameworkStartLevel() {
114         return frameworkBeginningStartLevel;
115     }
116
117     /**
118      * Set the initial start level value that is assigned
119      * to a Bundle when it is first installed.
120      *
121      * <p>The initial bundle start level will be set to the specified start level. The
122      * initial bundle start level value will be persistently recorded
123      * by the Framework.
124      *
125      * <p>When a Bundle is installed via <tt>BundleContext.installBundle</tt>,
126      * it is assigned the initial bundle start level value.
127      *
128      * <p>The default initial bundle start level value is 1
129      * unless this method has been
130      * called to assign a different initial bundle
131      * start level value.
132      *
133      * <p>This method does not change the start level values of installed
134      * bundles.
135      *
136      * @param startlevel The initial start level for newly installed bundles.
137      * @throws IllegalArgumentException If the specified start level is less than or
138      * equal to zero.
139      * @throws SecurityException if the caller does not have the
140      * <tt>AdminPermission</tt> and the Java runtime environment supports
141      * permissions.
142      */

143     public void setInitialBundleStartLevel(int startlevel) {
144         framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL);
145         if (startlevel <= 0) {
146             throw new IllegalArgumentException JavaDoc();
147         }
148         initialBundleStartLevel = startlevel;
149         framework.adaptor.setInitialBundleStartLevel(startlevel);
150     }
151
152     /**
153      * Return the active start level value of the Framework.
154      *
155      * If the Framework is in the process of changing the start level
156      * this method must return the active start level if this
157      * differs from the requested start level.
158      *
159      * @return The active start level value of the Framework.
160      */

161     public int getStartLevel() {
162         return activeSL;
163     }
164
165     /**
166      * Modify the active start level of the Framework.
167      *
168      * <p>The Framework will move to the requested start level. This method
169      * will return immediately to the caller and the start level
170      * change will occur asynchronously on another thread.
171      *
172      * <p>If the specified start level is
173      * higher than the active start level, the
174      * Framework will continue to increase the start level
175      * until the Framework has reached the specified start level,
176      * starting bundles at each
177      * start level which are persistently marked to be started as described in the
178      * <tt>Bundle.start</tt> method.
179      *
180      * At each intermediate start level value on the
181      * way to and including the target start level, the framework must:
182      * <ol>
183      * <li>Change the active start level to the intermediate start level value.
184      * <li>Start bundles at the intermediate start level in
185      * ascending order by <tt>Bundle.getBundleId</tt>.
186      * </ol>
187      * When this process completes after the specified start level is reached,
188      * the Framework will broadcast a Framework event of
189      * type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to announce it has moved to the specified
190      * start level.
191      *
192      * <p>If the specified start level is lower than the active start level, the
193      * Framework will continue to decrease the start level
194      * until the Framework has reached the specified start level
195      * stopping bundles at each
196      * start level as described in the <tt>Bundle.stop</tt> method except that their
197      * persistently recorded state indicates that they must be restarted in the
198      * future.
199      *
200      * At each intermediate start level value on the
201      * way to and including the specified start level, the framework must:
202      * <ol>
203      * <li>Stop bundles at the intermediate start level in
204      * descending order by <tt>Bundle.getBundleId</tt>.
205      * <li>Change the active start level to the intermediate start level value.
206      * </ol>
207      * When this process completes after the specified start level is reached,
208      * the Framework will broadcast a Framework event of
209      * type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to announce it has moved to the specified
210      * start level.
211      *
212      * <p>If the specified start level is equal to the active start level, then
213      * no bundles are started or stopped, however, the Framework must broadcast
214      * a Framework event of type <tt>FrameworkEvent.STARTLEVEL_CHANGED</tt> to
215      * announce it has finished moving to the specified start level. This
216      * event may arrive before the this method return.
217      *
218      * @param newSL The requested start level for the Framework.
219      * @throws IllegalArgumentException If the specified start level is less than or
220      * equal to zero.
221      * @throws SecurityException If the caller does not have the
222      * <tt>AdminPermission</tt> and the Java runtime environment supports
223      * permissions.
224      */

225     public void setStartLevel(int newSL, org.osgi.framework.Bundle callerBundle) {
226         if (newSL <= 0) {
227             throw new IllegalArgumentException JavaDoc(NLS.bind(Msg.STARTLEVEL_EXCEPTION_INVALID_REQUESTED_STARTLEVEL, "" + newSL)); //$NON-NLS-1$
228
}
229         framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL);
230
231         if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
232             Debug.println("StartLevelImpl: setStartLevel: " + newSL + "; callerBundle = " + callerBundle.getBundleId()); //$NON-NLS-1$ //$NON-NLS-2$
233
}
234         issueEvent(new StartLevelEvent(StartLevelEvent.CHANGE_FW_SL, newSL, (AbstractBundle) callerBundle));
235
236     }
237
238     protected void setStartLevel(int newSL) {
239         setStartLevel(newSL, framework.systemBundle);
240     }
241
242     /**
243      * Internal method to allow the framework to be launched synchronously by calling the
244      * StartLevelListener worker calls directly
245      *
246      * This method does not return until all bundles that should be started are started
247      */

248     protected void launch(int startlevel) {
249
250         doSetStartLevel(startlevel, framework.systemBundle);
251     }
252
253     /**
254      * Internal method to shut down the framework synchronously by setting the startlevel to zero
255      * and calling the StartLevelListener worker calls directly
256      *
257      * This method does not return until all bundles are stopped and the framework is shut down.
258      */

259     protected void shutdown() {
260
261         doSetStartLevel(0, framework.systemBundle);
262     }
263
264     /**
265      * Internal worker method to set the startlevel
266      *
267      * @param newSL start level value
268      * @param callerBundle - the bundle initiating the change in start level
269      */

270     private void doSetStartLevel(int newSL, AbstractBundle callerBundle) {
271         synchronized (lock) {
272             settingStartLevel = true;
273             try {
274                 int tempSL = activeSL;
275
276                 if (newSL > tempSL) {
277                     for (int i = tempSL; i < newSL; i++) {
278                         if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
279                             Debug.println("sync - incrementing Startlevel from " + tempSL); //$NON-NLS-1$
280
}
281                         tempSL++;
282                         incFWSL(i + 1, callerBundle);
283                     }
284                 } else {
285                     AbstractBundle[] sortedBundles = getInstalledBundles(framework.bundles, true);
286                     for (int i = tempSL; i > newSL; i--) {
287                         if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
288                             Debug.println("sync - decrementing Startlevel from " + tempSL); //$NON-NLS-1$
289
}
290                         tempSL--;
291                         decFWSL(i - 1, sortedBundles);
292                     }
293                 }
294                 framework.publishFrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, callerBundle, null);
295                 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
296                     Debug.println("StartLevelImpl: doSetStartLevel: STARTLEVEL_CHANGED event published"); //$NON-NLS-1$
297
}
298             } finally {
299                 settingStartLevel = false;
300             }
301         }
302     }
303
304     /**
305      * This method is used within the package to save the actual active startlevel value for the framework.
306      * Externally the setStartLevel method must be used.
307      *
308      * @param newSL - the new startlevel to save
309      */

310     protected void saveActiveStartLevel(int newSL) {
311         synchronized (lock) {
312             activeSL = newSL;
313         }
314     }
315
316     /**
317      * Return the persistent state of the specified bundle.
318      *
319      * <p>This method returns the persistent state of a bundle.
320      * The persistent state of a bundle indicates whether a bundle
321      * is persistently marked to be started when it's start level is
322      * reached.
323      *
324      * @return <tt>true</tt> if the bundle is persistently marked to be started,
325      * <tt>false</tt> if the bundle is not persistently marked to be started.
326      * @exception java.lang.IllegalArgumentException If the specified bundle has been uninstalled.
327      */

328     public boolean isBundlePersistentlyStarted(org.osgi.framework.Bundle bundle) {
329         if (bundle.getState() == Bundle.UNINSTALLED)
330             throw new IllegalArgumentException JavaDoc(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation()));
331         return (((AbstractBundle) bundle).getBundleData().getStatus() & Constants.BUNDLE_STARTED) != 0;
332     }
333
334     public boolean isBundleActivationPolicyUsed(Bundle bundle) {
335         if (bundle.getState() == Bundle.UNINSTALLED)
336             throw new IllegalArgumentException JavaDoc(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation()));
337         return (((AbstractBundle) bundle).getBundleData().getStatus() & Constants.BUNDLE_ACTIVATION_POLICY) != 0;
338     }
339
340     /**
341      * Return the assigned start level value for the specified Bundle.
342      *
343      * @param bundle The target bundle.
344      * @return The start level value of the specified Bundle.
345      * @exception java.lang.IllegalArgumentException If the specified bundle has been uninstalled.
346      */

347     public int getBundleStartLevel(org.osgi.framework.Bundle bundle) {
348
349         if (bundle.getState() == Bundle.UNINSTALLED) {
350             throw new IllegalArgumentException JavaDoc(NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation()));
351         }
352         return ((AbstractBundle) bundle).getStartLevel();
353     }
354
355     /**
356      * Assign a start level value to the specified Bundle.
357      *
358      * <p>The specified bundle will be assigned the specified start level. The
359      * start level value assigned to the bundle will be persistently recorded
360      * by the Framework.
361      *
362      * If the new start level for the bundle is lower than or equal to the active start level of
363      * the Framework, the Framework will start the specified bundle as described
364      * in the <tt>Bundle.start</tt> method if the bundle is persistently marked
365      * to be started. The actual starting of this bundle must occur asynchronously.
366      *
367      * If the new start level for the bundle is higher than the active start level of
368      * the Framework, the Framework will stop the specified bundle as described
369      * in the <tt>Bundle.stop</tt> method except that the persistently recorded
370      * state for the bundle indicates that the bundle must be restarted in the
371      * future. The actual stopping of this bundle must occur asynchronously.
372      *
373      * @param bundle The target bundle.
374      * @param newSL The new start level for the specified Bundle.
375      * @throws IllegalArgumentException
376      * If the specified bundle has been uninstalled or
377      * if the specified start level is less than or equal to zero, or the specified bundle is
378      * the system bundle.
379      * @throws SecurityException if the caller does not have the
380      * <tt>AdminPermission</tt> and the Java runtime environment supports
381      * permissions.
382      */

383     public void setBundleStartLevel(org.osgi.framework.Bundle bundle, int newSL) {
384
385         String JavaDoc exceptionText = null;
386         if (bundle.getBundleId() == 0) { // system bundle has id=0
387
exceptionText = Msg.STARTLEVEL_CANT_CHANGE_SYSTEMBUNDLE_STARTLEVEL;
388         } else if (bundle.getState() == Bundle.UNINSTALLED) {
389             exceptionText = NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation());
390         } else if (newSL <= 0) {
391             exceptionText = NLS.bind(Msg.STARTLEVEL_EXCEPTION_INVALID_REQUESTED_STARTLEVEL, "" + newSL); //$NON-NLS-1$
392
}
393         if (exceptionText != null)
394             throw new IllegalArgumentException JavaDoc(exceptionText);
395         // first check the permission of the caller
396
framework.checkAdminPermission(bundle, AdminPermission.EXECUTE);
397         try {
398             // if the bundle's startlevel is not already at the requested startlevel
399
if (newSL != ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundle).getStartLevel()) {
400                 final AbstractBundle b = (AbstractBundle) bundle;
401                 b.getBundleData().setStartLevel(newSL);
402                 try {
403                     AccessController.doPrivileged(new PrivilegedExceptionAction() {
404                         public Object JavaDoc run() throws Exception JavaDoc {
405                             b.getBundleData().save();
406                             return null;
407                         }
408                     });
409                 } catch (PrivilegedActionException e) {
410                     if (e.getException() instanceof IOException JavaDoc) {
411                         throw (IOException JavaDoc) e.getException();
412                     }
413                     throw (RuntimeException JavaDoc) e.getException();
414                 }
415                 // handle starting or stopping the bundle asynchronously
416
issueEvent(new StartLevelEvent(StartLevelEvent.CHANGE_BUNDLE_SL, newSL, (AbstractBundle) bundle));
417             }
418         } catch (IOException JavaDoc e) {
419             framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
420         }
421
422     }
423
424     /**
425      * This method sends the StartLevelEvent to the EventManager for dispatching
426      *
427      * @param sle The event to be queued to the Event Manager
428      */

429     private void issueEvent(StartLevelEvent sle) {
430
431         /* queue to hold set of listeners */
432         ListenerQueue queue = new ListenerQueue(eventManager);
433
434         /* add set of StartLevelListeners to queue */
435         queue.queueListeners(startLevelListeners, this);
436
437         /* dispatch event to set of listeners */
438         queue.dispatchEventAsynchronous(sle.getType(), sle);
439     }
440
441     /**
442      * This method is the call back that is called once for each listener.
443      * This method must cast the EventListener object to the appropriate listener
444      * class for the event type and call the appropriate listener method.
445      *
446      * @param listener This listener must be cast to the appropriate listener
447      * class for the events created by this source and the appropriate listener method
448      * must then be called.
449      * @param listenerObject This is the optional object that was passed to
450      * EventListeners.addListener when the listener was added to the EventListeners.
451      * @param eventAction This value was passed to the ListenerQueue object via one of its
452      * dispatchEvent* method calls. It can provide information (such
453      * as which listener method to call) so that this method
454      * can complete the delivery of the event to the listener.
455      * @param eventObject This object was passed to the ListenerQueue object via one of its
456      * dispatchEvent* method calls. This object was created by the event source and
457      * is passed to this method. It should contain all the necessary information (such
458      * as what event object to pass) so that this method
459      * can complete the delivery of the event to the listener.
460      */

461     public void dispatchEvent(Object JavaDoc listener, Object JavaDoc listenerObject, int eventAction, Object JavaDoc eventObject) {
462         try {
463             switch (eventAction) {
464                 case StartLevelEvent.CHANGE_BUNDLE_SL :
465                     setBundleSL((StartLevelEvent) eventObject);
466                     break;
467                 case StartLevelEvent.CHANGE_FW_SL :
468                     doSetStartLevel(((StartLevelEvent) eventObject).getNewSL(), ((StartLevelEvent) eventObject).getBundle());
469                     break;
470             }
471         } catch (Throwable JavaDoc t) {
472             // allow the adaptor to handle this unexpected error
473
framework.adaptor.handleRuntimeError(t);
474         }
475     }
476
477     /**
478      * Increment the active startlevel by one
479      */

480     protected void incFWSL(int incToSL, AbstractBundle callerBundle) {
481         if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
482             Debug.println("SLL: incFWSL: saving activeSL of " + incToSL); //$NON-NLS-1$
483
}
484
485         saveActiveStartLevel(incToSL);
486
487         AbstractBundle[] launch;
488         BundleRepository bundles = framework.bundles;
489
490         launch = getInstalledBundles(bundles, false);
491
492         if (incToSL == 1) { // framework was not active
493

494             /* Load all installed bundles */
495             loadInstalledBundles(launch);
496             /* Resume all bundles */
497             resumeBundles(launch, true);
498
499             /* publish the framework started event */
500             if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
501                 Debug.println("SLL: Framework started"); //$NON-NLS-1$
502
}
503
504             framework.publishFrameworkEvent(FrameworkEvent.STARTED, callerBundle, null);
505
506         } else {
507             // incrementing an already active framework
508
resumeBundles(launch, false);
509         }
510     }
511
512     /**
513      * Build an array of all installed bundles to be launch.
514      * The returned array is sorted by increasing startlevel/id order.
515      * @param bundles - the bundles installed in the framework
516      * @return A sorted array of bundles
517      */

518     private AbstractBundle[] getInstalledBundles(BundleRepository bundles, boolean sortByDependency) {
519
520         /* make copy of bundles vector in case it is modified during launch */
521         AbstractBundle[] installedBundles;
522
523         synchronized (bundles) {
524             List allBundles = bundles.getBundles();
525             installedBundles = new AbstractBundle[allBundles.size()];
526             allBundles.toArray(installedBundles);
527
528             /* sort bundle array in ascending startlevel / bundle id order
529              * so that bundles are started in ascending order.
530              */

531             Util.sort(installedBundles, 0, installedBundles.length);
532             if (sortByDependency)
533                 sortByDependency(installedBundles);
534         }
535         return installedBundles;
536     }
537
538     static void sortByDependency(AbstractBundle[] bundles) {
539         synchronized (framework.bundles) {
540             if (bundles.length <= 1)
541                 return;
542             int currentSL = bundles[0].getStartLevel();
543             int currentSLindex = 0;
544             boolean lazy = false;
545             for (int i = 0; i < bundles.length; i++) {
546                 if (currentSL != bundles[i].getStartLevel()) {
547                     if (lazy)
548                         sortByDependencies(bundles, currentSLindex, i);
549                     currentSL = bundles[i].getStartLevel();
550                     currentSLindex = i;
551                     lazy = false;
552                 }
553                 lazy |= (bundles[i].getBundleData().getStatus() & Constants.BUNDLE_LAZY_START) != 0;
554             }
555             // sort the last set of bundles
556
if (lazy)
557                 sortByDependencies(bundles, currentSLindex, bundles.length);
558         }
559     }
560
561     private static void sortByDependencies(AbstractBundle[] bundles, int start, int end) {
562         if (end - start <= 1)
563             return;
564         List descList = new ArrayList(end - start);
565         List missingDescs = new ArrayList(0);
566         for (int i = start; i < end; i++) {
567             BundleDescription desc = bundles[i].getBundleDescription();
568             if (desc != null)
569                 descList.add(desc);
570             else
571                 missingDescs.add(bundles[i]);
572         }
573         if (descList.size() <= 1)
574             return;
575         BundleDescription[] descriptions = (BundleDescription[]) descList.toArray(new BundleDescription[descList.size()]);
576         framework.adaptor.getPlatformAdmin().getStateHelper().sortBundles(descriptions);
577         for (int i = start; i < descriptions.length + start; i++)
578             bundles[i] = framework.bundles.getBundle(descriptions[i - start].getBundleId());
579         if (missingDescs.size() > 0) {
580             Iterator missing = missingDescs.iterator();
581             for (int i = start + descriptions.length; i < end && missing.hasNext(); i++)
582                 bundles[i] = (AbstractBundle) missing.next();
583         }
584     }
585
586     /**
587      * Load all bundles in the list
588      * @param installedBundles a list of bundles to load
589      */

590     private void loadInstalledBundles(AbstractBundle[] installedBundles) {
591
592         for (int i = 0; i < installedBundles.length; i++) {
593             AbstractBundle bundle = installedBundles[i];
594             if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
595                 Debug.println("SLL: Trying to load bundle " + bundle); //$NON-NLS-1$
596
}
597             bundle.load();
598         }
599     }
600
601     /**
602      * Resume all bundles in the launch list
603      * @param launch a list of Bundle Objects to launch
604      * @param launchingFW tells whether or not to launch the framework (system bundle)
605      */

606     private void resumeBundles(AbstractBundle[] launch, boolean launchingFW) {
607         if (launchingFW) {
608             /* Start the system bundle */
609             try {
610                 framework.systemBundle.state = Bundle.STARTING;
611                 framework.systemBundle.context.start();
612             } catch (BundleException be) {
613                 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
614                     Debug.println("SLL: Bundle resume exception: " + be.getMessage()); //$NON-NLS-1$
615
Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
616                 }
617
618                 framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, be);
619                 throw new RuntimeException JavaDoc(be.getMessage());
620             }
621
622         }
623         /* Resume all bundles that were previously started and whose startlevel is <= the active startlevel */
624         int fwsl = getStartLevel();
625         for (int i = 0; i < launch.length; i++) {
626             int bsl = launch[i].getStartLevel();
627             if (bsl < fwsl) {
628                 // skip bundles who should have already been started
629
continue;
630             } else if (bsl == fwsl) {
631                 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
632                     Debug.println("SLL: Active sl = " + fwsl + "; Bundle " + launch[i].getBundleId() + " sl = " + bsl); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
633
}
634                 framework.resumeBundle(launch[i]);
635             } else {
636                 // can stop resuming bundles since any remaining bundles have a greater startlevel than the framework active startlevel
637
break;
638             }
639         }
640
641         framework.systemBundle.state = Bundle.ACTIVE;
642
643     }
644
645     /**
646      * Decrement the active startlevel by one
647      * @param decToSL - the startlevel value to set the framework to
648      */

649     protected void decFWSL(int decToSL, AbstractBundle[] shutdown) {
650         if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
651             Debug.println("SLL: decFWSL: saving activeSL of " + decToSL); //$NON-NLS-1$
652
}
653
654         saveActiveStartLevel(decToSL);
655
656         if (decToSL == 0) { // stopping the framework
657
// stop and unload all bundles
658
suspendAllBundles(framework.bundles);
659             unloadAllBundles(framework.bundles);
660             return;
661         }
662         // just decrementing the active startlevel - framework is not shutting down
663
for (int i = shutdown.length - 1; i >= 0; i--) {
664             int bsl = shutdown[i].getStartLevel();
665             if (bsl > decToSL + 1)
666                 // skip bundles who should have already been stopped
667
continue;
668             else if (bsl <= decToSL)
669                 // stopped all bundles we are going to for this start level
670
break;
671             else if (shutdown[i].isActive()) {
672                 // if bundle is active or starting, then stop the bundle
673
if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL)
674                     Debug.println("SLL: stopping bundle " + shutdown[i].getBundleId()); //$NON-NLS-1$
675
framework.suspendBundle(shutdown[i], false);
676             }
677         }
678     }
679
680     /**
681      * Suspends all bundles in the vector passed in.
682      * @param bundles list of Bundle objects to be suspended
683      */

684     private void suspendAllBundles(BundleRepository bundles) {
685         boolean changed;
686         do {
687             changed = false;
688
689             AbstractBundle[] shutdown = this.getInstalledBundles(bundles, false);
690
691             // shutdown all running bundles
692
for (int i = shutdown.length - 1; i >= 0; i--) {
693                 AbstractBundle bundle = shutdown[i];
694
695                 if (framework.suspendBundle(bundle, false)) {
696                     if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
697                         Debug.println("SLL: stopped bundle " + bundle.getBundleId()); //$NON-NLS-1$
698
}
699                     changed = true;
700                 }
701             }
702         } while (changed);
703
704         try {
705             framework.systemBundle.context.stop();
706         } catch (BundleException sbe) {
707             if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
708                 Debug.println("SLL: Bundle suspend exception: " + sbe.getMessage()); //$NON-NLS-1$
709
Debug.printStackTrace(sbe.getNestedException() == null ? sbe : sbe.getNestedException());
710             }
711
712             framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, sbe);
713         }
714
715         framework.systemBundle.state = Bundle.RESOLVED;
716     }
717
718     /**
719      * Unloads all bundles in the vector passed in.
720      * @param bundles list of Bundle objects to be unloaded
721      */

722     private void unloadAllBundles(BundleRepository bundles) {
723         synchronized (bundles) {
724             /* unload all installed bundles */
725             List allBundles = bundles.getBundles();
726             int size = allBundles.size();
727
728             for (int i = 0; i < size; i++) {
729                 AbstractBundle bundle = (AbstractBundle) allBundles.get(i);
730
731                 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
732                     Debug.println("SLL: Trying to unload bundle " + bundle); //$NON-NLS-1$
733
}
734                 bundle.refresh();
735                 try {
736                     // make sure we close all the bundle data objects
737
bundle.getBundleData().close();
738                 } catch (IOException JavaDoc e) {
739                     // ignore, we are shutting down anyway
740
}
741             }
742         }
743     }
744
745     /**
746      * Set the bundle's startlevel to the new value
747      * This may cause the bundle to start or stop based on the active framework startlevel
748      * @param startLevelEvent - the event requesting change in bundle startlevel
749      */

750     protected void setBundleSL(StartLevelEvent startLevelEvent) {
751         synchronized (lock) {
752             int currentSL = getStartLevel();
753             int newSL = startLevelEvent.getNewSL();
754             AbstractBundle bundle = startLevelEvent.getBundle();
755
756             if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
757                 Debug.print("SLL: bundle active=" + bundle.isActive()); //$NON-NLS-1$
758
Debug.print("; newSL = " + newSL); //$NON-NLS-1$
759
Debug.println("; activeSL = " + currentSL); //$NON-NLS-1$
760
}
761
762             if (bundle.isActive() && (newSL > currentSL)) {
763                 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
764                     Debug.println("SLL: stopping bundle " + bundle.getBundleId()); //$NON-NLS-1$
765
}
766                 framework.suspendBundle(bundle, false);
767             } else {
768                 if (!bundle.isActive() && (newSL <= currentSL)) {
769                     if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
770                         Debug.println("SLL: starting bundle " + bundle.getBundleId()); //$NON-NLS-1$
771
}
772                     framework.resumeBundle(bundle);
773                 }
774             }
775             if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) {
776                 Debug.println("SLL: Bundle Startlevel set to " + newSL); //$NON-NLS-1$
777
}
778         }
779     }
780
781     /**
782      * Returns a StartLevel object, created for each requesting bundle.
783      *
784      * @param owner bundle, requested to get StartLevel service.
785      * @pre callerBundle!=null
786      * @param registration ServiceRegistration of the StartLevel service
787      * @pre sReg!=null
788      * @return StartLevel object
789      */

790     public synchronized Object JavaDoc getService(Bundle owner, ServiceRegistration registration) {
791         if (implementation == null)
792             implementation = new StartLevelImpl(framework.systemBundle, framework);
793         return implementation;
794     }
795
796     /**
797      * Does nothing, as the StartLevel bundle does not keep references to StartLevel objects.
798      *
799      * @param owner bundle requesting to unget StartLevel service.
800      * @param registration ServiceRegistration of StartLevel
801      * @param service Service object, already been got by this bundle.
802      */

803     public void ungetService(Bundle owner, ServiceRegistration registration, Object JavaDoc service) {
804         // do nothing;
805
}
806
807     public boolean isSettingStartLevel() {
808         return settingStartLevel;
809     }
810 }
811
Popular Tags