diff -r 893c55cd168d core.startup/nbproject/project.properties --- a/core.startup/nbproject/project.properties Wed Aug 05 06:31:25 2009 +0400 +++ b/core.startup/nbproject/project.properties Wed Aug 05 18:19:21 2009 +0200 @@ -37,7 +37,7 @@ # Version 2 license, then the option applies only if the new code is # made subject to such option by the copyright holder. -spec.version.base=1.16.0 +spec.version.base=1.17.0 javadoc.arch=${basedir}/arch.xml javac.compilerargs=-Xlint -Xlint:-serial javac.source=1.5 diff -r 893c55cd168d core.startup/nbproject/project.xml --- a/core.startup/nbproject/project.xml Wed Aug 05 06:31:25 2009 +0400 +++ b/core.startup/nbproject/project.xml Wed Aug 05 18:19:21 2009 +0200 @@ -60,7 +60,7 @@ - 7.19 + 7.23 diff -r 893c55cd168d core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java --- a/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java Wed Aug 05 06:31:25 2009 +0400 +++ b/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java Wed Aug 05 18:19:21 2009 +0200 @@ -88,7 +88,7 @@ /** other layers */ private final FileSystem[] otherLayers; /** addLookup */ - private final boolean addLookup; + private final boolean addLookupBefore; /** Create layered filesystem based on a supplied writable layer. * @param userDir is this layer for modules from userdir or not? @@ -116,7 +116,7 @@ this.writableLayer = writableLayer; this.otherLayers = otherLayers; this.cacheLayer = cacheLayer; - this.addLookup = addLookup; + this.addLookupBefore = addLookup; // Wish to permit e.g. a user-installed module to mask files from a // root-installed module, so propagate masks up this high. @@ -126,19 +126,20 @@ urls = null; - if (addLookup) { - result.addLookupListener(this); - result.allItems(); - } - + result.addLookupListener(this); + result.allItems(); } - private static FileSystem[] appendLayers(FileSystem fs1, boolean addLookup, FileSystem[] fs2s, FileSystem fs3, boolean addClasspathLayers) { + private static FileSystem[] appendLayers(FileSystem fs1, boolean addLookupBefore, FileSystem[] fs2s, FileSystem fs3, boolean addClasspathLayers) { List l = new ArrayList(fs2s.length + 2); l.add(fs1); - if (addLookup) { - Collection fromLookup = result.allInstances(); - l.addAll(fromLookup); + if (addLookupBefore) { + for (FileSystem f : result.allInstances()) { + if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N + continue; + } + l.add(f); + } } l.addAll(Arrays.asList(fs2s)); l.add(fs3); @@ -175,6 +176,13 @@ err.log(Level.WARNING, "Setting layer URLs: " + layerUrls, x); } } + if (!addLookupBefore) { + for (FileSystem f : result.allInstances()) { + if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N + l.add(f); + } + } + } return l.toArray(new FileSystem[l.size()]); } @@ -246,7 +254,7 @@ } cacheLayer = manager.store(cacheLayer, urls); err.log(Level.FINEST, "changing delegates"); - setDelegates(appendLayers(writableLayer, addLookup, otherLayers, cacheLayer, false)); + setDelegates(appendLayers(writableLayer, addLookupBefore, otherLayers, cacheLayer, false)); err.log(Level.FINEST, "delegates changed"); } @@ -278,7 +286,7 @@ /** Refresh layers */ public void resultChanged(LookupEvent ev) { - setDelegates(appendLayers(writableLayer, addLookup, otherLayers, cacheLayer, false)); + setDelegates(appendLayers(writableLayer, addLookupBefore, otherLayers, cacheLayer, false)); } private static void setStatusText (String msg) { diff -r 893c55cd168d core.startup/test/unit/src/org/netbeans/core/startup/layers/BinaryCacheManagerTest.java --- a/core.startup/test/unit/src/org/netbeans/core/startup/layers/BinaryCacheManagerTest.java Wed Aug 05 06:31:25 2009 +0400 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/BinaryCacheManagerTest.java Wed Aug 05 18:19:21 2009 +0200 @@ -126,6 +126,12 @@ InputSource is = m.resolveEntity(pubid, sysid); assertNotNull("DTD Filesystem 1.2 not resolved.", is); } + public void testJustAttributes() throws SAXException, IOException { + BinaryCacheManager m = new BinaryCacheManager(); + List urls = new ArrayList(Arrays.asList(BinaryCacheManagerTest.class.getResource("data/attribsonly.xml"))); + FileSystem fs = store(m, urls); + assertEquals(Boolean.TRUE, fs.getRoot().getAttribute("myAttr")); + } public void testFastReplacement() throws Exception { clearWorkDir(); diff -r 893c55cd168d core.startup/test/unit/src/org/netbeans/core/startup/layers/DynamicSFSFallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/DynamicSFSFallbackTest.java Wed Aug 05 18:19:21 2009 +0200 @@ -0,0 +1,157 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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.layers; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Iterator; +import junit.framework.Test; +import org.netbeans.core.startup.MainLookup; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.LocalFileSystem; +import org.openide.util.Lookup; +import org.openide.util.lookup.InstanceContent; + +/** Test layering of filesystems installed via lookup. + * + * @author Jaroslav Tulach + */ +public class DynamicSFSFallbackTest extends NbTestCase +implements InstanceContent.Convertor { + FileSystem fs1; + FileSystem fs2; + + public DynamicSFSFallbackTest(String testName) { + super(testName); + } + + public static Test suite() { + return NbModuleSuite.create( + NbModuleSuite.emptyConfiguration(). + addTest(DynamicSFSFallbackTest.class). + clusters("org-netbeans-core-ui.*") + ); + } + + @Override + protected void setUp() throws Exception { + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + MainLookup.unregister(fs1, this); + MainLookup.unregister(fs2, this); + } + + + + public void testDynamicSystemsCanAlsoBeBehindLayers() throws Exception { + FileObject global = FileUtil.getConfigFile("Toolbars/Standard.xml"); + assertNotNull("File Object installed: " + global, global); + if (global.asText().indexOf(" it = Lookup.getDefault().lookupAll(FileSystem.class).iterator(); + assertTrue("At least One", it.hasNext()); + assertEquals("first is fs1", fs1, it.next()); + assertTrue("At least two ", it.hasNext()); + assertEquals("first is fs2", fs2, it.next()); + + if (global.asText().indexOf(" type(FileSystem obj) { + return obj.getClass(); + } + + public String id(FileSystem obj) { + return obj.getDisplayName(); + } + + public String displayName(FileSystem obj) { + return obj.getDisplayName(); + } +} diff -r 893c55cd168d core.startup/test/unit/src/org/netbeans/core/startup/layers/data/attribsonly.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/data/attribsonly.xml Wed Aug 05 18:19:21 2009 +0200 @@ -0,0 +1,5 @@ + + + + + diff -r 893c55cd168d ide.ergonomics/nbproject/project.xml --- a/ide.ergonomics/nbproject/project.xml Wed Aug 05 06:31:25 2009 +0400 +++ b/ide.ergonomics/nbproject/project.xml Wed Aug 05 18:19:21 2009 +0200 @@ -38,7 +38,7 @@ 1 - 1.15 + 1.17 diff -r 893c55cd168d ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java Wed Aug 05 06:31:25 2009 +0400 +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java Wed Aug 05 18:19:21 2009 +0200 @@ -120,16 +120,16 @@ boolean empty = true; LOG.fine("collecting layers"); // NOI18N List urls = new ArrayList(); + urls.add(0, FoDFileSystem.class.getResource("common.xml")); // NOI18N for (FeatureInfo info : FeatureManager.features()) { if (!info.isPresent()) { continue; } - if (!info.isEnabled()) { - LOG.finest("adding feature " + info.clusterName); // NOI18N - if (info.getLayerURL() != null) { - urls.add(info.getLayerURL()); - } - } else { + LOG.finest("adding feature " + info.clusterName); // NOI18N + if (info.getLayerURL() != null) { + urls.add(info.getLayerURL()); + } + if (info.isEnabled()) { empty = false; } } diff -r 893c55cd168d ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/common.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/common.xml Wed Aug 05 18:19:21 2009 +0200 @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff -r 893c55cd168d openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml Wed Aug 05 06:31:25 2009 +0400 +++ b/openide.filesystems/apichanges.xml Wed Aug 05 18:19:21 2009 +0200 @@ -46,7 +46,25 @@ Filesystems API - + + + Allow modules to dynamically add/remove layer content + + + + + +

