This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 120724
Collapse All | Expand All

(-)a/core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java (+14 lines)
Lines 372-377 Link Here
372
        // Attributes implementation:
372
        // Attributes implementation:
373
373
374
        /** Get the file attribute with the specified name. */
374
        /** Get the file attribute with the specified name. */
375
        @Override
375
        public Object getAttribute(String attrName) {
376
        public Object getAttribute(String attrName) {
376
            initialize();
377
            initialize();
377
            AttrImpl attr = attrs.get(attrName);
378
            AttrImpl attr = attrs.get(attrName);
Lines 379-384 Link Here
379
                attr = attrs.get(attrName.substring(6));
380
                attr = attrs.get(attrName.substring(6));
380
                return attr == null ? null : attr.getType(this);
381
                return attr == null ? null : attr.getType(this);
381
            }
382
            }
383
            if (attr == null && attrName.startsWith("raw:")) { // NOI18N
384
                attr = attrs.get(attrName.substring(4));
385
                try {
386
                    if (attr != null && attr.index == 10) {
387
                        return attr.methodValue(attr.value, this, attrName).getMethod();
388
                    }
389
                    if (attr != null && attr.index == 11) {
390
                        return attr.getType(this);
391
                    }
392
                } catch (Exception ex) {
393
                }
394
                return null;
395
            }
382
            if (attr == null && attrName.equals("layers")) { // NOI18N
396
            if (attr == null && attrName.equals("layers")) { // NOI18N
383
                return getLayersAttr();
397
                return getLayersAttr();
384
            }
398
            }
(-)a/openide.filesystems/apichanges.xml (+22 lines)
Lines 49-54 Link Here
49
        <apidef name="filesystems">Filesystems API</apidef>
49
        <apidef name="filesystems">Filesystems API</apidef>
50
    </apidefs>
50
    </apidefs>
51
    <changes>
51
    <changes>
52
        <change id="attribute.methodvalue">
53
            <api name="filesystems"/>
54
            <summary>setAttribute("methodvalue:attrname", method) and "newvalue:"</summary>
55
            <version major="7" minor="43"/>
56
            <date day="24" month="11" year="2010"/>
57
            <author login="jtulach"/>
58
            <compatibility addition="yes"/>
59
            <description>
60
                <p>
61
                    You can use prefix <code>"methodvalue:"</code> to set
62
                    an attribute of type <a href="@JDK@/java/lang/reflect/Method.html">Method</a>.
63
                    When the attribute is queried (without the prefix), the
64
                    method is called as is common in
65
                    <a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">XMLFileSystem</a>
66
                    attributes. You can also use <code>newvalue:</code> prefix
67
                    for attribute of type 
68
                    <a href="@JDK@/java/lang/Class.html">Class</a>.
69
                </p>
70
            </description>
71
            <class package="org.openide.filesystems" name="FileUtil"/>
72
            <issue number="120724"/>
73
        </change>
52
        <change id="createAndOpen">
74
        <change id="createAndOpen">
53
            <api name="filesystems"/>
75
            <api name="filesystems"/>
54
            <summary>FileObject.createAndOpen</summary>
76
            <summary>FileObject.createAndOpen</summary>
(-)a/openide.filesystems/arch.xml (-1 / +21 lines)
Lines 454-464 Link Here
454
        </question>
454
        </question>
