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 20962
Collapse All | Expand All

(-)ant/src/org/apache/tools/ant/module/AntSettings.java (+7 lines)
Lines 58-63 Link Here
58
    
58
    
59
    protected void initialize () {
59
    protected void initialize () {
60
        super.initialize();
60
        super.initialize();
61
        reset ();
62
    }
63
    
64
    /** Called from initialize and also using reflection when this option
65
     * is about to be "reset". See issue #20962.
66
     */
67
    protected void reset () {
61
        setVerbosity(2 /*Project.MSG_INFO*/);
68
        setVerbosity(2 /*Project.MSG_INFO*/);
62
        Properties p = new Properties ();
69
        Properties p = new Properties ();
63
        // Enable hyperlinking for Jikes:
70
        // Enable hyperlinking for Jikes:
(-)openide/api/doc/changes/apichanges.xml (+19 lines)
Lines 114-119 Link Here
114
114
115
<!-- ACTUAL CHANGES BEGIN HERE: -->
115
<!-- ACTUAL CHANGES BEGIN HERE: -->
116
<changes>
116
<changes>
117
    <change id="SharedClassObject.reset">
118
        <api name="util"/>
119
        <summary>Added <code>SharedClassObject.reset</code> method to allow subclasses to implement reset correctly</summary>
120
        <version major="4" minor="46"/>
121
        <date day="2" month="9" year="2004"/>
122
        <author login="jtulach"/>
123
        <compatibility addition="yes" binary="compatible" source="incompatible" semantic="compatible" />
124
        <description>
125
            The new <code>SharedClassObject.reset</code> method is called
126
            by the infrastructure in moments when an original (at the time
127
            of start) state of an option or any other <code>SharedClassObject</code>
128
            is requested. Interested subclasses (like <code>SystemOption</code>s
129
            in Tools/Option dialog) are free to implement any kind of clean
130
            then need.
131
        </description>
132
        <class package="org.openide.util" name="SharedClassObject"/>
133
        <issue number="20962"/>
134
    </change>
135
    
117
    <change id="TreeView.dragActive">
136
    <change id="TreeView.dragActive">
118
        <api name="explorer"/>
137
        <api name="explorer"/>
119
        <summary>Fixed <code>TreeView.drag/dropActive</code> switcher</summary>
138
        <summary>Fixed <code>TreeView.drag/dropActive</code> switcher</summary>
(-)openide/src/org/openide/options/SystemOption.java (-3 lines)
Lines 53-61 Link Here
53
53
54
    /** Default constructor. */
54
    /** Default constructor. */
55
    public SystemOption() {
55
    public SystemOption() {
56
        // SystemOption must declare this property in order to be correctly deserialized
57
        // by SharedClassObject.findObject function
58
        putProperty ("netbeans.systemoption.hack", null); // NOI18N
59
    }
56
    }
60
57
61
    /** Fire a property change event to all listeners. Delays
58
    /** Fire a property change event to all listeners. Delays
(-)openide/src/org/openide/util/SharedClassObject.java (-58 / +24 lines)
Lines 40-47 Link Here
40
    /** Name of the method used to determine whether an option is global or not. */
40
    /** Name of the method used to determine whether an option is global or not. */
41
    static final String GLOBAL_METHOD_NAME = "isGlobal"; // NOI18N
41
    static final String GLOBAL_METHOD_NAME = "isGlobal"; // NOI18N
42
    
42
    
43
    private byte [] defaultInstance = null;
44
    
45
    /** property change support (PropertyChangeSupport) */
43
    /** property change support (PropertyChangeSupport) */
46
    private static final Object PROP_SUPPORT = new Object ();
44
    private static final Object PROP_SUPPORT = new Object ();
47
45
Lines 237-246 Link Here
237
            throw new NullPointerException("Tried to pass null key (value=" + value + ") to putProperty"); // NOI18N
235
            throw new NullPointerException("Tried to pass null key (value=" + value + ") to putProperty"); // NOI18N
238
        }
236
        }
239
        synchronized (getLock ()) {
237
        synchronized (getLock ()) {
240
            if (key.equals ("netbeans.systemoption.hack")) { // NOI18N
241
                systemOption = true;
242
                return null;
243
            }
244
            if (waitingOnSystemOption && key != PROP_SUPPORT &&
238
            if (waitingOnSystemOption && key != PROP_SUPPORT &&
245
                    prematureSystemOptionMutation == null && !dataEntry.isInInitialize() && !inReadExternal) {
239
                    prematureSystemOptionMutation == null && !dataEntry.isInInitialize() && !inReadExternal) {
246
                // See below in findObject. Note that if we are still in initialize(),
240
                // See below in findObject. Note that if we are still in initialize(),
Lines 472-479 Link Here
472
                }
466
                }
473
            }
467
            }
474
            if (created) {
468
            if (created) {
475
                obj.reset ();
476
477
                // This hack was created due to the remove of SystemOptions deserialization
469
                // This hack was created due to the remove of SystemOptions deserialization
478
                // from project open operation, all SystemOptions are deserialized at this place
470
                // from project open operation, all SystemOptions are deserialized at this place
479
                // the first time anybody asks for the option.
471
                // the first time anybody asks for the option.
Lines 481-487 Link Here
481
                // otherwise it can cause deadlocks.
473
                // otherwise it can cause deadlocks.
482
                // Lookup in the active session is used to find serialized state of the option,
474
                // Lookup in the active session is used to find serialized state of the option,
483
                // if such state exists it is deserialized before the object is returned from lookup.
475
                // if such state exists it is deserialized before the object is returned from lookup.
484
                if (obj.systemOption) {
476
                if (obj.isSystemOption ()) {
485
                    // Lookup will find serialized version of searched object and deserialize it
477
                    // Lookup will find serialized version of searched object and deserialize it
486
                    final Lookup.Result r = Lookup.getDefault().lookup(new Lookup.Template(clazz));
478
                    final Lookup.Result r = Lookup.getDefault().lookup(new Lookup.Template(clazz));
487
                    if (r.allInstances().isEmpty()) {
479
                    if (r.allInstances().isEmpty()) {
Lines 518-523 Link Here
518
            return obj;
510
            return obj;
519
        }
511
        }
520
    }
512
    }
513
    
514
    /** checks whether we are instance of system option.
515
     */
516
    private boolean isSystemOption () {
517
        Class c = this.getClass ();
518
        while (c != SharedClassObject.class) {
519
            if ("org.openide.options.SystemOption".equals (c.getName ())) return true; // NOI18N
520
            c = c.getSuperclass ();
521
        }
522
        return false;
523
    }
524
    
521
    // See above:
525
    // See above:
522
    private static void warn(Throwable t) {
526
    private static void warn(Throwable t) {
523
        err.notify(ErrorManager.INFORMATIONAL, t);
527
        err.notify(ErrorManager.INFORMATIONAL, t);
Lines 547-603 Link Here
547
        }
551
        }
548
    }
552
    }
549
553
550
    /** Resets shared data to it default value. */
554
    /** Is called by the infrastructure in cases when a clean instance is requested.
551
    private void reset () {
555
     * As instances of <code>SharedClassObject</code> are singletons, there is 
552
        if (!systemOption || !isProjectOption ()) {
556
     * no way how to create new instance that would not contain the same data
553
            return;
557
     * as previously existing one. This method allows all subclasses that care
554
        }
558
     * about the ability to refresh the settings (like <code>SystemOption</code>s) 
555
559
     * to be notified about the cleaning request and clean their settings themselves.
556
        synchronized (getLock ()) {
560
     * <p>
557
            // [PENDING] should be changed to next line after all options in layers will
561
     * Default implementation does nothing.
558
            // use put{get}Property and initilaize properly
562
     *
559
            // dataEntry.reset (this);
563
     * @since made protected in version 4.46
560
            
561
            if (defaultInstance == null) {
562
                try {
563
                    ByteArrayOutputStream baos = new ByteArrayOutputStream (1024);
564
                    ObjectOutput oo = new org.openide.util.io.NbObjectOutputStream (baos);
565
                    oo.writeObject (this);
566
                    defaultInstance = baos.toByteArray ();
567
                } catch (IOException e) {
568
                    defaultInstance = null;
569
                }
570
                return;
571
            }
572
573
            try {
574
                ByteArrayInputStream bais = new ByteArrayInputStream (defaultInstance);
575
                ObjectInputStream oi = new org.openide.util.io.NbObjectInputStream (bais);
576
                oi.readObject ();
577
            } catch (Exception e) {
578
                // ignore and leave it as it is
579
            }
580
        }
581
    }
582
    
583
    /**
584
     * Test if the object is Project specific.
585
     * @return true if the object is Project specific
586
     */
564
     */
587
    private boolean isProjectOption () {
565
    protected void reset () {
588
        try {
589
            Class clazz = getClass ();
590
            // the old hack with undocumented method isGlobal
591
            Method m = clazz.getMethod(GLOBAL_METHOD_NAME, new Class[] {});
592
            m.setAccessible(true);
593
            Boolean b = (Boolean) m.invoke(this, new Object[] {});
594
            return !b.booleanValue();
595
        } catch (Exception ex) {
596
            // ignore and return default
597
        }
598
        return false;
599
    }
566
    }
600
    
601
    
567
    
602
    /** Class that is used as default write replace.
568
    /** Class that is used as default write replace.
603
    */
569
    */
(-)openide/test/unit/src/org/openide/loaders/InstanceDataObjectTest.java (+54 lines)
Lines 564-569 Link Here
564
        assertNotNull ("Has cookie", ic);
564
        assertNotNull ("Has cookie", ic);
565
        assertEquals ("And its value is x", x, ic.instanceCreate ());
565
        assertEquals ("And its value is x", x, ic.instanceCreate ());
566
    }
566
    }
567
568
    
569
    public void testWeAreAbleToResetSharedClassObjectByCallingResetOnItIssue20962 () throws Exception {
570
        FileObject lookupFO;
571
        {
572
            Object x = Setting.findObject (Setting.class, true);
573
            lookupFO = lfs.findResource("/system/Services/lookupTest");
574
            DataFolder folderTest = DataFolder.findFolder(lookupFO);
575
            InstanceDataObject ido = InstanceDataObject.create (folderTest, "testLookupRefresh", x, null);
576
            lookupFO = ido.getPrimaryFile ();
577
            WeakReference ref = new WeakReference (ido);
578
            Setting.resetCalled = 0;
579
        }
580
581
        InstanceDataObject ido = (InstanceDataObject)DataObject.find (lookupFO);
582
        InstanceCookie ic = (InstanceCookie)ido.getCookie (InstanceCookie.class);
583
        assertNotNull ("Has cookie", ic);
584
        Object obj = ic.instanceCreate ();
585
        assertNotNull ("Not null", obj);
586
        assertEquals ("It is settings", Setting.class, obj.getClass ());
587
        
588
        
589
        FileLock lock = lookupFO.lock ();
590
        OutputStream os = lookupFO.getOutputStream (lock);
591
        
592
        PrintWriter pw = new PrintWriter (os);
593
        pw.println ("<?xml version=\"1.0\"?>");
594
        pw.println ("<!DOCTYPE settings PUBLIC \"-//NetBeans//DTD Session settings 1.0//EN\" \"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd\">");
595
        pw.println ("<settings version=\"1.0\">");
596
        pw.println ("  <module name=\"org.openide/1\" spec=\"1.13\"/>");
597
        pw.println ("  <instanceof class=\"org.openide.options.SystemOption\"/>");
598
        pw.println ("  <instance class=\"" + Setting.class.getName () + "\"/>");
599
        pw.println ("</settings>");
600
        pw.close ();
601
        lock.releaseLock ();
602
        
603
        ic = (InstanceCookie)ido.getCookie (InstanceCookie.class);
604
        assertNotNull ("Has cookie", ic);
605
        assertNotNull ("Not null", obj);
606
        assertEquals ("It is settings", Setting.class, obj.getClass ());
607
        Setting s = (Setting)Setting.findObject (Setting.class, true);
608
        assertEquals ("Refresh has been called", 1, s.resetCalled);
609
    }
567
    
610
    
568
    /** Checks whether the instance is not saved multiple times.
611
    /** Checks whether the instance is not saved multiple times.
569
     *
612
     *
Lines 920-923 Link Here
920
        }
963
        }
921
    }
964
    }
922
965
966
    public static final class Setting extends org.openide.options.SystemOption {
967
        private static int resetCalled;
968
        
969
        protected void reset () {
970
            resetCalled++;
971
        }
972
        
973
        public String displayName () {
974
            return "My Setting";
975
        }
976
    }
923
}
977
}

Return to bug 20962