1 11 12 package org.eclipse.osgi.framework.internal.core; 13 14 import java.io.IOException ; 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 34 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 42 protected int frameworkBeginningStartLevel = 1; 43 44 45 protected int initialBundleStartLevel = 1; 46 48 49 private static int activeSL = 0; 50 51 52 private static final Object lock = new Object (); 53 54 volatile private boolean settingStartLevel = false; 55 56 private StartLevelImpl implementation; 57 58 59 protected StartLevelManager(Framework framework) { 60 StartLevelManager.framework = framework; 61 } 62 63 protected void initialize() { 64 initialBundleStartLevel = framework.adaptor.getInitialBundleStartLevel(); 65 66 String 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 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 eventManager = new EventManager("Start Level Event Dispatcher"); 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 104 public int getInitialBundleStartLevel() { 105 return initialBundleStartLevel; 106 } 107 108 113 public int getFrameworkStartLevel() { 114 return frameworkBeginningStartLevel; 115 } 116 117 143 public void setInitialBundleStartLevel(int startlevel) { 144 framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL); 145 if (startlevel <= 0) { 146 throw new IllegalArgumentException (); 147 } 148 initialBundleStartLevel = startlevel; 149 framework.adaptor.setInitialBundleStartLevel(startlevel); 150 } 151 152 161 public int getStartLevel() { 162 return activeSL; 163 } 164 165 225 public void setStartLevel(int newSL, org.osgi.framework.Bundle callerBundle) { 226 if (newSL <= 0) { 227 throw new IllegalArgumentException (NLS.bind(Msg.STARTLEVEL_EXCEPTION_INVALID_REQUESTED_STARTLEVEL, "" + newSL)); } 229 framework.checkAdminPermission(framework.systemBundle, AdminPermission.STARTLEVEL); 230 231 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 232 Debug.println("StartLevelImpl: setStartLevel: " + newSL + "; callerBundle = " + callerBundle.getBundleId()); } 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 248 protected void launch(int startlevel) { 249 250 doSetStartLevel(startlevel, framework.systemBundle); 251 } 252 253 259 protected void shutdown() { 260 261 doSetStartLevel(0, framework.systemBundle); 262 } 263 264 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); } 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); } 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"); } 298 } finally { 299 settingStartLevel = false; 300 } 301 } 302 } 303 304 310 protected void saveActiveStartLevel(int newSL) { 311 synchronized (lock) { 312 activeSL = newSL; 313 } 314 } 315 316 328 public boolean isBundlePersistentlyStarted(org.osgi.framework.Bundle bundle) { 329 if (bundle.getState() == Bundle.UNINSTALLED) 330 throw new IllegalArgumentException (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 (NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation())); 337 return (((AbstractBundle) bundle).getBundleData().getStatus() & Constants.BUNDLE_ACTIVATION_POLICY) != 0; 338 } 339 340 347 public int getBundleStartLevel(org.osgi.framework.Bundle bundle) { 348 349 if (bundle.getState() == Bundle.UNINSTALLED) { 350 throw new IllegalArgumentException (NLS.bind(Msg.BUNDLE_UNINSTALLED_EXCEPTION, ((AbstractBundle) bundle).getBundleData().getLocation())); 351 } 352 return ((AbstractBundle) bundle).getStartLevel(); 353 } 354 355 383 public void setBundleStartLevel(org.osgi.framework.Bundle bundle, int newSL) { 384 385 String exceptionText = null; 386 if (bundle.getBundleId() == 0) { 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); } 393 if (exceptionText != null) 394 throw new IllegalArgumentException (exceptionText); 395 framework.checkAdminPermission(bundle, AdminPermission.EXECUTE); 397 try { 398 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 run() throws Exception { 405 b.getBundleData().save(); 406 return null; 407 } 408 }); 409 } catch (PrivilegedActionException e) { 410 if (e.getException() instanceof IOException ) { 411 throw (IOException ) e.getException(); 412 } 413 throw (RuntimeException ) e.getException(); 414 } 415 issueEvent(new StartLevelEvent(StartLevelEvent.CHANGE_BUNDLE_SL, newSL, (AbstractBundle) bundle)); 417 } 418 } catch (IOException e) { 419 framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e); 420 } 421 422 } 423 424 429 private void issueEvent(StartLevelEvent sle) { 430 431 432 ListenerQueue queue = new ListenerQueue(eventManager); 433 434 435 queue.queueListeners(startLevelListeners, this); 436 437 438 queue.dispatchEventAsynchronous(sle.getType(), sle); 439 } 440 441 461 public void dispatchEvent(Object listener, Object listenerObject, int eventAction, Object 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 t) { 472 framework.adaptor.handleRuntimeError(t); 474 } 475 } 476 477 480 protected void incFWSL(int incToSL, AbstractBundle callerBundle) { 481 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 482 Debug.println("SLL: incFWSL: saving activeSL of " + incToSL); } 484 485 saveActiveStartLevel(incToSL); 486 487 AbstractBundle[] launch; 488 BundleRepository bundles = framework.bundles; 489 490 launch = getInstalledBundles(bundles, false); 491 492 if (incToSL == 1) { 494 495 loadInstalledBundles(launch); 496 497 resumeBundles(launch, true); 498 499 500 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 501 Debug.println("SLL: Framework started"); } 503 504 framework.publishFrameworkEvent(FrameworkEvent.STARTED, callerBundle, null); 505 506 } else { 507 resumeBundles(launch, false); 509 } 510 } 511 512 518 private AbstractBundle[] getInstalledBundles(BundleRepository bundles, boolean sortByDependency) { 519 520 521 AbstractBundle[] installedBundles; 522 523 synchronized (bundles) { 524 List allBundles = bundles.getBundles(); 525 installedBundles = new AbstractBundle[allBundles.size()]; 526 allBundles.toArray(installedBundles); 527 528 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 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 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); } 597 bundle.load(); 598 } 599 } 600 601 606 private void resumeBundles(AbstractBundle[] launch, boolean launchingFW) { 607 if (launchingFW) { 608 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()); Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException()); 616 } 617 618 framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, be); 619 throw new RuntimeException (be.getMessage()); 620 } 621 622 } 623 624 int fwsl = getStartLevel(); 625 for (int i = 0; i < launch.length; i++) { 626 int bsl = launch[i].getStartLevel(); 627 if (bsl < fwsl) { 628 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); } 634 framework.resumeBundle(launch[i]); 635 } else { 636 break; 638 } 639 } 640 641 framework.systemBundle.state = Bundle.ACTIVE; 642 643 } 644 645 649 protected void decFWSL(int decToSL, AbstractBundle[] shutdown) { 650 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 651 Debug.println("SLL: decFWSL: saving activeSL of " + decToSL); } 653 654 saveActiveStartLevel(decToSL); 655 656 if (decToSL == 0) { suspendAllBundles(framework.bundles); 659 unloadAllBundles(framework.bundles); 660 return; 661 } 662 for (int i = shutdown.length - 1; i >= 0; i--) { 664 int bsl = shutdown[i].getStartLevel(); 665 if (bsl > decToSL + 1) 666 continue; 668 else if (bsl <= decToSL) 669 break; 671 else if (shutdown[i].isActive()) { 672 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) 674 Debug.println("SLL: stopping bundle " + shutdown[i].getBundleId()); framework.suspendBundle(shutdown[i], false); 676 } 677 } 678 } 679 680 684 private void suspendAllBundles(BundleRepository bundles) { 685 boolean changed; 686 do { 687 changed = false; 688 689 AbstractBundle[] shutdown = this.getInstalledBundles(bundles, false); 690 691 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()); } 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()); 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 722 private void unloadAllBundles(BundleRepository bundles) { 723 synchronized (bundles) { 724 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); } 734 bundle.refresh(); 735 try { 736 bundle.getBundleData().close(); 738 } catch (IOException e) { 739 } 741 } 742 } 743 } 744 745 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()); Debug.print("; newSL = " + newSL); Debug.println("; activeSL = " + currentSL); } 761 762 if (bundle.isActive() && (newSL > currentSL)) { 763 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 764 Debug.println("SLL: stopping bundle " + bundle.getBundleId()); } 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()); } 772 framework.resumeBundle(bundle); 773 } 774 } 775 if (Debug.DEBUG && Debug.DEBUG_STARTLEVEL) { 776 Debug.println("SLL: Bundle Startlevel set to " + newSL); } 778 } 779 } 780 781 790 public synchronized Object getService(Bundle owner, ServiceRegistration registration) { 791 if (implementation == null) 792 implementation = new StartLevelImpl(framework.systemBundle, framework); 793 return implementation; 794 } 795 796 803 public void ungetService(Bundle owner, ServiceRegistration registration, Object service) { 804 } 806 807 public boolean isSettingStartLevel() { 808 return settingStartLevel; 809 } 810 } 811 | Popular Tags |