455
-->
455
-->
456
<answer id="exec-reflection">
456
<answer id="exec-reflection">
457
Yes, attributes can contain also dynamic values associated with keys (<code>methodvalue</code> and <code>newvalue</code>).
457
<api type="export" group="layer" category="stable" name="methodvalue-newvalue">
458
Many <a href="@TOP@/org/openide/filesystems/FileSystem.html">FileSystem</a>
459
implementations support special form of arguments for their
460
<code>setAttribute</code> method. One can use 
461
prefix <code>methodvalue:</code> or <code>newvalue</code>
462
to store references to 
463
<a href="@JDK@/java/lang/reflect/Method.html">Method</a> or
464
<a href="@JDK@/java/lang/Class.html">Class</a> respectively. The 
465
<code>getAttribute</code> then behaves like 
466
<a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">XMLFileSystem</a>'s
467
<code>methodvalue</code> and <code>newvalue</code> attributes:
458
<ul>
468
<ul>
459
<li><a href="http://www.netbeans.org/dtds/attributes-1_0.dtd"><code>"-//NetBeans//DTD DefaultAttributes 1.0//EN"</code></a></li>
469
<li><a href="http://www.netbeans.org/dtds/attributes-1_0.dtd"><code>"-//NetBeans//DTD DefaultAttributes 1.0//EN"</code></a></li>
460
<li><a href="http://www.netbeans.org/dtds/filesystem-1_0.dtd"><code>"-//NetBeans//DTD Filesystem 1.0//EN"</code></a></li>           
470
<li><a href="http://www.netbeans.org/dtds/filesystem-1_0.dtd"><code>"-//NetBeans//DTD Filesystem 1.0//EN"</code></a></li>           
461
</ul>
471
</ul>
472
</api>
473
474
<api type="export" group="layer" category="private" name="raw-value">
475
It is possible to prefix call to <a href="@TOP@/org/openide/filesystems/FileObject.html">FileObject</a>.<code>getAttribute</code>
476
with <code>raw:</code> prefix to evaluate the attribute without instantiating it
477
(e.g. get <a href="@JDK@/java/lang/reflect/Method.html">Method</a> or
478
<a href="@JDK@/java/lang/Class.html">Class</a> values from
479
<code>methodvalue</code> and <code>newvalue</code> attributes. This API
480
is not intended for public use at present and can change in future.
481
</api>
462
 </answer>
482
 </answer>
463
483
464
484
(-)a/openide.filesystems/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.openide.filesystems
2
OpenIDE-Module: org.openide.filesystems
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
5
OpenIDE-Module-Specification-Version: 7.42
5
OpenIDE-Module-Specification-Version: 7.43
6
6
(-)a/openide.filesystems/src/org/openide/filesystems/AbstractFileObject.java (-2 / +2 lines)
Lines 327-333 Link Here
327
327
328
    /** performance hack */
328
    /** performance hack */
329
    final Object getAttribute(String attrName, String path) {
329
    final Object getAttribute(String attrName, String path) {
330
        return getAbstractFileSystem().attr.readAttribute(path, attrName);
330
        return XMLMapAttr.readAttribute(this, getAbstractFileSystem().attr, path, attrName);
331
    }
331
    }
332
332
333
    /* Set the file attribute with the specified name.
333
    /* Set the file attribute with the specified name.
Lines 348-354 Link Here
348
        Object oldValue = null;
348
        Object oldValue = null;
349
349
350
        //FileSystem fs = getAbstractFileSystem ();
350
        //FileSystem fs = getAbstractFileSystem ();
351
        //if (fs.isReadOnly()) 
351
        //if (fs.isReadOnly()) XMLFileSystemTestHid.java:934
352
        //  throw new FSException(NbBundle.getMessage(AbstractFileObject.class, "EXC_FSisRO", fs.getDisplayName ()); // NOI18N
352
        //  throw new FSException(NbBundle.getMessage(AbstractFileObject.class, "EXC_FSisRO", fs.getDisplayName ()); // NOI18N
353
        if (fire) {
353
        if (fire) {
354
            oldValue = getAttribute(attrName);
354
            oldValue = getAttribute(attrName);
(-)a/openide.filesystems/src/org/openide/filesystems/DefaultAttributes.java (+1 lines)
Lines 70-75 Link Here
70
import java.util.TreeSet;
70
import java.util.TreeSet;
71
import javax.xml.parsers.FactoryConfigurationError;
71
import javax.xml.parsers.FactoryConfigurationError;
72
import javax.xml.parsers.ParserConfigurationException;
72
import javax.xml.parsers.ParserConfigurationException;
73
import org.openide.filesystems.AbstractFileSystem.Attr;
73
import org.openide.util.Enumerations;
74
import org.openide.util.Enumerations;
74
import org.openide.util.NbBundle;
75
import org.openide.util.NbBundle;
75
import org.openide.util.Utilities;
76
import org.openide.util.Utilities;
(-)a/openide.filesystems/src/org/openide/filesystems/FileUtil.java (-2 / +11 lines)
Lines 54-59 Link Here
54
import java.lang.ref.Reference;
54
import java.lang.ref.Reference;
55
import java.lang.ref.SoftReference;
55
import java.lang.ref.SoftReference;
56
import java.lang.ref.WeakReference;
56
import java.lang.ref.WeakReference;
57
import java.lang.reflect.Method;
57
import java.net.MalformedURLException;
58
import java.net.MalformedURLException;
58
import java.net.URI;
59
import java.net.URI;
59
import java.net.URL;
60
import java.net.URL;
Lines 74-79 Link Here
74
import java.util.WeakHashMap;
75
import java.util.WeakHashMap;
75
import java.util.concurrent.Callable;
76
import java.util.concurrent.Callable;
76
import java.util.concurrent.ConcurrentHashMap;
77
import java.util.concurrent.ConcurrentHashMap;
78
import java.util.concurrent.atomic.AtomicBoolean;
77
import java.util.jar.JarEntry;
79
import java.util.jar.JarEntry;
78
import java.util.jar.JarInputStream;
80
import java.util.jar.JarInputStream;
79
import java.util.logging.Level;
81
import java.util.logging.Level;
Lines 1101-1114 Link Here
1101
                continue;
1103
                continue;
1102
            }
1104
            }
1103
1105
1104
            Object value = source.getAttribute(key);
1106
            AtomicBoolean isRawValue = new AtomicBoolean();
1107
            Object value = XMLMapAttr.getRawAttribute(source, key, isRawValue);
1105
1108
1106
            // #132801 and #16761 - don't set attributes where value is 
1109
            // #132801 and #16761 - don't set attributes where value is 
1107
            // instance of VoidValue because these attributes were previously written 
1110
            // instance of VoidValue because these attributes were previously written 
1108
            // by mistake in code. So it should happen only if you import some
1111
            // by mistake in code. So it should happen only if you import some
1109
            // settings from old version.
1112
            // settings from old version.
1110
            if (value != null && !(value instanceof MultiFileObject.VoidValue)) {
1113
            if (value != null && !(value instanceof MultiFileObject.VoidValue)) {
1111
                dest.setAttribute(key, value);
1114
                if (isRawValue.get() && value instanceof Method) {
1115
                    dest.setAttribute("methodvalue:" + key, value); // NOI18N
1116
                } else if (isRawValue.get() && value instanceof Class) {
1117
                    dest.setAttribute("newvalue:" + key, value); // NOI18N
1118
                } else {
1119
                    dest.setAttribute(key, value);
1120
                }
1112
            }
1121
            }
1113
        }
1122
        }
1114
    }
1123
    }
(-)a/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java (-17 / +59 lines)
Lines 61-66 Link Here
61
import java.util.Set;
61
import java.util.Set;
62
import java.util.SortedSet;
62
import java.util.SortedSet;
63
import java.util.TreeSet;
63
import java.util.TreeSet;
64
import java.util.concurrent.atomic.AtomicBoolean;
64
import org.openide.util.SharedClassObject;
65
import org.openide.util.SharedClassObject;
65
import org.openide.util.Utilities;
66
import org.openide.util.Utilities;
66
import org.openide.util.io.NbMarshalledObject;
67
import org.openide.util.io.NbMarshalledObject;
Lines 149-154 Link Here
149
        return new Attr(index, value);
150
        return new Attr(index, value);
150
    }
151
    }
151
152
153
    static Object getRawAttribute(FileObject fo, String name, AtomicBoolean ab) {
154
        Object raw = fo.getAttribute("raw:" + name); // NOI18N
155
        if (raw != null) {
156
            if (ab != null) {
157
                ab.set(true);
158
            }
159
            return raw;
160
        }
161
        if (ab != null) {
162
            ab.set(false);
163
        }
164
        return fo.getAttribute(name);
165
    }
166
    private static ThreadLocal<FileObject> ATTR_FOR = new ThreadLocal<FileObject>();
167
    static Object readAttribute(FileObject forFO, AbstractFileSystem.Attr attr, String path, String attrName) {
168
        FileObject prev = ATTR_FOR.get();
169
        try {
170
            ATTR_FOR.set(forFO);
171
            return attr.readAttribute(path, attrName);
172
        } finally {
173
            ATTR_FOR.set(prev);
174
        }
175
    }
152
    /** According to name of attribute returns attribute as object
176
    /** According to name of attribute returns attribute as object
153
    * @param p1 is name of attribute
177
    * @param p1 is name of attribute
154
    * @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
178
    * @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
Lines 186-192 Link Here
186
    /** implementation of Map.get. But fires Exception to have chance in
210
    /** implementation of Map.get. But fires Exception to have chance in
187
     * DefaultAttributes to catch and annotate*/
211
     * DefaultAttributes to catch and annotate*/
188
    Object getAttribute(Object attrName) throws Exception {
212
    Object getAttribute(Object attrName) throws Exception {
189
        return getAttribute(attrName, null);
213
        return getAttribute(attrName, new Object[] { ATTR_FOR.get(), attrName });
190
    }
214
    }
191
215
192
    private Object getAttribute(Object attrName, Object[] params)
216
    private Object getAttribute(Object attrName, Object[] params)
Lines 204-215 Link Here
204
        if (attr == null && origAttrName.startsWith("class:")) { // NOI18N
228
        if (attr == null && origAttrName.startsWith("class:")) { // NOI18N
205
            attr = (Attr) map.get(origAttrName.substring(6));
229
            attr = (Attr) map.get(origAttrName.substring(6));
206
            retVal = attr != null ? attr.getType(params) : null;
230
            retVal = attr != null ? attr.getType(params) : null;
231
        } else if (attr == null && origAttrName.startsWith("raw:")) { // NOI18N
232
            attr = (Attr) map.get(origAttrName.substring(4));
233
            if (attr != null && attr.keyIndex == 9) {
234
                return attr.methodValue(attr.value, params).getMethod();
235
            }
236
            if (attr != null && attr.keyIndex == 12) {
237
                return attr.getType(params);
238
            }
207
        } else {
239
        } else {
208
            try {
240
            if (keyValuePair[1] instanceof ModifiedAttribute) {
209
                retVal = (attr == null) ? attr : attr.get(params);
241
                return attr;
210
            } catch (Exception e) {
242
            } else {
211
                ExternalUtil.annotate(e, "attrName = " + attrName); //NOI18N
243
                try {
212
                throw e;
244
                    retVal = (attr == null) ? attr : attr.get(params);
245
                } catch (Exception e) {
246
                    ExternalUtil.annotate(e, "attrName = " + attrName); //NOI18N
247
                    throw e;
248
                }
213
            }
249
            }
214
        }
250
        }
215
251
Lines 244-251 Link Here
244
        Object[] keyValuePair = ModifiedAttribute.translateInto((String) p1, p2);
280
        Object[] keyValuePair = ModifiedAttribute.translateInto((String) p1, p2);
245
        String key = (String) keyValuePair[0];
281
        String key = (String) keyValuePair[0];
246
        Object value = keyValuePair[1];
282
        Object value = keyValuePair[1];
247
        Object toStore = ((value == null) || value instanceof Attr) ? value : new Attr(value);
283
        Object toStore;
248
284
        if (value == null) {
285
            toStore = null;
286
        } else if (value instanceof Attr) {
287
            toStore = value;
288
        } else if (value instanceof Method && key.startsWith("methodvalue:")) { // NOI18N
289
            Method m = (Method)value;
290
            key = key.substring("methodvalue:".length()); // NOI18N
291
            toStore = new Attr("methodvalue", m.getDeclaringClass().getName() + '.' + m.getName()); // NOI18N
292
        } else if (value instanceof Class && key.startsWith("newvalue:")) { // NOI18N
293
            Class<?> c = (Class<?>)value;
294
            key = key.substring("newvalue:".length()); // NOI18N
295
            toStore = new Attr("newvalue", c.getName()); // NOI18N
296
        } else {
297
            toStore = new Attr(value);
298
        }
249
        if (decode) {
299
        if (decode) {
250
            key = Attr.decode(key).intern();
300
            key = Attr.decode(key).intern();
251
        }
301
        }
Lines 621-639 Link Here
621
        }
