Issue #141925: provide a simpler way to declare which layer entries override others. diff --git a/core.ide/src/org/netbeans/core/ide/resources/layer.xml b/core.ide/src/org/netbeans/core/ide/resources/layer.xml --- a/core.ide/src/org/netbeans/core/ide/resources/layer.xml +++ b/core.ide/src/org/netbeans/core/ide/resources/layer.xml @@ -92,6 +92,7 @@ the changes if appropriate --> + diff --git a/favorites/src/org/netbeans/modules/favorites/resources/layer.xml b/favorites/src/org/netbeans/modules/favorites/resources/layer.xml --- a/favorites/src/org/netbeans/modules/favorites/resources/layer.xml +++ b/favorites/src/org/netbeans/modules/favorites/resources/layer.xml @@ -135,13 +135,6 @@ - - - - - - - diff --git a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-init b/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-init deleted file mode 100644 --- a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-init +++ /dev/null @@ -1,9 +0,0 @@ -cdc-hi-init - - - - - - - - diff --git a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-run b/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-run deleted file mode 100644 --- a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/cdc-hi-run +++ /dev/null @@ -1,18 +0,0 @@ -cdc-hi-run - - - - - - - - - - - - - - - - - diff --git a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/layer.xml b/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/layer.xml --- a/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/layer.xml +++ b/j2me.cdc.project.savaje/src/org/netbeans/modules/j2me/cdc/project/savaje/resources/layer.xml @@ -9,9 +9,6 @@ - - - @@ -22,9 +19,6 @@ - - - diff --git a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-init b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-init --- a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-init +++ b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-init @@ -5,5 +5,4 @@ - - + diff --git a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-run b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-run --- a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-run +++ b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/buildscript/cdc-hi-run @@ -16,4 +16,3 @@ - diff --git a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/layer.xml b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/layer.xml --- a/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/layer.xml +++ b/mobility.project/src/org/netbeans/modules/mobility/project/ui/resources/layer.xml @@ -364,7 +364,7 @@ - + @@ -466,7 +466,7 @@ - + diff --git a/o.n.core/test/qa-functional/src/org/netbeans/core/validation/ValidateLayerConsistencyTest.java b/o.n.core/test/qa-functional/src/org/netbeans/core/validation/ValidateLayerConsistencyTest.java --- a/o.n.core/test/qa-functional/src/org/netbeans/core/validation/ValidateLayerConsistencyTest.java +++ b/o.n.core/test/qa-functional/src/org/netbeans/core/validation/ValidateLayerConsistencyTest.java @@ -86,7 +86,6 @@ import org.openide.loaders.DataObject; import org.openide.loaders.DataShadow; import org.openide.modules.Dependency; -import org.openide.modules.ModuleInfo; import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.NbCollections; @@ -477,12 +476,10 @@ assertNoErrors(errors.size() + " actions is not registered properly", errors); } - public void testIfOneFileIsDefinedTwiceByDifferentModulesTheyNeedToHaveMutualDependency() throws Exception { + public void testLayerOverrides() throws Exception { ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); assertNotNull ("In the IDE mode, there always should be a classloader", l); - // String -> List - Map> files = new HashMap>(); class ContentAndAttrs { final byte[] contents; final Map attrs; @@ -506,19 +503,15 @@ return Arrays.equals(contents, caa.contents) && attrs.equals(caa.attrs); } } - /* < FO path , { content, attributes } > */ - Map contents = new HashMap(); - /* < FO path , < module name, { content, attributes } > > */ - Map> differentContents = new HashMap>(); + Map> files = new TreeMap>(); Map>> folderAttributes = new TreeMap>>(); + Map> directDeps = new HashMap>(); StringBuffer sb = new StringBuffer(); Map hiddenFiles = new HashMap(); Set allFiles = new HashSet(); final String suffix = "_hidden"; - - boolean atLeastOne = false; Enumeration en = l.getResources("META-INF/MANIFEST.MF"); while (en.hasMoreElements ()) { URL u = en.nextElement(); @@ -535,35 +528,47 @@ } String layer = mf.getMainAttributes ().getValue ("OpenIDE-Module-Layer"); if (layer == null) { + // XXX should also consider META-INF/generated-layer.xml here continue; } + String depsS = mf.getMainAttributes().getValue("OpenIDE-Module-Module-Dependencies"); + if (depsS != null) { + Set deps = new HashSet(); + for (Dependency d : Dependency.create(Dependency.TYPE_MODULE, depsS)) { + deps.add(d.getName().replaceFirst("/.+$", "")); + } + directDeps.put(module, deps); + } - atLeastOne = true; URL base = new URL(u, "../"); URL layerURL = new URL(base, layer); - java.net.URLConnection connect = layerURL.openConnection (); + URLConnection connect = layerURL.openConnection (); connect.setDefaultUseCaches (false); FileSystem fs = new XMLFileSystem(layerURL); Enumeration all = fs.getRoot().getChildren(true); while (all.hasMoreElements ()) { FileObject fo = all.nextElement (); - String path = fo.getPath(); + String simplePath = fo.getPath(); - if (path.endsWith(suffix)) { - hiddenFiles.put(path, layerURL); + if (simplePath.endsWith(suffix)) { + hiddenFiles.put(simplePath, layerURL); } else { - allFiles.add(path); + allFiles.add(simplePath); } + Number weight = (Number) fo.getAttribute("weight"); + // XXX if weight != null, test that it is actually overriding something or being overridden + String weightedPath = weight == null ? simplePath : simplePath + "#" + weight; + Map attributes = getAttributes(fo, base); if (fo.isFolder()) { for (Map.Entry attr : attributes.entrySet()) { - Map> m1 = folderAttributes.get(path); + Map> m1 = folderAttributes.get(weightedPath); if (m1 == null) { m1 = new TreeMap>(); - folderAttributes.put(path, m1); + folderAttributes.put(weightedPath, m1); } Map m2 = m1.get(attr.getKey()); if (m2 == null) { @@ -575,103 +580,50 @@ continue; } - List list = files.get(path); - if (list == null) { - list = new ArrayList(); - files.put (path, list); - list.add (module); - contents.put(path, new ContentAndAttrs(fo.asBytes(), attributes, layerURL)); - } else { - ContentAndAttrs contentAttrs = contents.get(path); - ContentAndAttrs nue = new ContentAndAttrs(fo.asBytes(), attributes, layerURL); - if (!nue.equals(contentAttrs)) { - //System.err.println("Found differences in " + path + " between " + nue + " and " + contentAttrs); - Map diffs = differentContents.get(path); - if (diffs == null) { - diffs = new HashMap(); - differentContents.put(path, diffs); - diffs.put(list.get(0), contentAttrs); - } - diffs.put(module, nue); - list.add (module); - } + Map overrides = files.get(weightedPath); + if (overrides == null) { + overrides = new TreeMap(); + files.put(weightedPath, overrides); } + overrides.put(module, new ContentAndAttrs(fo.asBytes(), attributes, layerURL)); } // make sure the filesystem closes the stream connect.getInputStream ().close (); } - contents = null; // Not needed any more - - for (Map.Entry> e : files.entrySet()) { - List list = e.getValue(); - if (list.size() == 1) { + assertFalse("At least one layer file is usually used", allFiles.isEmpty()); + + for (Map.Entry> e : files.entrySet()) { + Map overrides = e.getValue(); + if (overrides.size() == 1) { continue; } - - Collection res = Lookup.getDefault().lookupAll(ModuleInfo.class); - assertFalse("Some modules found", res.isEmpty()); - - List list2 = new ArrayList(list); - for (String name : list) { - for (ModuleInfo info : res) { - if (name.equals (info.getCodeName ())) { - // remove dependencies - for (Dependency d : info.getDependencies()) { - list2.remove(d.getName()); - } + Set overriders = overrides.keySet(); + String file = e.getKey(); + + if (new HashSet(overrides.values()).size() == 1) { + // All the same. Check whether these are parallel declarations (e.g. CND debugger vs. Java debugger), or vertical. + for (String overrider : overriders) { + Set deps = new HashSet(directDeps.get(overrider)); + deps.retainAll(overriders); + if (!deps.isEmpty()) { + sb.append(file).append(" is pointlessly overridden in ").append(overrider). + append(" relative to ").append(deps.iterator().next()).append('\n'); } } - } - // ok, modules depend on each other - if (list2.size() <= 1) { continue; } - - sb.append (e.getKey ()).append( " is provided by: " ).append(list).append('\n'); - Map diffList = differentContents.get(e.getKey()); - if (diffList != null) { - if (list.size() == 2) { - String module1 = list.get(0); - String module2 = list.get(1); - ContentAndAttrs contentAttrs1 = diffList.get(module1); - ContentAndAttrs contentAttrs2 = diffList.get(module2); - if (!Arrays.equals(contentAttrs1.contents, contentAttrs2.contents)) { - sb.append(' ').append(module1).append(": content = '").append(new String(contentAttrs1.contents)).append('\n'); - sb.append(' ').append(module2).append(": content = '").append(new String(contentAttrs2.contents)).append('\n'); - } - if (!contentAttrs1.attrs.equals(contentAttrs2.attrs)) { - Map attr1 = contentAttrs1.attrs; - Map attr2 = contentAttrs2.attrs; - Set keys = new HashSet(attr1.keySet()); - keys.retainAll(attr2.keySet()); - for (String attribute : keys) { - Object value1 = attr1.get(attribute); - Object value2 = attr2.get(attribute); - if (value1 == value2 || (value1 != null && value1.equals(value2))) { - // Remove the common attributes so that just the differences show up - attr1.remove(attribute); - attr2.remove(attribute); - } - } - sb.append(' ').append(module1).append(": different attributes = '").append(contentAttrs1.attrs).append('\n'); - sb.append(' ').append(module2).append(": different attributes = '").append(contentAttrs2.attrs).append('\n'); - } - } else { - for (String module : list) { - ContentAndAttrs contentAttrs = diffList.get(module); - sb.append(" ").append(module).append(": content = '").append(new String(contentAttrs.contents)). - append("', attributes = ").append(contentAttrs.attrs).append("\n"); - } - } + + sb.append(file).append(" is provided by: ").append(overriders).append('\n'); + for (Map.Entry entry : overrides.entrySet()) { + ContentAndAttrs contentAttrs = entry.getValue(); + sb.append(" ").append(entry.getKey()).append(": content = '").append(new String(contentAttrs.contents)). + append("', attributes = ").append(contentAttrs.attrs).append("\n"); } } - assertTrue ("At least one layer file is usually used", atLeastOne); - for (Map.Entry>> entry1 : folderAttributes.entrySet()) { for (Map.Entry> entry2 : entry1.getValue().entrySet()) { if (new HashSet(entry2.getValue().values()).size() > 1) { - // XXX currently do not check if the modules are unrelated by dependency. sb.append("Some modules conflict on the definition of ").append(entry2.getKey()).append(" for "). append(entry1.getKey()).append(": ").append(entry2.getValue()).append("\n"); } @@ -679,7 +631,7 @@ } if (sb.length () > 0) { - fail ("Some modules override their files and do not depend on each other\n" + sb); + fail("Some modules override some files without using the weight attribute correctly\n" + sb); } diff --git a/openide.filesystems/apichanges.xml b/openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml +++ b/openide.filesystems/apichanges.xml @@ -46,6 +46,60 @@ Filesystems API + + + Ability to specify "weight" for MultiFileSystem overrides + + + + +