+ One can provide fallback + content of system filesystem by + returning Boolean.TRUE from call + to fs.getRoot().getAttribute("fallback"). +

+
+ + +
+ Read files with asText(), asBytes() and asLines() diff -r 893c55cd168d openide.filesystems/arch.xml --- a/openide.filesystems/arch.xml Wed Aug 05 06:31:25 2009 +0400 +++ b/openide.filesystems/arch.xml Wed Aug 05 18:19:21 2009 +0200 @@ -370,7 +370,7 @@ is provided for applications where a history of recently used directories is a security concern. - + @@ -909,6 +909,16 @@ memory file system, or any other you write yourself.

+ +

+ Since version 7.23 you can use + By returning Boolean.TRUE from call + to fs.getRoot().getAttribute("fallback") + you can place your filesystem behind all layers provided + by standard modules and form a kind of fallback + +

diff -r 893c55cd168d openide.filesystems/nbproject/project.properties --- a/openide.filesystems/nbproject/project.properties Wed Aug 05 06:31:25 2009 +0400 +++ b/openide.filesystems/nbproject/project.properties Wed Aug 05 18:19:21 2009 +0200 @@ -44,4 +44,4 @@ javadoc.main.page=org/openide/filesystems/doc-files/api.html javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=7.22.0 +spec.version.base=7.23.0 diff -r 893c55cd168d openide.filesystems/src/org/openide/filesystems/ExternalUtil.java --- a/openide.filesystems/src/org/openide/filesystems/ExternalUtil.java Wed Aug 05 06:31:25 2009 +0400 +++ b/openide.filesystems/src/org/openide/filesystems/ExternalUtil.java Wed Aug 05 18:19:21 2009 +0200 @@ -231,8 +231,18 @@ private static FileSystem[] computeDelegates() { List arr = new ArrayList(); arr.add(MEMORY); + for (FileSystem f : ALL.allInstances()) { + if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N + continue; + } + arr.add(f); + } arr.add(layers); - arr.addAll(ALL.allInstances()); + for (FileSystem f : ALL.allInstances()) { + if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N + arr.add(f); + } + } return arr.toArray(new FileSystem[0]); } diff -r 893c55cd168d openide.filesystems/test/unit/src/org/openide/filesystems/DynamicSFSFallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/DynamicSFSFallbackTest.java Wed Aug 05 18:19:21 2009 +0200 @@ -0,0 +1,132 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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.openide.filesystems; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; +import org.netbeans.junit.MockServices; +import org.netbeans.junit.NbTestCase; +import org.openide.util.lookup.InstanceContent; + +/** Test layering of filesystems installed via lookup. + * + * @author Jaroslav Tulach + */ +public class DynamicSFSFallbackTest extends NbTestCase +implements InstanceContent.Convertor { + public DynamicSFSFallbackTest(String testName) { + super(testName); + } + + @Override + protected void setUp() throws Exception { + MyFS1.dir = new File(getWorkDir(), "dir1"); + MyFS2.dir = new File(getWorkDir(), "dir2"); + MockServices.setServices(MyFS1.class, MyFS2.class); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public static final class MyFS1 extends LocalFileSystem { + static File dir; + + public MyFS1() throws Exception { + dir.mkdirs(); + setRootDirectory(dir); + getRoot().setAttribute("fallback", Boolean.TRUE); + + FileObject fo1 = FileUtil.createData(getRoot(), "test/data.txt"); + fo1.setAttribute("one", 1); + write(fo1, "fileone"); + FileObject fo11 = FileUtil.createData(getRoot(), "test-fs-is-there.txt"); + write(fo11, "hereIam"); + } + } + public static final class MyFS2 extends LocalFileSystem { + static File dir; + + public MyFS2() throws Exception { + dir.mkdirs(); + setRootDirectory(dir); + FileObject fo1 = FileUtil.createData(getRoot(), "test/data.txt"); + fo1.setAttribute("two", 1); + write(fo1, "two"); + } + } + + public void testDynamicSystemsCanAlsoBeBehindLayers() throws Exception { + FileObject global = FileUtil.getConfigFile("test/data.txt"); + assertEquals("Second file system takes preceedence", "two", global.asText()); + assertTrue("Still valid", global.isValid()); + + FileObject fo = FileUtil.getConfigFile("test-fs-is-there.txt"); + assertNotNull("File found: " + Arrays.toString(FileUtil.getConfigRoot().getChildren()), fo); + assertEquals("Text is correct", "hereIam", fo.asText()); + } + + private static void write(FileObject fo, String txt) throws IOException { + OutputStream os = fo.getOutputStream(); + os.write(txt.getBytes()); + os.close(); + } + + public FileSystem convert(FileSystem obj) { + return obj; + } + + public Class type(FileSystem obj) { + return obj.getClass(); + } + + public String id(FileSystem obj) { + return obj.getDisplayName(); + } + + public String displayName(FileSystem obj) { + return obj.getDisplayName(); + } +}