--- a/core.netigso/arch.xml Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/arch.xml Thu Sep 08 10:23:15 2011 +0200 @@ -620,7 +620,12 @@ -->

- XXX no answer for exec-property + + One can influence the initial OSGi framework start level by rebranding + the FRAMEWORK_START_LEVEL key in org/netbeans/core/netigso/Bundle.properties. + By default the key is empty, which means no change to default OSGi start level of 1. +

--- a/core.netigso/manifest.mf Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/manifest.mf Thu Sep 08 10:23:15 2011 +0200 @@ -2,7 +2,7 @@ OpenIDE-Module: org.netbeans.core.netigso OpenIDE-Module-Localizing-Bundle: org/netbeans/core/netigso/Bundle.properties OpenIDE-Module-Provides: org.netbeans.NetigsoFramework -OpenIDE-Module-Specification-Version: 1.10 +OpenIDE-Module-Specification-Version: 1.11 OpenIDE-Module-Needs: org.osgi.framework.launch.FrameworkFactory AutoUpdate-Essential-Module: true --- a/core.netigso/nbproject/project.xml Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/nbproject/project.xml Thu Sep 08 10:23:15 2011 +0200 @@ -55,7 +55,7 @@ 1 - 2.37 + 2.43 --- a/core.netigso/src/org/netbeans/core/netigso/Bundle.properties Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/src/org/netbeans/core/netigso/Bundle.properties Thu Sep 08 10:23:15 2011 +0200 @@ -40,3 +40,4 @@ # Version 2 license, then the option applies only if the new code is # made subject to such option by the copyright holder. OpenIDE-Module-Name=NetBeans OSGi Integration +FRAMEWORK_START_LEVEL= --- a/core.netigso/src/org/netbeans/core/netigso/Netigso.java Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/src/org/netbeans/core/netigso/Netigso.java Thu Sep 08 10:23:15 2011 +0200 @@ -69,6 +69,7 @@ import org.openide.modules.ModuleInfo; import org.openide.modules.Places; import org.openide.util.Lookup; +import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; import org.osgi.framework.Bundle; @@ -82,6 +83,7 @@ import org.osgi.framework.launch.FrameworkFactory; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.service.packageadmin.RequiredBundle; +import org.osgi.service.startlevel.StartLevel; /** * @@ -162,6 +164,10 @@ @Override protected void start() { try { + String startLevel = NbBundle.getMessage(Netigso.class, "FRAMEWORK_START_LEVEL"); + if (startLevel.length() > 0) { + setFrameworkStartLevel(framework.getBundleContext(), Integer.parseInt(startLevel)); + } framework.start(); } catch (BundleException ex) { LOG.log(Level.WARNING, "Cannot start Container" + framework, ex); @@ -383,6 +389,10 @@ } LOG.log(Level.FINE, "Installing bundle {0}", loc); b = bc.installBundle(loc); + int startLevel = m.getStartLevel(); + if (startLevel > 0) { + setBundleStartLevel(bc, b, startLevel); + } } } else { InputStream is = fakeBundle(m); @@ -403,6 +413,39 @@ throw new IOException(ex); } } + + private void setFrameworkStartLevel(BundleContext bc, int startLevel) { + ServiceReference sr = bc.getServiceReference("org.osgi.service.startlevel.StartLevel"); // NOI18N + StartLevel level = null; + if (sr != null) { + level = (StartLevel) bc.getService(sr); + if (level != null) { + level.setStartLevel(startLevel); + return; + } + } + LOG.log( + Level.WARNING, + "Cannot set framewok startLevel to {1} reference: {2} level {3}", + new Object[]{null, startLevel, sr, level} + ); + } + private void setBundleStartLevel(BundleContext bc, Bundle b, int startLevel) { + ServiceReference sr = bc.getServiceReference("org.osgi.service.startlevel.StartLevel"); // NOI18N + StartLevel level = null; + if (sr != null) { + level = (StartLevel) bc.getService(sr); + if (level != null) { + level.setBundleStartLevel(b, startLevel); + return; + } + } + LOG.log( + Level.WARNING, + "Cannot set startLevel for {0} to {1} reference: {2} level {3}", + new Object[]{b.getSymbolicName(), startLevel, sr, level} + ); + } private static String threeDotsWithMajor(String version, String withMajor) { int indx = withMajor.indexOf('/'); --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 62a50e6c46aa Thu Sep 08 10:23:15 2011 +0200 @@ -0,0 +1,41 @@ +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2011 Oracle and/or its affiliates. All rights reserved. +# +# Oracle and Java are registered trademarks of Oracle and/or its affiliates. +# Other names may be trademarks of their respective owners. +# +# The contents of this file are subject to the terms of either the GNU +# General Public License Version 2 only ("GPL") or the Common +# Development and Distribution License("CDDL") (collectively, the +# "License"). You may not use this file except in compliance with the +# License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the +# specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header +# Notice in each file and include the License file at +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the GPL Version 2 section of the License file that +# accompanied this code. If applicable, add the following below the +# License Header, with the fields enclosed by brackets [] replaced by +# your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# If you wish your version of this file to be governed by only the CDDL +# or only the GPL Version 2, indicate your decision by adding +# "[Contributor] elects to include this software in this distribution +# under the [CDDL or GPL Version 2] license." If you do not indicate a +# single choice of license, a recipient has the option to distribute +# your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. +# However, if you add GPL Version 2 code and therefore, elected the GPL +# Version 2 license, then the option applies only if the new code is +# made subject to such option by the copyright holder. +# +# Contributor(s): +# +# Portions Copyrighted 2011 Sun Microsystems, Inc. + +FRAMEWORK_START_LEVEL=20 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 62a50e6c46aa Thu Sep 08 10:23:15 2011 +0200 @@ -0,0 +1,111 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.core.netigso; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import org.netbeans.Module; +import org.netbeans.ModuleManager; +import org.netbeans.SetupHid; +import org.netbeans.core.startup.Main; +import org.netbeans.core.startup.ModuleSystem; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.service.startlevel.StartLevel; + +/** + * Do we correctly call the BundleActivators? + * + * @author Jaroslav Tulach + */ +public class NetigsoDefaultStartLevelTest extends SetupHid { + private static Module m1; + private static ModuleManager mgr; + private int cnt; + private File simpleModule; + + public NetigsoDefaultStartLevelTest(String name) { + super(name); + } + + protected @Override void setUp() throws Exception { + Locale.setDefault(new Locale("te", "ST")); + clearWorkDir(); + File ud = new File(getWorkDir(), "ud"); + ud.mkdirs(); + System.setProperty("netbeans.user", ud.getPath()); + + data = new File(getDataDir(), "jars"); + jars = new File(getWorkDir(), "space in path"); + jars.mkdirs(); + simpleModule = createTestJAR("activate", null); + } + + public void testActivation() throws Exception { + ModuleSystem ms = Main.getModuleSystem(); + mgr = ms.getManager(); + mgr.mutexPrivileged().enterWriteAccess(); + try { + m1 = mgr.createBundle(simpleModule, null, false, false, false, 10); + mgr.enable(m1); + + Class main = m1.getClassLoader().loadClass("org.activate.Main"); + Object s = main.getField("start").get(null); + s = main.getField("start").get(null); + assertNotNull("Bundle started as default start level is 20, its context provided", s); + + mgr.disable(m1); + + Object e = main.getField("stop").get(null); + assertNotNull("Bundle stopped, its context provided", e); + } finally { + mgr.mutexPrivileged().exitWriteAccess(); + } + } + private File createTestJAR(String name, String srcdir, File... classpath) throws IOException { + return createTestJAR(data, jars, name, srcdir, classpath); + } +} --- a/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoServicesTest.java Thu Sep 08 08:07:19 2011 +0200 +++ a/core.netigso/test/unit/src/org/netbeans/core/netigso/NetigsoServicesTest.java Thu Sep 08 10:23:15 2011 +0200 @@ -44,7 +44,6 @@ package org.netbeans.core.netigso; -import org.netbeans.core.startup.*; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; @@ -62,6 +61,8 @@ import org.netbeans.ModuleManager; import org.netbeans.NetigsoFramework; import org.netbeans.SetupHid; +import org.netbeans.core.startup.Main; +import org.netbeans.core.startup.ModuleSystem; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.Lookup; @@ -70,6 +71,7 @@ import org.openide.util.LookupListener; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.launch.Framework; /** * How does OSGi integration deals with layer registration? @@ -79,6 +81,7 @@ public class NetigsoServicesTest extends SetupHid implements LookupListener { private static Module m1; private static ModuleManager mgr; + private int cnt; public NetigsoServicesTest(String name) { @@ -166,10 +169,7 @@ static Bundle findBundle(String bsn) throws Exception { - Object o = Lookup.getDefault().lookup(NetigsoFramework.class); - assertEquals("The right class", Netigso.class, o.getClass()); - Netigso f = (Netigso)o; - Bundle[] arr = f.getFramework().getBundleContext().getBundles(); + Bundle[] arr = findFramework().getBundleContext().getBundles(); for (Bundle b : arr) { if (bsn.equals(b.getSymbolicName())) { return b; @@ -202,7 +202,16 @@ return f; } + @Override public void resultChanged(LookupEvent ev) { cnt++; } + + static Framework findFramework() { + Object o = Lookup.getDefault().lookup(NetigsoFramework.class); + assertEquals("The right class", Netigso.class, o.getClass()); + Netigso f = (Netigso)o; + final Framework frame = f.getFramework(); + return frame; + } } --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 62a50e6c46aa Thu Sep 08 10:23:15 2011 +0200 @@ -0,0 +1,147 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.core.netigso; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import org.netbeans.Module; +import org.netbeans.ModuleManager; +import org.netbeans.SetupHid; +import org.netbeans.core.startup.Main; +import org.netbeans.core.startup.ModuleSystem; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkEvent; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.service.startlevel.StartLevel; + +/** + * Do we correctly use start levels? + * + * @author Jaroslav Tulach + */ +public class NetigsoStartLevelTest extends SetupHid +implements FrameworkListener { + private static Module m1; + private static ModuleManager mgr; + private int cnt; + private File simpleModule; + private boolean levelChanged; + + public NetigsoStartLevelTest(String name) { + super(name); + } + + protected @Override void setUp() throws Exception { + Locale.setDefault(Locale.US); + clearWorkDir(); + File ud = new File(getWorkDir(), "ud"); + ud.mkdirs(); + System.setProperty("netbeans.user", ud.getPath()); + + data = new File(getDataDir(), "jars"); + jars = new File(getWorkDir(), "space in path"); + jars.mkdirs(); + simpleModule = createTestJAR("activate", null); + } + + public void testActivation() throws Exception { + ModuleSystem ms = Main.getModuleSystem(); + mgr = ms.getManager(); + mgr.mutexPrivileged().enterWriteAccess(); + try { + m1 = mgr.createBundle(simpleModule, null, false, false, false, 10); + mgr.enable(m1); + } finally { + mgr.mutexPrivileged().exitWriteAccess(); + } + + Class main = m1.getClassLoader().loadClass("org.activate.Main"); + Object s = main.getField("start").get(null); + assertNull("Not started yet", s); + + Framework f = NetigsoServicesTest.findFramework(); + final BundleContext fc = f.getBundleContext(); + fc.addFrameworkListener(this); + ServiceReference sr = fc.getServiceReference(StartLevel.class.getName()); + assertNotNull("Start level service found", sr); + StartLevel level = (StartLevel) fc.getService(sr); + assertNotNull("Start level found", level); + level.setStartLevel(10); + waitLevelChanged(); + + s = main.getField("start").get(null); + assertNotNull("Bundle started, its context provided", s); + + mgr.mutexPrivileged().enterWriteAccess(); + try { + mgr.disable(m1); + + Object e = main.getField("stop").get(null); + assertNotNull("Bundle stopped, its context provided", e); + } finally { + mgr.mutexPrivileged().exitWriteAccess(); + } + } + private File createTestJAR(String name, String srcdir, File... classpath) throws IOException { + return createTestJAR(data, jars, name, srcdir, classpath); + } + + @Override + public synchronized void frameworkEvent(FrameworkEvent fe) { + if (fe.getType() == FrameworkEvent.STARTLEVEL_CHANGED) { + levelChanged = true; + notifyAll(); + } + } + + private synchronized void waitLevelChanged() throws InterruptedException { + while (!levelChanged) { + wait(); + } + } +} --- a/core.startup/src/org/netbeans/core/startup/ModuleList.java Thu Sep 08 08:07:19 2011 +0200 +++ a/core.startup/src/org/netbeans/core/startup/ModuleList.java Thu Sep 08 10:23:15 2011 +0200 @@ -93,7 +93,6 @@ import org.openide.modules.Dependency; import org.openide.modules.InstalledFileLocator; import org.openide.modules.SpecificationVersion; -import org.openide.util.Exceptions; import org.openide.util.Parameters; import org.openide.util.RequestProcessor; import org.openide.util.Utilities; @@ -164,7 +163,7 @@ * enable as needed. All discovered modules are returned. * Write mutex only. */ - public Set readInitial() { + public Set readInitial() { ev.log(Events.START_READ); final Set read = new HashSet(); try { @@ -175,6 +174,25 @@ return read; } + final Module createModule( + File jarFile, ModuleHistory hist, boolean reloadable, boolean autoload, + boolean eager, Integer startLevel + ) throws IOException { + Module m; + try { + if (startLevel != null) { + m = mgr.createBundle(jarFile, hist, reloadable, autoload, eager, startLevel); + } else { + m = mgr.create(jarFile, hist, reloadable, autoload, eager); + } + } catch (DuplicateException dupe) { + // XXX should this be tolerated somehow? In case the original is + // in fact scheduled for deletion anyway? + throw new IOException(dupe); + } + return m; + } + /** * Try to find a module JAR by an XML-supplied name. * @param jar the JAR name (relative to an install dir, or a full path) @@ -427,6 +445,9 @@ ) { return Boolean.valueOf(v); } else { + if (k == "startlevel") { // NOI18N + return Integer.valueOf(v); + } // Other properties are of type String. // Intern the smaller ones which are likely to be repeated somewhere. if (v.length() < 100) v = v.intern(); @@ -657,9 +678,11 @@ Stamps.getModulesJARs().scheduleSave(this, "all-modules.dat", false); } + @Override public void cacheReady() { } + @Override public void flushCaches(DataOutputStream os) throws IOException { ObjectOutputStream oss = new ObjectOutputStream(os); for (Module m : mgr.getModules()) { @@ -957,6 +980,9 @@ p.put("autoload", m.isAutoload()); // NOI18N p.put("eager", m.isEager()); // NOI18N p.put("reloadable", m.isReloadable()); // NOI18N + if (m.getStartLevel() > 0) { + p.put("startlevel", m.getStartLevel()); // NOI18N + } if (m.getHistory() instanceof ModuleHistory) { ModuleHistory hist = (ModuleHistory) m.getHistory(); p.put("jar", hist.getJar()); // NOI18N @@ -1087,7 +1113,7 @@ fileDeleted0(ev.getName(), ev.getExt()/*, ev.getTime()*/); fileCreated0(fo.getName(), fo.getExt()/*, ev.getTime()*/); } - + private void fileCreated0(String name, String ext/*, long time*/) { if ("xml".equals(ext)) { // NOI18N String codenamebase = name.replace('-', '.'); @@ -1340,14 +1366,9 @@ boolean autoload = (autoloadB != null ? autoloadB.booleanValue() : false); Boolean eagerB = (Boolean)props.get("eager"); // NOI18N boolean eager = (eagerB != null ? eagerB.booleanValue() : false); - Module m; - try { - m = mgr.create(jarFile, new ModuleHistory(jar, "created from " + xmlfile), reloadable, autoload, eager); - } catch (DuplicateException dupe) { - // XXX should this be tolerated somehow? In case the original is - // in fact scheduled for deletion anyway? - throw (IOException) new IOException(dupe.toString()).initCause(dupe); - } + Integer startLevel = (Integer)props.get("startlevel"); // NOI18N + ModuleHistory hist = new ModuleHistory(jar, "created from " + xmlfile); + Module m = createModule(jarFile, hist, reloadable, autoload, eager, startLevel); m.addPropertyChangeListener(this); // Mark the status as disabled for the moment, so in step 3 it will be turned on // if in dirtyprops it was marked enabled. @@ -1641,7 +1662,8 @@ Boolean eagerB = (Boolean) props.get("eager"); // NOI18N boolean eager = eagerB != null ? eagerB.booleanValue() : false; NbInstaller.register(name, props.get("deps")); // NOI18N - Module m = mgr.create(jarFile, history, reloadable, autoload, eager); + Integer startLevel = (Integer)props.get("startlevel"); // NOI18N + Module m = createModule(jarFile, history, reloadable, autoload, eager, startLevel); NbInstaller.register(null, null); read.add(m); DiskStatus status = new DiskStatus(); --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 62a50e6c46aa Thu Sep 08 10:23:15 2011 +0200 @@ -0,0 +1,10 @@ + + + + true + false + modules/com-jcraft-jsch.jar + false + 4 + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 62a50e6c46aa Thu Sep 08 10:23:15 2011 +0200 @@ -0,0 +1,148 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.core.startup; + +import org.netbeans.SetupHid; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.netbeans.*; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.LocalFileSystem; +import org.openide.modules.InstalledFileLocator; +import org.openide.modules.api.PlacesTestUtils; +import org.openide.util.test.MockLookup; + +/** Do we recognize startlevel? + * @author Jaroslav Tulach + */ +public class ModuleListStartLevelTest extends SetupHid { + + private static final String PREFIX = "wherever/"; + private LocalFileSystem fs; + private MockEvents ev; + private File ud; + + private final class IFL extends InstalledFileLocator { + public IFL() {} + public File locate(String relativePath, String codeNameBase, boolean localized) { + if (relativePath.startsWith(PREFIX)) { + File f = new File(jars, relativePath.substring(PREFIX.length()).replace('/', File.separatorChar)); + if (f.exists()) { + return f; + } + } + return null; + } + } + + public ModuleListStartLevelTest(String name) { + super(name); + } + + private ModuleManager mgr; + private FileObject modulesfolder; + @Override + protected void setUp() throws Exception { + super.setUp(); + + MockLookup.setInstances(new IFL()); + + ud = new File(getWorkDir(), "ud"); + PlacesTestUtils.setUserDirectory(ud); + + MockModuleInstaller installer = new MockModuleInstaller(); + ev = new MockEvents(); + mgr = new ModuleManager(installer, ev); + File dir = new File(ud, "config"); + File modulesdir = new File(dir, "Modules"); + if (! modulesdir.mkdirs()) throw new IOException("Making " + modulesdir); + fs = new LocalFileSystem(); + fs.setRootDirectory(dir); + modulesfolder = fs.findResource("Modules"); + assertNotNull(modulesfolder); + } + + public void testParsesStartLevel() throws Exception { + FileObject fo = modulesfolder.createData("com-jcraft-jsch.xml"); + File mod = new File(new File(ud, "modules"), "com-jcraft-jsch.jar"); + final HashMap man = new HashMap(); + man.put("Bundle-SymbolicName", "com.jcraft.jsch"); + createJar(mod, new HashMap(), man); + + InputStream is = ModuleListStartLevelTest.class.getResourceAsStream("ModuleList-com-jscraft-jsch.xml"); + assertNotNull("Module definition found", is); + final OutputStream os = fo.getOutputStream(); + FileUtil.copy(is, os); + os.close(); + is.close(); + + ModuleList list = new ModuleList(mgr, modulesfolder, ev); + Set set = list.readInitial(); + + assertEquals("One module: " + set, 1, set.size()); + Module m = set.iterator().next(); + + assertEquals("Start level has been specified to four", 4, m.getStartLevel()); + + Stamps.getModulesJARs().flush(0); + Stamps.getModulesJARs().shutdown(); + + Map> cache = list.readCache(); + assertNotNull("Cache read", cache); + Map module = cache.get("com.jcraft.jsch"); + assertNotNull("Module info found", module); + Object level = module.get("startlevel"); + assertEquals("Start level is remembered", Integer.valueOf(4), level); + } + + +} --- a/o.n.bootstrap/manifest.mf Thu Sep 08 08:07:19 2011 +0200 +++ a/o.n.bootstrap/manifest.mf Thu Sep 08 10:23:15 2011 +0200 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.bootstrap/1 -OpenIDE-Module-Specification-Version: 2.41 +OpenIDE-Module-Specification-Version: 2.43 OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties OpenIDE-Module-Recommends: org.netbeans.NetigsoFramework --- a/o.n.bootstrap/src/org/netbeans/Module.java Thu Sep 08 08:07:19 2011 +0200 +++ a/o.n.bootstrap/src/org/netbeans/Module.java Thu Sep 08 10:23:15 2011 +0200 @@ -609,6 +609,20 @@ public final Object getHistory() { return history; } + + /** Finds out if a module has been assigned with a specific start level. + * Start level is only useful for OSGi bundles. Otherwise it is always zero. + * + * @return zero, if no specific level is assigned, positive integer if so + * @since 2.43 + */ + public final int getStartLevel() { + return getStartLevelImpl(); + } + + int getStartLevelImpl() { + return 0; + } /** String representation for debugging. */ public @Override String toString() { --- a/o.n.bootstrap/src/org/netbeans/ModuleFactory.java Thu Sep 08 08:07:19 2011 +0200 +++ a/o.n.bootstrap/src/org/netbeans/ModuleFactory.java Thu Sep 08 10:23:15 2011 +0200 @@ -80,7 +80,7 @@ throw ex; } } - + /** * This method creates a "fixed" module. Fixed modules cannot be * realoaded, are always enabled and are typically present on the --- a/o.n.bootstrap/src/org/netbeans/ModuleManager.java Thu Sep 08 08:07:19 2011 +0200 +++ a/o.n.bootstrap/src/org/netbeans/ModuleManager.java Thu Sep 08 10:23:15 2011 +0200 @@ -598,6 +598,34 @@ subCreate(m); return m; } + + /** Create a module from a JAR representing an OSGi bundle + * and adds it to the managed set. + * Behavior is the same as {@link #create(java.io.File, java.lang.Object, boolean, boolean, boolean)} + * just adds additional start level info. + * + * @param startLevel an OSGi start level. Zero indicates, no changes to default level. + * @throws InvalidException if the JAR does not represent an OSGi bundle + * @since 2.43 + */ + public Module createBundle( + File jar, Object history, boolean reloadable, boolean autoload, + boolean eager, int startLevel + ) throws IOException, DuplicateException { + assertWritable(); + ev.log(Events.START_CREATE_REGULAR_MODULE, jar); + Module m = moduleFactory.create(jar.getAbsoluteFile(), + history, reloadable, autoload, eager, this, ev); + if (m instanceof NetigsoModule) { + NetigsoModule nm = (NetigsoModule)m; + nm.setStartLevel(startLevel); + } else { + throw new InvalidException("Expecting an OSGI bundle in " + jar); + } + ev.log(Events.FINISH_CREATE_REGULAR_MODULE, jar); + subCreate(m); + return m; + } /** Create a fixed module (e.g. from classpath). * Will initially be disabled. --- a/o.n.bootstrap/src/org/netbeans/NetigsoModule.java Thu Sep 08 08:07:19 2011 +0200 +++ a/o.n.bootstrap/src/org/netbeans/NetigsoModule.java Thu Sep 08 10:23:15 2011 +0200 @@ -63,8 +63,9 @@ final class NetigsoModule extends Module { static final Logger LOG = Logger.getLogger(NetigsoModule.class.getPackage().getName()); - private File jar; - private Manifest manifest; + private final File jar; + private final Manifest manifest; + private int startLevel; public NetigsoModule(Manifest mani, File jar, ModuleManager mgr, Events ev, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException { super(mgr, ev, history, reloadable, autoload, eager); @@ -224,6 +225,15 @@ return s.replaceFirst(";.*$", ""); } + @Override + final int getStartLevelImpl() { + return startLevel; + } + + final void setStartLevel(int startLevel) { + this.startLevel = startLevel; + } + private final class DelegateCL extends ProxyClassLoader implements Util.ModuleProvider { public DelegateCL() {