diff -r 2d9e48ea2b00 core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java --- a/core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java Wed Apr 28 11:52:13 2010 +0200 +++ b/core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java Wed Apr 28 12:42:54 2010 +0200 @@ -376,6 +376,14 @@ attr = attrs.get(attrName.substring(6)); return attr == null ? null : attr.getType(this); } + if (attr == null && attrName.startsWith("raw:")) { // NOI18N + attr = attrs.get(attrName.substring(4)); + try { + return attr == null || attr.index != 10 ? null : attr.methodValue(attr.value, this, attrName).getMethod(); + } catch (Exception ex) { + return null; + } + } if (attr == null && attrName.equals("layers")) { // NOI18N return getLayersAttr(); } diff -r 2d9e48ea2b00 openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/apichanges.xml Wed Apr 28 12:42:54 2010 +0200 @@ -46,6 +46,26 @@ Filesystems API + + + setAttribute("methodvalue:attrname", method) + + + + + +

+ You can use prefix "methodvalue:" to set + an attribute of type Method. + When the attribute is queried (without the prefix), the + method is called as is common in + XMLFileSystem + attributes. +

+
+ + +
Interruptable addRecursiveListener diff -r 2d9e48ea2b00 openide.filesystems/manifest.mf --- a/openide.filesystems/manifest.mf Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/manifest.mf Wed Apr 28 12:42:54 2010 +0200 @@ -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.38 +OpenIDE-Module-Specification-Version: 7.39 diff -r 2d9e48ea2b00 openide.filesystems/src/org/openide/filesystems/AbstractFileObject.java --- a/openide.filesystems/src/org/openide/filesystems/AbstractFileObject.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/AbstractFileObject.java Wed Apr 28 12:42:54 2010 +0200 @@ -324,7 +324,7 @@ /** performance hack */ final Object getAttribute(String attrName, String path) { - return getAbstractFileSystem().attr.readAttribute(path, attrName); + return XMLMapAttr.readAttribute(this, getAbstractFileSystem().attr, path, attrName); } /* Set the file attribute with the specified name. diff -r 2d9e48ea2b00 openide.filesystems/src/org/openide/filesystems/DefaultAttributes.java --- a/openide.filesystems/src/org/openide/filesystems/DefaultAttributes.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/DefaultAttributes.java Wed Apr 28 12:42:54 2010 +0200 @@ -67,6 +67,7 @@ import java.util.TreeSet; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; +import org.openide.filesystems.AbstractFileSystem.Attr; import org.openide.util.Enumerations; import org.openide.util.NbBundle; import org.openide.util.Utilities; diff -r 2d9e48ea2b00 openide.filesystems/src/org/openide/filesystems/FileUtil.java --- a/openide.filesystems/src/org/openide/filesystems/FileUtil.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/FileUtil.java Wed Apr 28 12:42:54 2010 +0200 @@ -49,6 +49,7 @@ import java.io.OutputStream; import java.io.SyncFailedException; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; @@ -68,6 +69,7 @@ import java.util.StringTokenizer; import java.util.WeakHashMap; import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.logging.Level; @@ -1088,14 +1090,19 @@ continue; } - Object value = source.getAttribute(key); + AtomicBoolean isRawValue = new AtomicBoolean(); + Object value = XMLMapAttr.getRawAttribute(source, key, isRawValue); // #132801 and #16761 - don't set attributes where value is // instance of VoidValue because these attributes were previously written // by mistake in code. So it should happen only if you import some // settings from old version. if (value != null && !(value instanceof MultiFileObject.VoidValue)) { - dest.setAttribute(key, value); + if (isRawValue.get() && value instanceof Method) { + dest.setAttribute("methodvalue:" + key, value); // NOI18N + } else { + dest.setAttribute(key, value); + } } } } diff -r 2d9e48ea2b00 openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java --- a/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Wed Apr 28 12:42:54 2010 +0200 @@ -58,6 +58,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicBoolean; import org.openide.util.SharedClassObject; import org.openide.util.Utilities; import org.openide.util.io.NbMarshalledObject; @@ -146,6 +147,29 @@ return new Attr(index, value); } + static Object getRawAttribute(FileObject fo, String name, AtomicBoolean ab) { + Object raw = fo.getAttribute("raw:" + name); // NOI18N + if (raw != null) { + if (ab != null) { + ab.set(true); + } + return raw; + } + if (ab != null) { + ab.set(false); + } + return fo.getAttribute(name); + } + private static ThreadLocal ATTR_FOR = new ThreadLocal(); + static Object readAttribute(FileObject forFO, AbstractFileSystem.Attr attr, String path, String attrName) { + FileObject prev = ATTR_FOR.get(); + try { + ATTR_FOR.set(forFO); + return attr.readAttribute(path, attrName); + } finally { + ATTR_FOR.set(prev); + } + } /** According to name of attribute returns attribute as object * @param p1 is name of attribute * @return attribute, which is hold in XMLMapAttr.Attr or null if such attribute doesn`t exist or isn`t able to construct form String representation @@ -183,7 +207,7 @@ /** implementation of Map.get. But fires Exception to have chance in * DefaultAttributes to catch and annotate*/ Object getAttribute(Object attrName) throws Exception { - return getAttribute(attrName, null); + return getAttribute(attrName, new Object[] { ATTR_FOR.get(), attrName }); } private Object getAttribute(Object attrName, Object[] params) @@ -201,6 +225,11 @@ if (attr == null && origAttrName.startsWith("class:")) { // NOI18N attr = (Attr) map.get(origAttrName.substring(6)); retVal = attr != null ? attr.getType(params) : null; + } else if (attr == null && origAttrName.startsWith("raw:")) { // NOI18N + attr = (Attr) map.get(origAttrName.substring(4)); + if (attr != null && attr.keyIndex == 9) { + return attr.methodValue(attr.value, params).getMethod(); + } } else { try { retVal = (attr == null) ? attr : attr.get(params); @@ -241,8 +270,18 @@ Object[] keyValuePair = ModifiedAttribute.translateInto((String) p1, p2); String key = (String) keyValuePair[0]; Object value = keyValuePair[1]; - Object toStore = ((value == null) || value instanceof Attr) ? value : new Attr(value); - + Object toStore; + if (value == null) { + toStore = null; + } else if (value instanceof Attr) { + toStore = value; + } else if (value instanceof Method && key.startsWith("methodvalue:")) { // NOI18N + Method m = (Method)value; + key = key.substring("methodvalue:".length()); // NOI18N + toStore = new Attr("methodvalue", m.getDeclaringClass().getName() + '.' + m.getName()); // NOI18N + } else { + toStore = new Attr(value); + } if (decode) { key = Attr.decode(key).intern(); } @@ -618,19 +657,11 @@ } /** - * Constructs new attribute as Object. Used for static creation from literal or serialValue. - * @return new attribute as Object - */ - private Object get() throws Exception { - return getObject(null); //getObject is ready to aobtain null - } - - /** * Constructs new attribute as Object. Used for dynamic creation: methodvalue . * @param objs has sense only for methodvalue invocation; and only 2 parametres will be used *@return new attribute as Object */ - private Object get(Object[] objs) throws Exception { + final Object get(Object[] objs) throws Exception { return getObject(objs); } diff -r 2d9e48ea2b00 openide.filesystems/test/unit/src/org/openide/filesystems/AttributesTestHidden.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/AttributesTestHidden.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/AttributesTestHidden.java Wed Apr 28 12:42:54 2010 +0200 @@ -44,6 +44,8 @@ import java.util.*; import java.io.*; +import java.lang.reflect.Method; +import org.xml.sax.SAXException; /** * @@ -281,6 +283,52 @@ assertTrue (TEST_ERR,testedFS != null); }*/ + public void testFileUtilCopyAttributes() throws Exception { + assertTrue(TEST_ERR, testedFS != null); + if (testedFS.isReadOnly()) { + return; + } + + File f = new File(getWorkDir(), "sample.xml"); + FileOutputStream fos = new FileOutputStream(f); + fos.write(("" + + "" + + "" + + "" + + "" + + "" + + " " + + " " + + "" + ).getBytes()); + fos.close(); + + XMLFileSystem xfs = new XMLFileSystem(f.toURI().toURL()); + FileObject template = xfs.findResource("Templates/Other/special"); + assertNotNull("template found", template); + FileObject foTested = testedFS.getRoot().createData("copiedTemplate"); + FileUtil.copyAttributes(template, foTested); + assertEquals("template copied too", Boolean.TRUE, foTested.getAttribute("temp")); + assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii")); + } + + public static String hello(FileObject obj, String attr) { + return "Hello " + attr + "@" + obj.getNameExt(); + } + + public void testSetMethodGetResult() throws Exception { + assertTrue(TEST_ERR, testedFS != null); + if (testedFS.isReadOnly()) { + return; + } + + FileObject foTested = testedFS.getRoot().createData("copiedTemplate"); + Method m = AttributesTestHidden.class.getDeclaredMethod("hello", FileObject.class, String.class); + foTested.setAttribute("methodvalue:ii", m); + + assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii")); + } + } diff -r 2d9e48ea2b00 openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Wed Apr 28 11:52:13 2010 +0200 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Wed Apr 28 12:42:54 2010 +0200 @@ -47,6 +47,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.File; +import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; @@ -781,7 +782,36 @@ assertAttr("Imutable value is still nochange", nochange, "value", "nochange"); assertEquals("No change in this attribute: " + no.events, 0, no.events.size()); - } + } + + public void testFileUtilCopyAttributesOnOwnLayer() throws Exception { + File f = new File(getWorkDir(), "sample.xml"); + FileOutputStream fos = new FileOutputStream(f); + fos.write(("" + + "" + + "" + + "" + + "" + + "" + + " " + + " " + + "" + ).getBytes()); + fos.close(); + + File r = new File(getWorkDir(), "root"); + r.mkdirs(); + LocalFileSystem target = new LocalFileSystem(); + target.setRootDirectory(r); + + FileSystem source = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURI().toURL()); + FileObject template = source.findResource("Templates/Other/special"); + assertNotNull("template found", template); + FileObject foTested = target.getRoot().createData("copiedTemplate"); + FileUtil.copyAttributes(template, foTested); + assertEquals("template copied too", Boolean.TRUE, foTested.getAttribute("temp")); + assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii")); + } private static Image icon;