+ Modules need no longer declare runtime-only dependencies + on other modules merely to override their layer entries. + Instead, they should specify a higher weight. + (Normally the base module will declare no weight, so any + positive number will do.) +

+
+ +

+ MultiFileSystems will now interpret a special + file attribute weight to determine how to + resolve otherwise ambiguous overrides. For example, in the + system filesystem, module XML layers can use this attribute. + Suppose a generic infrastructure module declares: +

+
+<filesystem>
+    <folder name="my-snippets">
+        <file name="common.xml" url="generic-snippet.xml"/>
+    </folder>
+</filesystem>
+                
+

+ If another module wishes to override this declaration, it + can do so by specifying: +

+
+<filesystem>
+    <folder name="my-snippets">
+        <file name="common.xml" url="special-snippet.xml">
+            <attribute name="weight" intvalue="100"/>
+        </file>
+    </folder>
+</filesystem>
+                
+

+ This override will work even if the module system happens + to load the specializing module before the infrastructure + module (as could happen if there is no module dependency + between them). The weight attribute also makes it clear that + something is being overridden. +

+
+ + +
Effective constructor for JarFileSystem 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.35 +OpenIDE-Module-Specification-Version: 7.36 diff --git a/openide.filesystems/src/org/openide/filesystems/MultiFileObject.java b/openide.filesystems/src/org/openide/filesystems/MultiFileObject.java --- a/openide.filesystems/src/org/openide/filesystems/MultiFileObject.java +++ b/openide.filesystems/src/org/openide/filesystems/MultiFileObject.java @@ -60,6 +60,8 @@ import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; import org.openide.util.NbBundle; /** Implementation of the file object for multi file system. @@ -75,6 +77,7 @@ /** default path separator */ private static final char PATH_SEP = '/'; + private static final String WEIGHT_ATTRIBUTE = "weight"; // NOI18N private static final FileSystem.AtomicAction markAtomicAction = new FileSystem.AtomicAction() { public void run() { } @@ -168,9 +171,11 @@ Set now = (delegates == null) ? Collections.EMPTY_SET : delegates; Set del = new HashSet(arr.length * 2); + Number maxWeight = 0; FileObject led = null; String name = getPath(); + FileSystem writable = mfs.writableLayer(name); for (int i = 0; i < arr.length; i++) { if (arr[i] != null) { @@ -184,8 +189,12 @@ fo.addFileChangeListener(weakL); } - if ((led == null) && fo.isValid()) { - led = fo; + if (fo.isValid()) { + Number weight = weightOf(fo, writable); + if (led == null || weight.doubleValue() > maxWeight.doubleValue()) { + led = fo; + maxWeight = weight; + } } } } @@ -297,6 +306,10 @@ private FileObject findLeader(FileSystem[] fs, String path) { MultiFileSystem mfs = getMultiFileSystem(); + Number maxWeight = 0; + FileObject _leader = null; + FileSystem writable = mfs.writableLayer(path); + for (FileSystem f : fs) { if (f == null) { continue; @@ -304,11 +317,36 @@ FileObject fo = mfs.findResourceOn(f, path); if (fo != null) { - return fo; + Number weight = weightOf(fo, writable); + if (_leader == null || weight.doubleValue() > maxWeight.doubleValue()) { + _leader = fo; + maxWeight = weight; + } } } - return null; + return _leader; + } + + private static Number weightOf(FileObject f, FileSystem writable) { + try { + if (f.getFileSystem() == writable) { + return Double.MAX_VALUE; + } + } catch (FileStateInvalidException x) {/* ignore */} + Object weight = f.getAttribute(WEIGHT_ATTRIBUTE); + if (weight instanceof Number) { + return (Number) weight; + } else if (weight == null) { + return 0; + } else { + try { + Logger.getLogger(MultiFileObject.class.getName()).log( + Level.WARNING, "File {0} in {1} has nonnumeric weight {2} of type {3}", + new Object[] {f.getPath(), f.getFileSystem(), weight, weight.getClass().getName()}); + } catch (FileStateInvalidException x) {/* ignore */} + return 0; + } } /** Getter for the right file system */ @@ -774,6 +812,10 @@ FileSystem[] systems = getMultiFileSystem().getDelegates(); + Number maxWeight = 0; + Object attr = null; + FileSystem writable = getMultiFileSystem().writableLayer(path); + // boolean isLoaderAttr = /* DataObject.EA_ASSIGNED_LOADER */ "NetBeansAttrAssignedLoader".equals (attrName); // NOI18N for (int i = 0; i < systems.length; i++) { if (systems[i] == null) { @@ -793,7 +835,11 @@ Object o = getAttribute(fo, attrName, fo.getPath()); // Performance tricks: if (o != null) { - return devoidify(o); + Number weight = weightOf(fo, writable); + if (attr == null || weight.doubleValue() > maxWeight.doubleValue()) { + attr = o; + maxWeight = weight; + } } } @@ -807,12 +853,16 @@ Object o = getAttribute(fo, prefixattr, ""); // NOI18N if (o != null) { - return devoidify(o); + Number weight = weightOf(fo, writable); + if (attr == null || weight.doubleValue() > maxWeight.doubleValue()) { + attr = o; + maxWeight = weight; + } } } } - return null; + return devoidify(attr); } private static boolean sameFullName(FileObject f1, FileObject f2) { diff --git a/openide.filesystems/src/org/openide/filesystems/MultiFileSystem.java b/openide.filesystems/src/org/openide/filesystems/MultiFileSystem.java --- a/openide.filesystems/src/org/openide/filesystems/MultiFileSystem.java +++ b/openide.filesystems/src/org/openide/filesystems/MultiFileSystem.java @@ -61,10 +61,19 @@ * *

