diff --git a/core.startup/nbproject/project.xml b/core.startup/nbproject/project.xml --- a/core.startup/nbproject/project.xml +++ b/core.startup/nbproject/project.xml @@ -63,7 +63,7 @@ - 7.57 + 7.59 diff --git a/core.startup/src/org/netbeans/core/startup/NbRepository.java b/core.startup/src/org/netbeans/core/startup/NbRepository.java --- a/core.startup/src/org/netbeans/core/startup/NbRepository.java +++ b/core.startup/src/org/netbeans/core/startup/NbRepository.java @@ -47,13 +47,21 @@ import java.beans.PropertyVetoException; import java.io.File; import java.io.IOException; +import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.netbeans.core.startup.layers.ModuleLayeredFileSystem; import org.openide.filesystems.*; import org.netbeans.core.startup.layers.SessionManager; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; import org.openide.util.NbBundle; /** Default repository. @@ -170,5 +178,22 @@ private static void doExit (int value) { TopLogging.exit(value); } - + + public List additionalLayers(List urls) { + for (LayersProvider p : Lookup.getDefault().lookupAll(LayersProvider.class)) { + List mix = new ArrayList(urls); + mix.addAll(findLayers(p)); + urls = mix; + } + return urls; + } + + @Override + protected void refreshAdditionalLayers() { + try { + ModuleLayeredFileSystem.getInstallationModuleLayer().setURLs(null); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } } diff --git a/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java b/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java --- a/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java +++ b/core.startup/src/org/netbeans/core/startup/layers/ModuleLayeredFileSystem.java @@ -54,11 +54,13 @@ import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; +import org.netbeans.core.startup.NbRepository; import org.netbeans.core.startup.StartLog; import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileUtil; import org.openide.filesystems.MultiFileSystem; +import org.openide.filesystems.Repository.LayersProvider; import org.openide.filesystems.XMLFileSystem; import org.openide.modules.ModuleInfo; import org.openide.util.Lookup; @@ -78,11 +80,13 @@ static final Logger err = Logger.getLogger("org.netbeans.core.projects"); // NOI18N - /** lookup result we listen on */ - private static Lookup.Result result = Lookup.getDefault().lookupResult(FileSystem.class); + /** lookup result for registered filesystems */ + private static Lookup.Result fsResult = Lookup.getDefault().lookupResult(FileSystem.class); + private static Lookup.Result layerResult = Lookup.getDefault().lookupResult(LayersProvider.class); /** current list of URLs - r/o; or null if not yet set */ private List urls; + private List prevs; /** cache manager */ private LayerCacheManager manager; /** writable layer */ @@ -130,15 +134,15 @@ urls = null; - result.addLookupListener(this); - result.allItems(); + fsResult.addLookupListener(this); + layerResult.addLookupListener(this); } 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 (addLookupBefore) { - for (FileSystem f : result.allInstances()) { + for (FileSystem f : fsResult.allInstances()) { if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N continue; } @@ -163,7 +167,7 @@ } } if (!addLookupBefore) { - for (FileSystem f : result.allInstances()) { + for (FileSystem f : fsResult.allInstances()) { if (Boolean.TRUE.equals(f.getRoot().getAttribute("fallback"))) { // NOI18N l.add(f); } @@ -222,13 +226,23 @@ /** Change the list of module layers URLs. * @param urls the urls describing module layers to use. List */ - public void setURLs (final List urls) throws Exception { + public void setURLs (List urls) throws Exception { + if (urls == null) { + urls = this.prevs; + } + if (urls == null) { + return; + } if (urls.contains(null)) { throw new NullPointerException("urls=" + urls); } // NOI18N if (err.isLoggable(Level.FINE)) { err.log(Level.FINE, "setURLs: {0}", urls); } + List orig = urls; + if (this == ModuleLayeredFileSystem.getInstallationModuleLayer()) { + urls = ((NbRepository)NbRepository.getDefault()).additionalLayers(urls); + } if (this.urls != null && urls.equals(this.urls)) { err.fine("no-op"); return; @@ -248,6 +262,7 @@ } this.urls = urls; + this.prevs = orig; firePropertyChange ("layers", null, null); // NOI18N StartLog.logEnd("setURLs"); // NOI18N @@ -261,8 +276,8 @@ } // Add to the front: #23609. ArrayList arr = new ArrayList(urls); - if (this.urls != null) { - arr.addAll(this.urls); + if (this.prevs != null) { + arr.addAll(this.prevs); } setURLs(arr); } @@ -274,8 +289,8 @@ throw new NullPointerException("urls=" + urls); } ArrayList arr = new ArrayList(); - if (this.urls != null) { - arr.addAll(this.urls); + if (this.prevs != null) { + arr.addAll(this.prevs); } arr.removeAll(urls); setURLs(arr); @@ -283,7 +298,21 @@ /** Refresh layers */ @Override public void resultChanged(LookupEvent ev) { - setDelegates(appendLayers(writableLayer, addLookupBefore, otherLayers, cacheLayer, addLookupBefore)); + if (ev.getSource() == fsResult) { + setDelegates(appendLayers(writableLayer, addLookupBefore, otherLayers, cacheLayer, addLookupBefore)); + return; + } + if (ev.getSource() == layerResult) { + if (prevs != null) { + try { + setURLs(prevs); + } catch (Exception ex) { + err.log(Level.INFO, null, ex); + } + } + return; + } + throw new IllegalStateException("Unknown source: " + ev.getSource()); } public static List collectLayers(ClassLoader loader) throws IOException { diff --git a/core.startup/test/unit/src/org/netbeans/core/startup/layers/ContentProviderTest.java b/core.startup/test/unit/src/org/netbeans/core/startup/layers/ContentProviderTest.java new file mode 100644 --- /dev/null +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/ContentProviderTest.java @@ -0,0 +1,118 @@ +/* + * 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. + */ +package org.netbeans.core.startup.layers; + +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import junit.framework.Test; +import org.netbeans.core.startup.MainLookup; +import org.netbeans.core.startup.NbRepository; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.Repository; +import org.openide.filesystems.Repository.LayersProvider; +import org.openide.util.Lookup; + +/** + * + * @author Jaroslav Tulach + */ +public class ContentProviderTest extends NbTestCase { + public ContentProviderTest(String name) { + super(name); + } + + public static Test suite() { + return NbModuleSuite.createConfiguration(ContentProviderTest.class) + .gui(false).suite(); + } + + public void testBeforeRest() { + FileObject fo = FileUtil.getConfigFile("foo/bar"); + assertNull("no foo/bar provided", fo); + } + + public void testUsingNbRepositoryAndInit() { + if (Repository.getDefault() instanceof NbRepository) { + MainLookup.register(new MyProvider()); + return; + } + fail("Wrong repository: " + Repository.getDefault()); + } + + public void testCheckAFileFromOurLayer() { + FileObject fo = FileUtil.getConfigFile("foo/bar"); + assertNotNull("foo/bar is provided", fo); + assertEquals("value is val", "val", fo.getAttribute("x")); + } + + public void testReturnEmptyLayers() throws Exception { + MyProvider my = Lookup.getDefault().lookup(MyProvider.class); + my.makeEmpty(); + FileObject fo = FileUtil.getConfigFile("foo/bar"); + assertNull("no foo/bar is provided anymore", fo); + + } + + public static final class MyProvider extends LayersProvider { + private boolean empty; + + final void makeEmpty() { + empty = true; + refresh(); + } + + @Override + protected void registerLayers(Collection context) { + if (empty) { + return; + } + context.add(ContentProviderTest.class.getResource("ContentProviderTest.xml")); + assertFalse("No nulls", context.contains(null)); + } + } + +} diff --git a/openide.filesystems/test/unit/src/org/openide/filesystems/test-layer-attribs.xml b/core.startup/test/unit/src/org/netbeans/core/startup/layers/ContentProviderTest.xml copy from openide.filesystems/test/unit/src/org/openide/filesystems/test-layer-attribs.xml copy to core.startup/test/unit/src/org/netbeans/core/startup/layers/ContentProviderTest.xml diff --git a/ide.ergonomics/nbproject/project.xml b/ide.ergonomics/nbproject/project.xml --- a/ide.ergonomics/nbproject/project.xml +++ b/ide.ergonomics/nbproject/project.xml @@ -115,7 +115,7 @@ - 7.55 + 7.59 diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/Installer.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/Installer.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/Installer.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/Installer.java @@ -43,7 +43,6 @@ import org.netbeans.api.project.ui.OpenProjects; import org.netbeans.modules.ide.ergonomics.fod.FeatureManager; -import org.netbeans.modules.ide.ergonomics.fod.FoDFileSystem; import org.openide.modules.ModuleInstall; import org.openide.util.Exceptions; @@ -57,7 +56,6 @@ @Override public void restored() { WarmUp.init(); - FoDFileSystem.getInstance().initListener(); } @Override diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/debugger/AttachTypeProxy.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/debugger/AttachTypeProxy.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/debugger/AttachTypeProxy.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/debugger/AttachTypeProxy.java @@ -49,7 +49,7 @@ import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.modules.ide.ergonomics.fod.ConfigurationPanel; import org.netbeans.modules.ide.ergonomics.fod.FeatureInfo; -import org.netbeans.modules.ide.ergonomics.fod.FoDFileSystem; +import org.netbeans.modules.ide.ergonomics.fod.FoDLayersProvider; import org.netbeans.spi.debugger.ui.AttachType; import org.netbeans.spi.debugger.ui.Controller; import org.openide.filesystems.FileObject; @@ -74,7 +74,7 @@ } public static AttachType create(FileObject fob) { - FeatureInfo whichProvides = FoDFileSystem.getInstance().whichProvides(fob); + FeatureInfo whichProvides = FoDLayersProvider.getInstance().whichProvides(fob); String displayName = (String) fob.getAttribute("displayName"); if (displayName == null) { throw new IllegalArgumentException("No displayName attribute: " + fob); diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureAction.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureAction.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureAction.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureAction.java @@ -68,7 +68,7 @@ } public void actionPerformed(ActionEvent e) { - FeatureInfo info = FoDFileSystem.getInstance().whichProvides(fo); + FeatureInfo info = FoDLayersProvider.getInstance().whichProvides(fo); String n = Actions.cutAmpersand((String)fo.getAttribute("displayName")); // NOI18N boolean success = Utilities.featureDialog(info, n, n); if (!success) { diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureInfo.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureInfo.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureInfo.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureInfo.java @@ -187,7 +187,7 @@ fs = new XMLFileSystem(url); return fs; } catch (SAXException ex) { - FoDFileSystem.LOG.log(Level.SEVERE, "Cannot parse: " + url, ex); + FoDLayersProvider.LOG.log(Level.SEVERE, "Cannot parse: " + url, ex); Exceptions.printStackTrace(ex); } } @@ -223,7 +223,7 @@ try { required[1] = e = XPathFactory.newInstance().newXPath().compile((String) r1); } catch (XPathExpressionException ex) { - FoDFileSystem.LOG.log(Level.WARNING, "Cannot parse " + r1, ex); + FoDLayersProvider.LOG.log(Level.WARNING, "Cannot parse " + r1, ex); continue; } } else { diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java @@ -162,7 +162,7 @@ * @return */ public static int dumpModules(Level withLevel, Level detailsLevel) { - if (!FoDFileSystem.LOG.isLoggable(withLevel)) { + if (!FoDLayersProvider.LOG.isLoggable(withLevel)) { return -1; } int cnt = 0; @@ -180,26 +180,26 @@ } } if (enabled.isEmpty() && disabled.isEmpty()) { - FoDFileSystem.LOG.log(withLevel, info.clusterName + " not present"); // NOTICES + FoDLayersProvider.LOG.log(withLevel, info.clusterName + " not present"); // NOTICES continue; } if (enabled.isEmpty()) { - FoDFileSystem.LOG.log(withLevel, info.clusterName + " disabled"); // NOTICES + FoDLayersProvider.LOG.log(withLevel, info.clusterName + " disabled"); // NOTICES continue; } if (disabled.isEmpty()) { - FoDFileSystem.LOG.log(withLevel, info.clusterName + " enabled"); // NOTICES + FoDLayersProvider.LOG.log(withLevel, info.clusterName + " enabled"); // NOTICES cnt++; continue; } - FoDFileSystem.LOG.log(withLevel, + FoDLayersProvider.LOG.log(withLevel, info.clusterName + " enabled " + enabled.size() + " disabled " + disabled.size()); // NOTICES cnt++; for (String cnb : disabled) { - FoDFileSystem.LOG.log(detailsLevel, "- " + cnb); // NOI18N + FoDLayersProvider.LOG.log(detailsLevel, "- " + cnb); // NOI18N } for (String cnb : enabled) { - FoDFileSystem.LOG.log(detailsLevel, "+ " + cnb); // NOI18N + FoDLayersProvider.LOG.log(detailsLevel, "+ " + cnb); // NOI18N } } return cnt; @@ -292,12 +292,12 @@ } private void fireChange() { - FoDFileSystem.LOG.fine("Firing FeatureManager change"); // NOI18N + FoDLayersProvider.LOG.fine("Firing FeatureManager change"); // NOI18N for (FeatureInfo f : features()) { f.clearCache(); } support.fireChange(); - FoDFileSystem.LOG.fine("FeatureManager change delivered"); // NOI18N + FoDLayersProvider.LOG.fine("FeatureManager change delivered"); // NOI18N } /** Useful for testing */ diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FindComponentModules.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FindComponentModules.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FindComponentModules.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FindComponentModules.java @@ -165,7 +165,7 @@ } } if (res.size() > 1) { - FoDFileSystem.LOG.warning("No prefCNB found " + prefCNB + " using multiple " + res); + FoDLayersProvider.LOG.warning("No prefCNB found " + prefCNB + " using multiple " + res); } return res; } @@ -261,7 +261,7 @@ all.add (el); all.addAll (reqs); // } else { -// FoDFileSystem.LOG.fine("Cannot enable " + el.getCodeName() + " broken deps: " + breaks); // NOI18N +// FoDLayersProvider.LOG.fine("Cannot enable " + el.getCodeName() + " broken deps: " + breaks); // NOI18N // ignore.add(el.getCodeName()); // } } else { diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDEditorOpened.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDEditorOpened.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDEditorOpened.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDEditorOpened.java @@ -58,7 +58,7 @@ public void annotate(Set set, Lookup context) { if (!anEditorIsOpened) { anEditorIsOpened = true; - FoDFileSystem.getInstance().resultChanged(null); + FoDLayersProvider.getInstance().resultChanged(null); } } diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDLayersProvider.java rename from ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java rename to ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDLayersProvider.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDFileSystem.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDLayersProvider.java @@ -41,28 +41,18 @@ */ package org.netbeans.modules.ide.ergonomics.fod; -import java.io.IOException; import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import org.netbeans.core.startup.layers.LayerCacheManager; import org.netbeans.spi.project.ProjectFactory; import org.netbeans.spi.project.support.ant.AntBasedProjectType; import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileSystem; -import org.openide.filesystems.MultiFileSystem; +import org.openide.filesystems.Repository; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.RequestProcessor; -import org.openide.util.WeakListeners; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; @@ -71,65 +61,27 @@ * @author Jirka Rechtacek */ @ServiceProviders({ - @ServiceProvider(service=FileSystem.class), - @ServiceProvider(service=FoDFileSystem.class) + @ServiceProvider(service=Repository.LayersProvider.class), + @ServiceProvider(service=FoDLayersProvider.class) }) -public final class FoDFileSystem extends MultiFileSystem -implements Runnable, ChangeListener, LookupListener { - private static final LayerCacheManager manager = LayerCacheManager.create("all-ergonomics.dat"); // NOI18N - final static Logger LOG = Logger.getLogger (FoDFileSystem.class.getPackage().getName()); +public final class FoDLayersProvider extends Repository.LayersProvider +implements LookupListener, Runnable { + final static Logger LOG = Logger.getLogger (FoDLayersProvider.class.getPackage().getName()); private static RequestProcessor RP = new RequestProcessor("Ergonomics"); // NOI18N private RequestProcessor.Task refresh = RP.create(this, true); private Lookup.Result factories; private Lookup.Result ants; - private boolean forcedRefresh; - private final ChangeListener weakL; - public FoDFileSystem() { - setPropagateMasks(true); - weakL = WeakListeners.change(this, FeatureManager.getInstance()); - FileSystem fs; - try { - fs = manager.loadCache(); - if (fs != null) { - LOG.fine("Using cached layer"); // NOI18N - setDelegates(fs); - return; - } - } catch (IOException ex) { - LOG.log(Level.WARNING, "Cannot read cache", ex); // NOI18N - } - refresh(); - } - - public static FoDFileSystem getInstance() { - return Lookup.getDefault().lookup(FoDFileSystem.class); - } - - public void initListener() { - FeatureManager.getInstance().addChangeListener(weakL); - } - - public void refresh() { - refresh.schedule(0); - refresh.waitFinished(); - } - public void refreshForce() { - forcedRefresh = true; - refresh.schedule(0); - refresh.waitFinished(); - } - - public void waitFinished() { - refresh.waitFinished(); + public static FoDLayersProvider getInstance() { + return Lookup.getDefault().lookup(FoDLayersProvider.class); } @Override - public void run() { + protected void registerLayers(Collection context) { boolean empty = true; LOG.fine("collecting layers"); // NOI18N List urls = new ArrayList(); - urls.add(0, FoDFileSystem.class.getResource("common.xml")); // NOI18N + urls.add(0, FoDLayersProvider.class.getResource("common.xml")); // NOI18N for (FeatureInfo info : FeatureManager.features()) { if (!info.isPresent()) { continue; @@ -144,26 +96,11 @@ } if (empty && noAdditionalProjects() && !FoDEditorOpened.anEditorIsOpened) { LOG.fine("adding default layer"); // NOI18N - urls.add(0, FoDFileSystem.class.getResource("default.xml")); // NOI18N - } - if (forcedRefresh) { - forcedRefresh = false; - LOG.log(Level.INFO, "Forced refresh. Setting delegates to empty"); // NOI18N - setDelegates(); - LOG.log(Level.INFO, "New delegates count: {0}", urls.size()); // NOI18N - LOG.log(Level.INFO, "{0}", urls); // NOI18N + urls.add(0, FoDLayersProvider.class.getResource("default.xml")); // NOI18N } LOG.log(Level.FINE, "delegating to {0} layers", urls.size()); // NOI18N + context.addAll(urls); LOG.log(Level.FINEST, "{0}", urls); // NOI18N - - try { - FileSystem fs = getDelegates().length == 0 ? - manager.createEmptyFileSystem() : getDelegates()[0]; - fs = manager.store(fs, urls); - setDelegates(fs); - } catch (IOException ex) { - LOG.log(Level.WARNING, "Cannot save cache", ex); - } LOG.fine("done"); FeatureManager.dumpModules(); } @@ -192,13 +129,18 @@ } @Override - public void stateChanged(ChangeEvent e) { + public void resultChanged(LookupEvent ev) { refresh.schedule(500); } - + public void refreshForce() { + super.refresh(); + } @Override - public void resultChanged(LookupEvent ev) { - refresh.schedule(0); + public void run() { + super.refresh(); + } + public void waitFinished() { + refresh.waitFinished(); } private boolean noAdditionalProjects() { diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactory.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactory.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactory.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactory.java @@ -82,7 +82,7 @@ private FodDataObjectFactory(FileObject fo) { this.definition = fo; - this.info = FoDFileSystem.getInstance().whichProvides(definition); + this.info = FoDLayersProvider.getInstance().whichProvides(definition); } @@ -154,10 +154,10 @@ } private void delegate(boolean open) { - FeatureInfo info = FoDFileSystem.getInstance().whichProvides(definition); + FeatureInfo info = FoDLayersProvider.getInstance().whichProvides(definition); String msg = NbBundle.getMessage(FodDataObjectFactory.class, "MSG_Opening_File", fo.getNameExt()); - FoDFileSystem.LOG.log(Level.FINER, "Opening file {0}", this); + FoDLayersProvider.LOG.log(Level.FINER, "Opening file {0}", this); this.open = open; boolean success = Utilities.featureDialog(info, msg, msg); if (success) { @@ -170,7 +170,7 @@ ignore.add(getPrimaryFile()); try { DataObject obj = DataObject.find(fo); - FoDFileSystem.LOG.log(Level.FINER, "finishOpen {0}", obj); + FoDLayersProvider.LOG.log(Level.FINER, "finishOpen {0}", obj); Class what = open ? OpenCookie.class : EditCookie.class; Object oc = obj.getLookup().lookup(what); if (oc == this) { @@ -193,8 +193,8 @@ @Override public void stateChanged(ChangeEvent e) { - FeatureInfo info = FoDFileSystem.getInstance().whichProvides(definition); - FoDFileSystem.LOG.log(Level.FINER, "Refresh state of {0}", this); + FeatureInfo info = FoDLayersProvider.getInstance().whichProvides(definition); + FoDLayersProvider.LOG.log(Level.FINER, "Refresh state of {0}", this); ignore.add(getPrimaryFile()); if (info == null || info.isEnabled()) { dispose(); diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesActivator.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesActivator.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesActivator.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesActivator.java @@ -111,7 +111,7 @@ progressMonitor.onError(ex.getLocalizedMessage()); Logger.getLogger(ModulesActivator.class.getName()).warning(ex.getMessage()); } finally { - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); } } diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesInstaller.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesInstaller.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesInstaller.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/ModulesInstaller.java @@ -128,7 +128,7 @@ } if (success) { - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); } return success; @@ -193,7 +193,7 @@ ); DialogDisplayer.getDefault ().notifyLater (nd); } finally { - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); } } diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/OpenAdvancedAction.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/OpenAdvancedAction.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/OpenAdvancedAction.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/OpenAdvancedAction.java @@ -78,7 +78,7 @@ if (mimeDefinition == null) { return; } - final FeatureInfo info = FoDFileSystem.getInstance().whichProvides(mimeDefinition); + final FeatureInfo info = FoDLayersProvider.getInstance().whichProvides(mimeDefinition); if (info == null || info.isEnabled()) { return; } diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/DescriptionStep.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/DescriptionStep.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/DescriptionStep.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/DescriptionStep.java @@ -43,6 +43,7 @@ */ package org.netbeans.modules.ide.ergonomics.newproject; +import java.util.concurrent.ExecutionException; import org.netbeans.modules.ide.ergonomics.fod.FindComponentModules; import org.netbeans.modules.ide.ergonomics.fod.ModulesInstaller; import java.awt.Component; @@ -68,7 +69,7 @@ import org.netbeans.api.progress.ProgressHandle; import org.netbeans.modules.ide.ergonomics.ServerWizardProviderProxy; import org.netbeans.modules.ide.ergonomics.fod.ConfigurationPanel; -import org.netbeans.modules.ide.ergonomics.fod.FoDFileSystem; +import org.netbeans.modules.ide.ergonomics.fod.FoDLayersProvider; import org.netbeans.modules.ide.ergonomics.fod.FeatureInfo; import org.netbeans.modules.ide.ergonomics.fod.FeatureManager; import org.netbeans.spi.server.ServerWizardProvider; @@ -109,7 +110,7 @@ configPanel = new ConfigurationPanel(new Callable() { @Override public JComponent call() throws Exception { - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); waitForDelegateWizard(); return new JLabel(" "); } @@ -182,7 +183,7 @@ forEnable = elems; fireChange (); } else { - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); waitForDelegateWizard (); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -207,7 +208,7 @@ Object o = settings.getProperty (FeatureOnDemandWizardIterator.CHOSEN_TEMPLATE); assert o != null && o instanceof FileObject : o + " is not null and instanceof FileObject."; FileObject fileObject = (FileObject) o; - info = FoDFileSystem.getInstance ().whichProvides(fileObject); + info = FoDLayersProvider.getInstance ().whichProvides(fileObject); assert info != null : "No info for " + fileObject; finder = new FindComponentModules(info); } @@ -228,8 +229,11 @@ WizardDescriptor.InstantiatingIterator iterator = null; int i = 0; while (fo == null || iterator == null) { - FoDFileSystem.getInstance().refresh(); - FoDFileSystem.getInstance().waitFinished(); + try { + FoDLayersProvider.getInstance().refreshForce(); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } // hot-fixed wizard providers - temporary if (templateResource.startsWith("Servers/WizardProvider")) { try { @@ -287,7 +291,7 @@ } LOG.info("Forcing refresh"); // NOI18N // force refresh for the filesystem - FoDFileSystem.getInstance().refreshForce(); + FoDLayersProvider.getInstance().refreshForce(); LOG.info("Done with refresh"); // NOI18N FileObject fake = FileUtil.getConfigFile(templateResource); diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/EnableStep.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/EnableStep.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/EnableStep.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/EnableStep.java @@ -61,7 +61,7 @@ import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.modules.ide.ergonomics.fod.FeatureInfo; import org.netbeans.modules.ide.ergonomics.fod.FeatureManager; -import org.netbeans.modules.ide.ergonomics.fod.FoDFileSystem; +import org.netbeans.modules.ide.ergonomics.fod.FoDLayersProvider; import org.openide.WizardDescriptor; import org.openide.WizardDescriptor.Panel; import org.openide.filesystems.FileObject; @@ -125,7 +125,7 @@ RequestProcessor.Task enable = activator.getEnableTask (); enable.schedule (0); enable.waitFinished (); - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); waitForDelegateWizard (); } } @@ -153,7 +153,7 @@ Object templateO = settings.getProperty (FeatureOnDemandWizardIterator.CHOSEN_TEMPLATE); assert templateO != null && templateO instanceof FileObject : templateO + " is not null and instanceof FileObject."; FileObject templateFO = (FileObject) templateO; - FeatureInfo info = FoDFileSystem.getInstance().whichProvides(templateFO); + FeatureInfo info = FoDLayersProvider.getInstance().whichProvides(templateFO); RequestProcessor.Task t = FeatureManager.getInstance().create(doEnable(info)); t.schedule(0); } diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/FeatureOnDemandWizardIterator.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/FeatureOnDemandWizardIterator.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/FeatureOnDemandWizardIterator.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/newproject/FeatureOnDemandWizardIterator.java @@ -53,7 +53,7 @@ import javax.swing.JComponent; import javax.swing.event.ChangeListener; import org.netbeans.api.progress.ProgressHandle; -import org.netbeans.modules.ide.ergonomics.fod.FoDFileSystem; +import org.netbeans.modules.ide.ergonomics.fod.FoDLayersProvider; import org.openide.WizardDescriptor; import org.openide.WizardDescriptor.InstantiatingIterator; import org.openide.WizardDescriptor.ProgressInstantiatingIterator; @@ -95,7 +95,7 @@ private static WizardDescriptor.InstantiatingIterator getRealNewMakeProjectWizardIterator (FileObject template) { WizardDescriptor.InstantiatingIterator res = null; - if (FoDFileSystem.getInstance().getDelegateFileSystem (template) != null) { + if (FoDLayersProvider.getInstance().getDelegateFileSystem (template) != null) { return null; } FileObject fo = FileUtil.getConfigFile(template.getPath ()); diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalAntBasedTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalAntBasedTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalAntBasedTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalAntBasedTest.java @@ -120,7 +120,7 @@ assertNotNull("Ant found", f); LOG.info("waiting for FoDFileSystem to be updated"); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().waitFinished(); LOG.info("waiting for FoDFileSystem to be waitFinished is over"); for (int cnt = 0; cnt < 5; cnt++) { diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalProjectFactoryTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalProjectFactoryTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalProjectFactoryTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/AdditionalProjectFactoryTest.java @@ -103,7 +103,7 @@ Factory f = Lookup.getDefault().lookup(Factory.class); assertNotNull("Factory found", f); LOG.info("Factory found"); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().waitFinished(); LOG.info("Refresh finished"); for (int i = 0; i < 100; i++) { diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/EnablingAutoloadLeavesFeatureDisabledTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/EnablingAutoloadLeavesFeatureDisabledTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/EnablingAutoloadLeavesFeatureDisabledTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/EnablingAutoloadLeavesFeatureDisabledTest.java @@ -155,8 +155,7 @@ ParseXMLContentTest.class.getResource("TestBundle4.properties") ); ic.add(info); - FoDFileSystem.getInstance().refresh(); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().refreshForce(); } diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactoryTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactoryTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactoryTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectFactoryTest.java @@ -154,8 +154,7 @@ ParseXMLContentTest.class.getResource("TestBundle.properties") ); ic.add(info); - FoDFileSystem.getInstance().refresh(); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().refreshForce(); } diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectXMLFactoryTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectXMLFactoryTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectXMLFactoryTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/FodDataObjectXMLFactoryTest.java @@ -160,8 +160,7 @@ ParseXMLContentTest.class.getResource("TestBundle.properties") ); ic.add(info); - FoDFileSystem.getInstance().refresh(); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().refreshForce(); } diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/GeneralActionTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/GeneralActionTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/GeneralActionTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/GeneralActionTest.java @@ -122,7 +122,7 @@ root = FileUtil.toFileObject(getWorkDir()); assertNotNull("fileobject found", root); - FoDFileSystem.getInstance().refresh(); + FoDLayersProvider.getInstance().refreshForce(); actionFile = FileUtil.getConfigFile("Actions/System/org-netbeans-modules-autoupdate-ui-actions-PluginManagerAction.instance"); assertNotNull("testing layer is loaded: ", actionFile); diff --git a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/OpenEditorEnablesEditMenuFactoryTest.java b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/OpenEditorEnablesEditMenuFactoryTest.java --- a/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/OpenEditorEnablesEditMenuFactoryTest.java +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/fod/OpenEditorEnablesEditMenuFactoryTest.java @@ -151,7 +151,7 @@ } }); LOG.info("waitFinished"); - FoDFileSystem.getInstance().waitFinished(); + FoDLayersProvider.getInstance().waitFinished(); FileObject fo = null; for (int i = 0; i < 100; i++) { diff --git a/openide.filesystems/apichanges.xml b/openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml +++ b/openide.filesystems/apichanges.xml @@ -49,6 +49,25 @@ Filesystems API + + + SPI for Additions to System File System + + + + + +

+ Those who wish to influence content of + + configuration file system have an easier + + way now. +

+
+ + +
Annotations to declare MIME type diff --git a/openide.filesystems/manifest.mf b/openide.filesystems/manifest.mf --- a/openide.filesystems/manifest.mf +++ b/openide.filesystems/manifest.mf @@ -2,5 +2,5 @@ OpenIDE-Module: org.openide.filesystems OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml -OpenIDE-Module-Specification-Version: 7.58 +OpenIDE-Module-Specification-Version: 7.59 diff --git a/openide.filesystems/src/org/openide/filesystems/Repository.java b/openide.filesystems/src/org/openide/filesystems/Repository.java --- a/openide.filesystems/src/org/openide/filesystems/Repository.java +++ b/openide.filesystems/src/org/openide/filesystems/Repository.java @@ -56,13 +56,8 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Vector; +import java.util.*; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; import java.util.jar.Manifest; import java.util.logging.Level; @@ -72,6 +67,7 @@ import org.openide.util.LookupListener; import org.openide.util.NbCollections; import org.openide.util.io.NbMarshalledObject; +import org.openide.util.lookup.ServiceProvider; /** * Holder for NetBeans default (system, configuration) filesystem, used for most @@ -143,6 +139,70 @@ return repository; } + + /** Contributes to content of {@link #getDefaultFileSystem() system file system} + * (which influences structure under {@link FileUtil#getConfigRoot()}). The + * method {@link #registerLayers(java.util.Collection)} + * is called during initialization of {@link Repository} and + * implementors (registered via {@link ServiceProvider} annotation) may + * add their layers (later processed via {@link XMLFileSystem}) into + * the general collection of existing providers. + *

+ * The list of layers as well as their content may be cached. + * In a typical NetBeans Platform application, the cache remains until + * list of modules + * and their enabled state remain the same. While it does, the {@link LayersProvider}s + * are not queried again. + *

+ * @since 7.59 + */ + public static abstract class LayersProvider { + /** Allows providers to add their additions to the structure + * beneath {@link FileUtil#getConfigRoot()}. The method is + * supposed to collect all additional layers and {@link Collection#add(java.lang.Object) add} + * them into the context collection. The provided + * layers will be processed by {@link XMLFileSystem}-like manner later. + * + * @param context the context where to register the additions + */ + protected abstract void registerLayers(Collection context); + + /** Method to call when set of URLs returned from the {@link #layers()} + * method changed and there is a need to refresh it. Refresh is very likely + * a time consuming task - consider invoking it on a background thread and + * don't hold any locks while calling the method + */ + protected final void refresh() { + Repository.getDefault().refreshAdditionalLayers(); + } + } + + /** Methods that tells {@link Repository} subclasses to refresh list of + * URLs provided by {@link LayersProvider}s. + * @since 7.59 + */ + protected void refreshAdditionalLayers() { + if (getDefaultFileSystem() instanceof MainFS) { + ((MainFS)getDefaultFileSystem()).refreshLayers(); + } + } + + /** Allows subclasses registered as {@link Repository#getDefault()} to + * find out list of URLs for a given provider. The method just calls + * {@link LayersProvider#layers()}. + * + * @param p the provider. + * @return ordered list of URLs + * @since 7.59 + */ + protected final List findLayers(LayersProvider p) { + if (this != Repository.getDefault()) { + return Collections.emptyList(); + } + List urls = new ArrayList(); + p.registerLayers(urls); + return urls; + } private static final class MainFS extends MultiFileSystem implements LookupListener { private static final Lookup.Result ALL = Lookup.getDefault().lookupResult(FileSystem.class); @@ -151,29 +211,13 @@ public MainFS() { ALL.addLookupListener(this); + refreshLayers(); + } + + final void refreshLayers() { List layerUrls = new ArrayList(); - ClassLoader l = Thread.currentThread().getContextClassLoader(); try { - for (URL manifest : NbCollections.iterable(l.getResources("META-INF/MANIFEST.MF"))) { // NOI18N - InputStream is = manifest.openStream(); - try { - Manifest mani = new Manifest(is); - String layerLoc = mani.getMainAttributes().getValue("OpenIDE-Module-Layer"); // NOI18N - if (layerLoc != null) { - URL layer = l.getResource(layerLoc); - if (layer != null) { - layerUrls.add(layer); - } else { - LOG.warning("No such layer: " + layerLoc); - } - } - } finally { - is.close(); - } - } - for (URL generatedLayer : NbCollections.iterable(l.getResources("META-INF/generated-layer.xml"))) { // NOI18N - layerUrls.add(generatedLayer); - } + provideLayer(layerUrls); layers.setXmlUrls(layerUrls.toArray(new URL[layerUrls.size()])); LOG.log(Level.FINE, "Loading classpath layers: {0}", layerUrls); } catch (Exception x) { @@ -182,6 +226,33 @@ resultChanged(null); // run after add listener - see PN1 in #26338 } + private void provideLayer(List layerUrls) throws IOException { + ClassLoader l = Thread.currentThread().getContextClassLoader(); + for (URL manifest : NbCollections.iterable(l.getResources("META-INF/MANIFEST.MF"))) { // NOI18N + InputStream is = manifest.openStream(); + try { + Manifest mani = new Manifest(is); + String layerLoc = mani.getMainAttributes().getValue("OpenIDE-Module-Layer"); // NOI18N + if (layerLoc != null) { + URL layer = l.getResource(layerLoc); + if (layer != null) { + layerUrls.add(layer); + } else { + LOG.warning("No such layer: " + layerLoc); + } + } + } finally { + is.close(); + } + } + for (URL generatedLayer : NbCollections.iterable(l.getResources("META-INF/generated-layer.xml"))) { // NOI18N + layerUrls.add(generatedLayer); + } + for (LayersProvider p : Lookup.getDefault().lookupAll(LayersProvider.class)) { + p.registerLayers(layerUrls); + } + } + private static FileSystem[] computeDelegates() { List arr = new ArrayList(); arr.add(MEMORY); diff --git a/openide.filesystems/test/unit/src/org/openide/filesystems/ContentProviderTest.java b/openide.filesystems/test/unit/src/org/openide/filesystems/ContentProviderTest.java new file mode 100644 --- /dev/null +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/ContentProviderTest.java @@ -0,0 +1,95 @@ +/* + * 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. + */ +package org.openide.filesystems; + +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.netbeans.junit.MockServices; +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.Repository.LayersProvider; +import org.openide.util.Lookup; + +public class ContentProviderTest extends NbTestCase { + static { + MockServices.setServices(MyProvider.class); + } + + public ContentProviderTest(String name) { + super(name); + } + + public void testCheckAFileFromOurLayer() { + FileObject fo = FileUtil.getConfigFile("foo/bar"); + assertNotNull("foo/bar is provided", fo); + assertEquals("value is val", "val", fo.getAttribute("x")); + } + + public void testRefreshTheProvider() throws Exception { + MyProvider my = Lookup.getDefault().lookup(MyProvider.class); + assertNotNull("My provider found", my); + + my.clear(); + + FileObject fo = FileUtil.getConfigFile("foo/bar"); + assertNull("foo/bar is no longer available", fo); + + } + + public static final class MyProvider extends LayersProvider { + private boolean empty; + + @Override + protected void registerLayers(Collection context) { + if (empty) { + return; + } + context.add(ContentProviderTest.class.getResource("test-layer-attribs.xml")); + } + + final void clear() throws Exception { + empty = true; + refresh(); + } + } +}