671
        }
622
672
623
        /**
673
        /**
624
        * Constructs new attribute as Object. Used for static creation from literal or serialValue.
625
        * @return new attribute as Object
626
        */
627
        private Object get() throws Exception {
628
            return getObject(null); //getObject is ready to aobtain null
629
        }
630
631
        /**
632
         * Constructs new attribute as Object. Used for dynamic creation: methodvalue .
674
         * Constructs new attribute as Object. Used for dynamic creation: methodvalue .
633
         * @param objs has sense only for methodvalue invocation; and only 2 parametres will be used
675
         * @param objs has sense only for methodvalue invocation; and only 2 parametres will be used
634
         *@return new attribute as Object
676
         *@return new attribute as Object
635
         */
677
         */
636
        private Object get(Object[] objs) throws Exception {
678
        final Object get(Object[] objs) throws Exception {
637
            return getObject(objs);
679
            return getObject(objs);
638
        }
680
        }
639
681
(-)a/openide.filesystems/test/unit/src/org/openide/filesystems/AttributesTestHidden.java (+54 lines)
Lines 47-52 Link Here
47
47
48
import java.util.*;
48
import java.util.*;
49
import java.io.*;
49
import java.io.*;
50
import java.lang.reflect.Method;
50
51
51
/**
52
/**
52
 *
53
 *
Lines 284-289 Link Here
284
        assertTrue (TEST_ERR,testedFS != null);                    
285
        assertTrue (TEST_ERR,testedFS != null);                    
285
    }*/
