startlevelimpl.java
来自「OSGI这是一个中间件,与UPNP齐名,是用于移植到嵌入式平台之上」· Java 代码 · 共 390 行
JAVA
390 行
/* * Copyright (c) 2003, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */package org.knopflerfish.framework;import org.osgi.framework.*;import org.osgi.service.startlevel.*;import java.util.Vector;import java.io.File;/** * StartLevel service implemenetation. * */public class StartLevelImpl implements StartLevel, Runnable { Thread wc; long wcDelay = 2000; boolean bRun = false; Queue jobQueue = new Queue(100); final static int START_MIN = 0; final static int START_MAX = Integer.MAX_VALUE; final static String LEVEL_FILE = "currentlevel"; int currentLevel = 0; int initStartLevel = 1; int targetStartLevel = currentLevel; Framework framework; FileTree storage; // Set to true indicates startlevel compatability mode. // all bundles and current start level will be 1 boolean bCompat = false; public static final String SPEC_VERSION = "1.0"; public StartLevelImpl(Framework framework) { this.framework = framework; storage = Util.getFileStorage("startlevel"); setStartLevel(1); } void open() { if(Debug.startlevel) { Debug.println("startlevel: open"); } wc = new Thread(this, "startlevel job thread"); bRun = true; wc.start(); } /** * Load persistent state from storage and * set up all actions necessary to bump bundle * states. * * After this call, getStartLevel will have the correct value. * * <p> * Note that open() needs to be called for any work to * be done. * </p> */ void restoreState() { if(Debug.startlevel) { Debug.println("startlevel: restoreState"); } // Skip level load in mem storage since bundle levels // isn't saved anyway if(!Framework.bIsMemoryStorage) { try { String s = Util.getContent(new File(storage, LEVEL_FILE)); if(s != null) { int oldStartLevel = Integer.parseInt(s); if(oldStartLevel != -1) { setStartLevel(oldStartLevel); } } } catch (Exception ignored) { } } } void close() { if(Debug.startlevel) { Debug.println("*** closing startlevel service"); } bRun = false; if(wc != null) { try { wc.join(wcDelay * 2); } catch (Exception ignored) { } wc = null; } } public void run() { while(bRun) { try { Runnable job = (Runnable)jobQueue.removeWait((float)(wcDelay / 1000.0)); if(job != null) { job.run(); } } catch (Exception ignored) { ignored.printStackTrace(); } } } public int getStartLevel() { return currentLevel; } public void setStartLevel(final int startLevel) { if(startLevel <= 0) { throw new IllegalArgumentException("Initial start level must be > 0, is " + startLevel); } if(Debug.startlevel) { Debug.println("startlevel: setStartLevel " + startLevel); } jobQueue.insert(new Runnable() { public void run() { int sl = bCompat ? 1 : startLevel; targetStartLevel = sl; while(targetStartLevel > currentLevel) { increaseStartLevel(); } while(targetStartLevel < currentLevel) { decreaseStartLevel(); } // Skip level save in mem storage since bundle levels // won't be saved anyway if(!Framework.bIsMemoryStorage) { try { Util.putContent(new File(storage, LEVEL_FILE), Integer.toString(currentLevel)); } catch (Exception e) { e.printStackTrace(); } } notifyFramework(); } }); } Object lock = new Object(); void increaseStartLevel() { synchronized(lock) { currentLevel++; if(Debug.startlevel) { Debug.println("startlevel: increaseStartLevel currentLevel=" + currentLevel); } Vector set = new Vector(); BundleImpl[] bundles = framework.bundles.getBundles(); for(int i = 0; i < bundles.length; i++) { BundleImpl bs = bundles[i]; if(canStart(bs)) { if(bs.getStartLevel() == currentLevel) { if(bs.archive.isPersistent()) { set.addElement(bs); } } } else { } } Util.sort(set, BSComparator, false); for(int i = 0; i < set.size(); i++) { BundleImpl bs = (BundleImpl)set.elementAt(i); try { if(bs.archive.isPersistent()) { if(Debug.startlevel) { Debug.println("startlevel: start " + bs); } bs.start(); } } catch (Exception e) { framework.listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, bs, e)); } } } } void decreaseStartLevel() { synchronized(lock) { currentLevel--; Vector set = new Vector(); BundleImpl[] bundles = framework.bundles.getBundles(); for(int i = 0; i < bundles.length; i++) { BundleImpl bs = bundles[i]; if(bs.getState() == Bundle.ACTIVE) { if(bs.getStartLevel() == currentLevel + 1) { set.addElement(bs); } } } Util.sort(set, BSComparator, true); for(int i = 0; i < set.size(); i++) { BundleImpl bs = (BundleImpl)set.elementAt(i); try { bs.stop(); bs.bDelayedStart = true; bs.setPersistent(true); } catch (Exception e) { framework.listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, bs, e)); } } } } boolean canStart(BundleImpl b) { return b.getState() != Bundle.UNINSTALLED; // b.getState() != Bundle.ACTIVE; } Util.Comparator BSComparator = new Util.Comparator() { public int compare(Object o1, Object o2) { BundleImpl b1 = (BundleImpl)o1; BundleImpl b2 = (BundleImpl)o2; return (int)(b1.getBundleId() - b2.getBundleId()); } }; public int getBundleStartLevel(Bundle bundle) { if(bundle.getBundleId() == 0) { return 0; } BundleImpl bs = (BundleImpl)bundle; return bs.getStartLevel(); } public void setBundleStartLevel(Bundle bundle, final int startLevel) { if(startLevel <= 0) { throw new IllegalArgumentException("Initial start level must be > 0, is " + startLevel); } if(bundle.getBundleId() == 0) { throw new IllegalArgumentException("System bundle start level cannot be changed"); } final BundleImpl bs = (BundleImpl)bundle; if(bs.getState() == Bundle.UNINSTALLED) { throw new IllegalArgumentException("uninstalled bundle start level cannot be changed"); } jobQueue.insert(new Runnable() { public void run() { int sl = bCompat ? 1 : startLevel; bs.setStartLevel(sl); syncStartLevel(bs); notifyFramework(); } }); } void syncStartLevel(BundleImpl bs) { synchronized(lock) { if(bs.getStartLevel() <= currentLevel) { if(canStart(bs)) { if(bs.archive.isPersistent() || (bs.getState() == Bundle.RESOLVED)) { try { bs.start(); } catch (Exception e) { framework.listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, bs, e)); } } else { bs.bDelayedStart = true; } } } else if(bs.getStartLevel() > currentLevel) { if(bs.getState() == Bundle.ACTIVE) { try { bs.stop(); bs.bDelayedStart = true; // Reset this since stop sets to false } catch (Exception e) { framework.listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, bs, e)); } } } } } public int getInitialBundleStartLevel() { return initStartLevel; } public void setInitialBundleStartLevel(int startLevel) { if(startLevel <= 0) { throw new IllegalArgumentException("Initial start level must be > 0, is " + startLevel); } initStartLevel = bCompat ? 1 : startLevel; } public boolean isBundlePersistentlyStarted(Bundle bundle) { return ((BundleImpl)bundle).isPersistent(); } private void notifyFramework() { framework.listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, framework.systemBundle, null)); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?