This filesystem has no form of storage in and of itself. Rather, it composes and proxies one or more * "delegate" filesystems. The result is that of a "layered" sandwich of filesystems, each able to provide files - * to appear in the merged result. The layers are ordered so that a filesystem in "front" can override one in - * "back". Often the frontmost layer will be writable, and all changes to the filesystem are sent to this layer, + * to appear in the merged result. + * Often the frontmost layer will be writable, and all changes to the filesystem are sent to this layer, * but that behavior is configurable. * + *

The layers are ordered so that entries in a filesystem in "front" can override one in "back". + * Since it is often not straightforward to arrange layers so that particular overrides work, + * as of org.openide.filesystems 7.36 + * you may set the special file attribute {@code weight} to any {@link Number} on a layer entry. + * (If unspecified, the implicit default value is zero.) + * A variant with a higher weight will override one with a lower weight even if it is further back. + * (The exception is that entries in a writable frontmost layer always override other layers, + * regardless of weight.) + * *

Creating a new MultiFileSystem is easy in the simplest cases: just call {@link * #MultiFileSystem(FileSystem[])} and pass a list of delegates. If you pass it only read-only delegates, the * composite will also be read-only. Or you may pass it one or more writable filesystems (make sure the first @@ -448,6 +457,15 @@ return systems[WRITE_SYSTEM_INDEX]; } + FileSystem writableLayer(String path) { + try { + return createWritableOn(path); + } catch (IOException x) { + // ignore + return systems.length > WRITE_SYSTEM_INDEX ? systems[WRITE_SYSTEM_INDEX] : null; + } + } + /** Special case of createWritableOn (@see #createWritableOn). * * @param oldName original name of the file (full) @@ -555,6 +573,7 @@ Enumeration delegates(final String name) { Enumeration en = Enumerations.array(systems); + // XXX order (stably) by weight class Resources implements Enumerations.Processor { public @Override FileObject process(FileSystem fs, Collection ignore) { if (fs == null) { diff --git a/openide.filesystems/test/unit/src/org/openide/filesystems/MultiFileSystemMaskTest.java b/openide.filesystems/test/unit/src/org/openide/filesystems/MultiFileSystemMaskTest.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/MultiFileSystemMaskTest.java +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/MultiFileSystemMaskTest.java @@ -41,11 +41,13 @@ package org.openide.filesystems; +import java.beans.PropertyVetoException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.test.TestFileUtils; // XXX should only *unused* mask files be listed when propagateMasks? // XXX write similar test for ParsingLayerCacheManager (simulate propagateMasks) @@ -249,6 +251,64 @@ // XXX test create -> mask -> recreate in same MFS + @SuppressWarnings("deprecation") // for debugging only + private static void setSystemName(FileSystem fs, String s) throws PropertyVetoException { + fs.setSystemName(s); + } + public void testWeightedOverrides() throws Exception { // #141925 + FileSystem wr = FileUtil.createMemoryFileSystem(); + setSystemName(wr, "wr"); + FileSystem fs1 = FileUtil.createMemoryFileSystem(); + setSystemName(fs1, "fs1"); + FileObject f = TestFileUtils.writeFile(fs1.getRoot(), "d/f", "1"); + f.setAttribute("a", 1); + FileSystem fs2 = FileUtil.createMemoryFileSystem(); + setSystemName(fs2, "fs2"); + f = TestFileUtils.writeFile(fs2.getRoot(), "d/f", "2"); + f.setAttribute("a", 2); + // Test behavior with no weights: first layer wins. + FileSystem mfs = new MultiFileSystem(new FileSystem[] {wr, fs1, fs2}); + f = mfs.findResource("d/f"); + assertEquals(1, f.getAttribute("a")); + assertEquals("1", f.asText()); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs2, fs1}); + f = mfs.findResource("d/f"); + assertEquals(2, f.getAttribute("a")); + assertEquals("2", f.asText()); + // Now test that weighted layer wins over unweighted regardless of order. + fs2.findResource("d/f").setAttribute("weight", 100); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs1, fs2}); + f = mfs.findResource("d/f"); + assertEquals(2, f.getAttribute("a")); + assertEquals("2", f.asText()); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs2, fs1}); + f = mfs.findResource("d/f"); + assertEquals(2, f.getAttribute("a")); + assertEquals("2", f.asText()); + // And that a higher weight beats a lower weight. + fs1.findResource("d/f").setAttribute("weight", 200); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs1, fs2}); + f = mfs.findResource("d/f"); + assertEquals(1, f.getAttribute("a")); + assertEquals("1", f.asText()); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs2, fs1}); + f = mfs.findResource("d/f"); + assertEquals(1, f.getAttribute("a")); + assertEquals("1", f.asText()); + // Now test writable layer which should always win regardless of weights. + mfs = new MultiFileSystem(new FileSystem[] {wr, fs1, fs2}); + f = mfs.findResource("d/f"); + f.setAttribute("a", 0); + TestFileUtils.writeFile(mfs.getRoot(), "d/f", "0"); + f = wr.findResource("d/f"); + // Oddly, it is null: assertEquals(0, f.getAttribute("a")); + assertEquals("0", f.asText()); + mfs = new MultiFileSystem(new FileSystem[] {wr, fs1, fs2}); + f = mfs.findResource("d/f"); + assertEquals(0, f.getAttribute("a")); + assertEquals("0", f.asText()); + } + public void testMultipleMaskLayers() throws Exception { MultiFileSystem fs = new MultiFileSystem(new FileSystem[] { TestUtilHid.createXMLFileSystem(getName() + "3", new String[] { diff --git a/projectui/src/org/netbeans/modules/project/ui/resources/layer.xml b/projectui/src/org/netbeans/modules/project/ui/resources/layer.xml --- a/projectui/src/org/netbeans/modules/project/ui/resources/layer.xml +++ b/projectui/src/org/netbeans/modules/project/ui/resources/layer.xml @@ -225,9 +225,9 @@ - + @@ -246,7 +246,9 @@ - + + + diff --git a/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/resources/layer.xml b/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/resources/layer.xml --- a/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/resources/layer.xml +++ b/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/resources/layer.xml @@ -15,12 +15,6 @@ - - - - - - diff --git a/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/layer.xml b/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/layer.xml --- a/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/layer.xml +++ b/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/layer.xml @@ -20,11 +20,6 @@ - - - - - diff --git a/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/resources/SessionKeyAuthenticator.template b/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/resources/SessionKeyAuthenticator.template deleted file mode 100644 --- a/websvc.saas.codegen.j2ee/src/org/netbeans/modules/websvc/saas/codegen/j2ee/resources/SessionKeyAuthenticator.template +++ /dev/null @@ -1,85 +0,0 @@ -<#-- FreeMarker template (see http://freemarker.org/) --> -<#assign licenseFirst = "/*"> -<#assign licensePrefix = " * "> -<#assign licenseLast = " */"> -<#include "../Licenses/license-${project.license}.txt"> - -<#if package?? && package != ""> -package ${package}; - - -import java.io.IOException; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeMap; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.netbeans.saas.RestConnection; - -/** - * - * @author ${user} - */ -public class ${name} { - - private static String apiKey; - private static String secret; - - static { - try { - Properties props = new Properties(); - props.load(${name}.class.getResourceAsStream( - "profile.properties")); - apiKey = props.getProperty("api_key"); - secret = props.getProperty("secret"); - } catch (IOException ex) { - Logger.getLogger(${name}.class.getName()).log(Level.SEVERE, null, ex); - } - } - - public static String getApiKey() { - return apiKey; - } - - public static String sign(String[][] params) { - return sign(secret, params); - } - - private static String sign(String secret, - String[][] params) { - - try { - TreeMap map = new TreeMap(); - - for (int i = 0; i < params.length; i++) { - String key = params[i][0]; - String value = params[i][1]; - - if (value != null) { - map.put(key, URLEncoder.encode(value, "UTF-8")); - } - } - - String signature = ""; - Set> entrySet = map.entrySet(); - for (Map.Entry entry : entrySet) { - signature += entry.getKey() + "=" + entry.getValue(); - } - signature += secret; - - MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] sum = md.digest(signature.getBytes("UTF-8")); - BigInteger bigInt = new BigInteger(1, sum); - - return bigInt.toString(16); - } catch (Exception ex) { - Logger.getLogger(${name}.class.getName()).log(Level.SEVERE, null, ex); - } - - return null; - } -}