286
    }*/
286
287
288
    public void testFileUtilCopyAttributes() throws Exception {
289
        assertTrue(TEST_ERR, testedFS != null);
290
        if (testedFS.isReadOnly()) {
291
            return;
292
        }
293
294
        File f = new File(getWorkDir(), "sample.xml");
295
        FileOutputStream fos = new FileOutputStream(f);
296
        fos.write(("<?xml version='1.0' encoding='UTF-8'?>" +
297
                "<!DOCTYPE filesystem PUBLIC '-//NetBeans//DTD Filesystem 1.2//EN' 'http://www.netbeans.org/dtds/filesystem-1_2.dtd'>" +
298
                "<filesystem>" +
299
                "<folder name='Templates'>" +
300
                "<folder name='Other'>" +
301
                "<file name='special'>" +
302
                "  <attr name='ii' methodvalue='" + AttributesTestHidden.class.getName() + ".hello'/>" +
303
                "  <attr name='temp' boolvalue='true'/>" +
304
                "</file></folder></folder></filesystem>"
305
        ).getBytes());
306
        fos.close();
307
308
        XMLFileSystem xfs = new XMLFileSystem(f.toURI().toURL());
309
        FileObject template = xfs.findResource("Templates/Other/special");
310
        assertNotNull("template found", template);
311
        FileObject foTested = testedFS.getRoot().createData("copiedTemplate");
312
        FileUtil.copyAttributes(template, foTested);
313
        assertEquals("template copied too", Boolean.TRUE, foTested.getAttribute("temp"));
314
        assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii"));
315
    }
