diff -r ba49237cb632 core.netigso/apichanges.xml --- a/core.netigso/apichanges.xml Tue Jan 03 13:49:57 2012 +0100 +++ b/core.netigso/apichanges.xml Tue Jan 03 13:50:20 2012 +0100 @@ -52,6 +52,19 @@ OSGi Related Behavior + + + Is archive active? + + + + + + One can check whether the access to resource archive is safe or not + by calling isActive() method. + + + Friend API is no longer accessible diff -r ba49237cb632 core.netigso/manifest.mf --- a/core.netigso/manifest.mf Tue Jan 03 13:49:57 2012 +0100 +++ b/core.netigso/manifest.mf Tue Jan 03 13:50:20 2012 +0100 @@ -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.13 +OpenIDE-Module-Specification-Version: 1.14 OpenIDE-Module-Needs: org.osgi.framework.launch.FrameworkFactory AutoUpdate-Essential-Module: true diff -r ba49237cb632 core.netigso/src/org/netbeans/core/netigso/Netigso.java --- a/core.netigso/src/org/netbeans/core/netigso/Netigso.java Tue Jan 03 13:49:57 2012 +0100 +++ b/core.netigso/src/org/netbeans/core/netigso/Netigso.java Tue Jan 03 13:50:20 2012 +0100 @@ -56,6 +56,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.logging.Level; @@ -95,7 +96,7 @@ }) public final class Netigso extends NetigsoFramework implements Stamps.Updater { static final Logger LOG = Logger.getLogger(Netigso.class.getName()); - private static final ThreadLocal SELF_QUERY = new ThreadLocal(); + private static final AtomicBoolean SELF_QUERY = new AtomicBoolean(); private static final String[] EMPTY = {}; private Framework framework; @@ -592,12 +593,16 @@ } public byte[] fromArchive(long bundleId, String resource, ArchiveResources ar) throws IOException { - if (Boolean.TRUE.equals(SELF_QUERY.get())) { + if (SELF_QUERY.get()) { return ar.resource(resource); } return fromArchive(ar, resource); } + public boolean isArchiveActive() { + return !SELF_QUERY.get(); + } + private static String toURI(final File file) { class VFile extends File { @@ -617,4 +622,5 @@ } return new VFile().toURI().toString(); } + } diff -r ba49237cb632 core.netigso/src/org/netbeans/core/netigso/spi/NetigsoArchive.java --- a/core.netigso/src/org/netbeans/core/netigso/spi/NetigsoArchive.java Tue Jan 03 13:49:57 2012 +0100 +++ b/core.netigso/src/org/netbeans/core/netigso/spi/NetigsoArchive.java Tue Jan 03 13:50:20 2012 +0100 @@ -100,6 +100,18 @@ public byte[] fromArchive(String resource) throws IOException { return netigso.fromArchive(bundleId, resource, content); } + + /** Checks whether the archive should be used or not. During first + * start the Netigso system iterates through all bundle entries to + * record so-called covered packages. During this iteration + * one should not try to use the archive - this method returns false. + * + * @return true, if it is safe to use the {@link #fromArchive(java.lang.String)} method + * @since 1.14 + */ + public boolean isActive() { + return netigso.isArchiveActive(); + } static { NetigsoArchiveFactory f = new NetigsoArchiveFactory() { diff -r ba49237cb632 netbinox/nbproject/project.xml --- a/netbinox/nbproject/project.xml Tue Jan 03 13:49:57 2012 +0100 +++ b/netbinox/nbproject/project.xml Tue Jan 03 13:50:20 2012 +0100 @@ -10,7 +10,7 @@ - 1.4.2 + 1.14 diff -r ba49237cb632 netbinox/src/org/netbeans/modules/netbinox/JarBundleFile.java --- a/netbinox/src/org/netbeans/modules/netbinox/JarBundleFile.java Tue Jan 03 13:49:57 2012 +0100 +++ b/netbinox/src/org/netbeans/modules/netbinox/JarBundleFile.java Tue Jan 03 13:50:20 2012 +0100 @@ -45,7 +45,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; import java.util.Enumeration; @@ -182,6 +181,7 @@ return d == null ? null : d.getFile(file, bln); } + @Override public byte[] resource(String name) throws IOException { BundleEntry u = findEntry("resource", name); if (u == null) { @@ -212,6 +212,7 @@ } finally { is.close(); } + NetbinoxFactory.LOG.log(Level.FINE, "Loaded {1} bytes for {0}", new Object[] { name, arr.length }); // NOI18N return arr; } @@ -238,6 +239,10 @@ @Override public BundleEntry getEntry(final String name) { + if (!archive.isActive()) { + return delegate("inactive", name).getEntry(name); // NOI18N + } + final byte[] arr = getCachedEntry(name); if (arr == null && !name.equals("/")) { return null; diff -r ba49237cb632 netbinox/test/unit/src/org/netbeans/modules/netbinox/LoadedBytesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netbinox/test/unit/src/org/netbeans/modules/netbinox/LoadedBytesTest.java Tue Jan 03 13:50:20 2012 +0100 @@ -0,0 +1,141 @@ +/* + * 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 Oracle + */ +package org.netbeans.modules.netbinox; + +import org.netbeans.core.startup.*; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import org.netbeans.Module; +import org.netbeans.ModuleManager; +import org.netbeans.SetupHid; + +/** + * Verify content is not loaded when enumerating covered packages. + * + * @author Jaroslav Tulach + */ +public class LoadedBytesTest extends SetupHid { + private static Module m1; + private static ModuleManager mgr; + int counter; + boolean used; + private File file; + + + public LoadedBytesTest(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(); + File simpleModule = createTestJAR("simple-module", null); + + String mf = "Manifest-Version: 1.0\n" + + "Bundle-SymbolicName: org.foo\n" + + "Bundle-Version: 1.2\n\n"; + + file = NetigsoHid.changeManifest(getWorkDir(), simpleModule, mf); + NetbinoxFactory.LOG.addHandler(new CountingHandler()); + } + + public void testEnumeratingEntriesDoesNotLoadContent() throws Exception { + ModuleSystem ms = Main.getModuleSystem(); + mgr = ms.getManager(); + mgr.mutexPrivileged().enterWriteAccess(); + try { + m1 = mgr.create(file, null, false, false, false); + mgr.enable(m1); + assertTrue("Is enabled: ", m1.isEnabled()); + + assertEquals("No bytes loaded", 0, counter); + + Class main = m1.getClassLoader().loadClass("org.foo.Something"); + assertNotNull("Class can be loaded", main); + mgr.disable(m1); + } finally { + mgr.mutexPrivileged().exitWriteAccess(); + } + assertTrue("The CountingHandler was active", used); + } + private File createTestJAR(String name, String srcdir, File... classpath) throws IOException { + return createTestJAR(data, jars, name, srcdir, classpath); + } + private class CountingHandler extends Handler { + public CountingHandler() { + setLevel(Level.ALL); + } + + @Override + public void publish(LogRecord record) { + if (record.getMessage().startsWith("opening") && record.getMessage().contains("because")) { + used = true; + } + if (record.getMessage().startsWith("Loaded") && record.getMessage().contains("bytes")) { + String name = (String) record.getParameters()[0]; + if (name.endsWith(".class")) { + counter += (Integer)record.getParameters()[1]; + } + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + } + +}