Index: ant/src/org/apache/tools/ant/module/AntSettings.java =================================================================== RCS file: /cvs/ant/src/org/apache/tools/ant/module/AntSettings.java,v retrieving revision 1.28 diff -u -r1.28 AntSettings.java --- ant/src/org/apache/tools/ant/module/AntSettings.java 31 Aug 2004 00:37:44 -0000 1.28 +++ ant/src/org/apache/tools/ant/module/AntSettings.java 2 Sep 2004 10:36:45 -0000 @@ -58,6 +58,13 @@ protected void initialize () { super.initialize(); + reset (); + } + + /** Called from initialize and also using reflection when this option + * is about to be "reset". See issue #20962. + */ + protected void reset () { setVerbosity(2 /*Project.MSG_INFO*/); Properties p = new Properties (); // Enable hyperlinking for Jikes: Index: openide/api/doc/changes/apichanges.xml =================================================================== RCS file: /cvs/openide/api/doc/changes/apichanges.xml,v retrieving revision 1.217 diff -u -r1.217 apichanges.xml --- openide/api/doc/changes/apichanges.xml 25 Aug 2004 13:34:49 -0000 1.217 +++ openide/api/doc/changes/apichanges.xml 2 Sep 2004 10:36:46 -0000 @@ -114,6 +114,25 @@ + + + Added SharedClassObject.reset method to allow subclasses to implement reset correctly + + + + + + The new SharedClassObject.reset method is called + by the infrastructure in moments when an original (at the time + of start) state of an option or any other SharedClassObject + is requested. Interested subclasses (like SystemOptions + in Tools/Option dialog) are free to implement any kind of clean + then need. + + + + + Fixed TreeView.drag/dropActive switcher Index: openide/src/org/openide/options/SystemOption.java =================================================================== RCS file: /cvs/openide/src/org/openide/options/SystemOption.java,v retrieving revision 1.36 diff -u -r1.36 SystemOption.java --- openide/src/org/openide/options/SystemOption.java 3 Aug 2004 16:44:23 -0000 1.36 +++ openide/src/org/openide/options/SystemOption.java 2 Sep 2004 10:36:47 -0000 @@ -53,9 +53,6 @@ /** Default constructor. */ public SystemOption() { - // SystemOption must declare this property in order to be correctly deserialized - // by SharedClassObject.findObject function - putProperty ("netbeans.systemoption.hack", null); // NOI18N } /** Fire a property change event to all listeners. Delays Index: openide/src/org/openide/util/SharedClassObject.java =================================================================== RCS file: /cvs/openide/src/org/openide/util/SharedClassObject.java,v retrieving revision 1.64 diff -u -r1.64 SharedClassObject.java --- openide/src/org/openide/util/SharedClassObject.java 18 Aug 2004 21:42:59 -0000 1.64 +++ openide/src/org/openide/util/SharedClassObject.java 2 Sep 2004 10:36:47 -0000 @@ -40,8 +40,6 @@ /** Name of the method used to determine whether an option is global or not. */ static final String GLOBAL_METHOD_NAME = "isGlobal"; // NOI18N - private byte [] defaultInstance = null; - /** property change support (PropertyChangeSupport) */ private static final Object PROP_SUPPORT = new Object (); @@ -237,10 +235,6 @@ throw new NullPointerException("Tried to pass null key (value=" + value + ") to putProperty"); // NOI18N } synchronized (getLock ()) { - if (key.equals ("netbeans.systemoption.hack")) { // NOI18N - systemOption = true; - return null; - } if (waitingOnSystemOption && key != PROP_SUPPORT && prematureSystemOptionMutation == null && !dataEntry.isInInitialize() && !inReadExternal) { // See below in findObject. Note that if we are still in initialize(), @@ -472,8 +466,6 @@ } } if (created) { - obj.reset (); - // This hack was created due to the remove of SystemOptions deserialization // from project open operation, all SystemOptions are deserialized at this place // the first time anybody asks for the option. @@ -481,7 +473,7 @@ // otherwise it can cause deadlocks. // Lookup in the active session is used to find serialized state of the option, // if such state exists it is deserialized before the object is returned from lookup. - if (obj.systemOption) { + if (obj.isSystemOption ()) { // Lookup will find serialized version of searched object and deserialize it final Lookup.Result r = Lookup.getDefault().lookup(new Lookup.Template(clazz)); if (r.allInstances().isEmpty()) { @@ -518,6 +510,18 @@ return obj; } } + + /** checks whether we are instance of system option. + */ + private boolean isSystemOption () { + Class c = this.getClass (); + while (c != SharedClassObject.class) { + if ("org.openide.options.SystemOption".equals (c.getName ())) return true; // NOI18N + c = c.getSuperclass (); + } + return false; + } + // See above: private static void warn(Throwable t) { err.notify(ErrorManager.INFORMATIONAL, t); @@ -547,57 +551,19 @@ } } - /** Resets shared data to it default value. */ - private void reset () { - if (!systemOption || !isProjectOption ()) { - return; - } - - synchronized (getLock ()) { - // [PENDING] should be changed to next line after all options in layers will - // use put{get}Property and initilaize properly - // dataEntry.reset (this); - - if (defaultInstance == null) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream (1024); - ObjectOutput oo = new org.openide.util.io.NbObjectOutputStream (baos); - oo.writeObject (this); - defaultInstance = baos.toByteArray (); - } catch (IOException e) { - defaultInstance = null; - } - return; - } - - try { - ByteArrayInputStream bais = new ByteArrayInputStream (defaultInstance); - ObjectInputStream oi = new org.openide.util.io.NbObjectInputStream (bais); - oi.readObject (); - } catch (Exception e) { - // ignore and leave it as it is - } - } - } - - /** - * Test if the object is Project specific. - * @return true if the object is Project specific + /** Is called by the infrastructure in cases when a clean instance is requested. + * As instances of SharedClassObject are singletons, there is + * no way how to create new instance that would not contain the same data + * as previously existing one. This method allows all subclasses that care + * about the ability to refresh the settings (like SystemOptions) + * to be notified about the cleaning request and clean their settings themselves. + *

+ * Default implementation does nothing. + * + * @since made protected in version 4.46 */ - private boolean isProjectOption () { - try { - Class clazz = getClass (); - // the old hack with undocumented method isGlobal - Method m = clazz.getMethod(GLOBAL_METHOD_NAME, new Class[] {}); - m.setAccessible(true); - Boolean b = (Boolean) m.invoke(this, new Object[] {}); - return !b.booleanValue(); - } catch (Exception ex) { - // ignore and return default - } - return false; + protected void reset () { } - /** Class that is used as default write replace. */ Index: openide/test/unit/src/org/openide/loaders/InstanceDataObjectTest.java =================================================================== RCS file: /cvs/openide/test/unit/src/org/openide/loaders/InstanceDataObjectTest.java,v retrieving revision 1.32 diff -u -r1.32 InstanceDataObjectTest.java --- openide/test/unit/src/org/openide/loaders/InstanceDataObjectTest.java 31 Aug 2004 11:21:22 -0000 1.32 +++ openide/test/unit/src/org/openide/loaders/InstanceDataObjectTest.java 2 Sep 2004 10:36:47 -0000 @@ -564,6 +564,49 @@ assertNotNull ("Has cookie", ic); assertEquals ("And its value is x", x, ic.instanceCreate ()); } + + + public void testWeAreAbleToResetSharedClassObjectByCallingResetOnItIssue20962 () throws Exception { + FileObject lookupFO; + { + Object x = Setting.findObject (Setting.class, true); + lookupFO = lfs.findResource("/system/Services/lookupTest"); + DataFolder folderTest = DataFolder.findFolder(lookupFO); + InstanceDataObject ido = InstanceDataObject.create (folderTest, "testLookupRefresh", x, null); + lookupFO = ido.getPrimaryFile (); + WeakReference ref = new WeakReference (ido); + Setting.resetCalled = 0; + } + + InstanceDataObject ido = (InstanceDataObject)DataObject.find (lookupFO); + InstanceCookie ic = (InstanceCookie)ido.getCookie (InstanceCookie.class); + assertNotNull ("Has cookie", ic); + Object obj = ic.instanceCreate (); + assertNotNull ("Not null", obj); + assertEquals ("It is settings", Setting.class, obj.getClass ()); + + + FileLock lock = lookupFO.lock (); + OutputStream os = lookupFO.getOutputStream (lock); + + PrintWriter pw = new PrintWriter (os); + pw.println (""); + pw.println (""); + pw.println (""); + pw.println (" "); + pw.println (" "); + pw.println (" "); + pw.println (""); + pw.close (); + lock.releaseLock (); + + ic = (InstanceCookie)ido.getCookie (InstanceCookie.class); + assertNotNull ("Has cookie", ic); + assertNotNull ("Not null", obj); + assertEquals ("It is settings", Setting.class, obj.getClass ()); + Setting s = (Setting)Setting.findObject (Setting.class, true); + assertEquals ("Refresh has been called", 1, s.resetCalled); + } /** Checks whether the instance is not saved multiple times. * @@ -920,4 +963,15 @@ } } + public static final class Setting extends org.openide.options.SystemOption { + private static int resetCalled; + + protected void reset () { + resetCalled++; + } + + public String displayName () { + return "My Setting"; + } + } }