316
317
    public static String hello(FileObject obj, String attr) {
318
        return "Hello " + attr + "@" + obj.getNameExt();
319
    }
320
321
    public void testSetMethodGetResult() throws Exception {
322
        assertTrue(TEST_ERR, testedFS != null);
323
        if (testedFS.isReadOnly()) {
324
            return;
325
        }
326
327
        FileObject foTested = testedFS.getRoot().createData("copiedTemplate");
328
        Method m = AttributesTestHidden.class.getDeclaredMethod("hello", FileObject.class, String.class);
329
        foTested.setAttribute("methodvalue:ii", m);
330
331
        assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii"));
332
    }
333
334
    public static final class Data {
335
        static int cnt;
336
        
337
        public Data() {
338
            cnt++;
339
        }
340
    } // end of Data
287
}
341
}
288
342
289
343
(-)a/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java (-2 / +36 lines)
Lines 61-67 Link Here
61
import java.util.Map;
61
import java.util.Map;
62
import java.util.jar.JarEntry;
62
import java.util.jar.JarEntry;
63
import java.util.jar.JarOutputStream;
63
import java.util.jar.JarOutputStream;
64
import java.util.zip.ZipEntry;
65
import org.openide.util.Enumerations;
64
import org.openide.util.Enumerations;
66
65
67
public class XMLFileSystemTestHid extends TestBaseHid {
66
public class XMLFileSystemTestHid extends TestBaseHid {
Lines 900-906 Link Here
900
        
899
        
901
        assertAttr("Imutable value is still nochange", nochange, "value", "nochange");
900
        assertAttr("Imutable value is still nochange", nochange, "value", "nochange");
902
        assertEquals("No change in this attribute: "  + no.events, 0, no.events.size());
901
        assertEquals("No change in this attribute: "  + no.events, 0, no.events.size());
903
    }    
902
    }
903
904
    public void testFileUtilCopyAttributesOnOwnLayer() throws Exception {
905
        File f = new File(getWorkDir(), "sample.xml");
906
        FileOutputStream fos = new FileOutputStream(f);
907
        fos.write(("<?xml version='1.0' encoding='UTF-8'?>" +
908
                "<!DOCTYPE filesystem PUBLIC '-//NetBeans//DTD Filesystem 1.2//EN' 'http://www.netbeans.org/dtds/filesystem-1_2.dtd'>" +
909
                "<filesystem>" +
910
                "<folder name='Templates'>" +
911
                "<folder name='Other'>" +
912
                "<file name='special'>" +
913
                "  <attr name='ii' methodvalue='" + AttributesTestHidden.class.getName() + ".hello'/>" +
914
                "  <attr name='jj' newvalue='" + AttributesTestHidden.Data.class.getName() + "'/>" +
915
                "  <attr name='temp' boolvalue='true'/>" +
916
                "</file></folder></folder></filesystem>"
917
        ).getBytes());
918
        fos.close();
919
920
        File r = new File(getWorkDir(), "root");
921
        r.mkdirs();
922
        LocalFileSystem target = new LocalFileSystem();
923
        target.setRootDirectory(r);
924
925
        FileSystem source = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURI().toURL());
926
        FileObject template = source.findResource("Templates/Other/special");
927
        assertNotNull("template found", template);
928
        FileObject foTested = target.getRoot().createData("copiedTemplate");
929
        FileUtil.copyAttributes(template, foTested);
930
        assertEquals("template copied too", Boolean.TRUE, foTested.getAttribute("temp"));
931
        assertEquals("instantiatingIterator called", "Hello ii@copiedTemplate", foTested.getAttribute("ii"));
932
        assertEquals("No data instantiated", 0, AttributesTestHidden.Data.cnt);
933
        Object newV = foTested.getAttribute("jj");
934
        assertNotNull("Value created", newV);
935
        assertEquals(AttributesTestHidden.Data.class, newV.getClass());
936
        assertEquals("One value instantiated", 1, AttributesTestHidden.Data.cnt);
937
    }
904
938
905
    private static Image icon;
939
    private static Image icon;
906
940

Return to bug 120724