#151415 - ignore exception from removePreferenceChangeListener and removeNodeChangeListener thrown when node has already been removed.
1.1 --- a/openide.util/src/org/openide/util/WeakListenerImpl.java Mon Feb 16 23:34:16 2009 +0300
1.2 +++ b/openide.util/src/org/openide/util/WeakListenerImpl.java Fri Mar 06 08:56:57 2009 +0100
1.3 @@ -584,13 +584,16 @@
1.4 try {
1.5 remove.invoke(src, params);
1.6 } catch (Exception ex) { // from invoke(), should not happen
1.7 - String errMessage = "Problem encountered while calling " + methodClass + "." + methodName + "(...) on " + src; // NOI18N
1.8 - LOG.warning( errMessage );
1.9 - //detailed logging needed in some cases
1.10 - boolean showErrMessage = ex instanceof InvocationTargetException
1.11 - || "object is not an instance of declaring class".equals(ex.getMessage());
1.12 + // #151415 - ignore exception from AbstractPreferences if node has been removed
1.13 + if (!"removePreferenceChangeListener".equals(methodName) && !"removeNodeChangeListener".equals(methodName)) { //NOI18N
1.14 + String errMessage = "Problem encountered while calling " + methodClass + "." + methodName + "(...) on " + src; // NOI18N
1.15 + LOG.warning( errMessage );
1.16 + //detailed logging needed in some cases
1.17 + boolean showErrMessage = ex instanceof InvocationTargetException
1.18 + || "object is not an instance of declaring class".equals(ex.getMessage());
1.19
1.20 - LOG.log(Level.WARNING, showErrMessage ? errMessage : null, ex);
1.21 + LOG.log(Level.WARNING, showErrMessage ? errMessage : null, ex);
1.22 + }
1.23 }
1.24 }
1.25
2.1 --- a/openide.util/test/unit/src/org/openide/util/WeakListenersTest.java Mon Feb 16 23:34:16 2009 +0300
2.2 +++ b/openide.util/test/unit/src/org/openide/util/WeakListenersTest.java Fri Mar 06 08:56:57 2009 +0100
2.3 @@ -47,8 +47,16 @@
2.4 import java.util.ArrayList;
2.5 import java.util.Arrays;
2.6 import java.util.List;
2.7 +import java.util.concurrent.atomic.AtomicBoolean;
2.8 +import java.util.logging.Handler;
2.9 import java.util.logging.Level;
2.10 +import java.util.logging.LogRecord;
2.11 import java.util.logging.Logger;
2.12 +import java.util.prefs.NodeChangeEvent;
2.13 +import java.util.prefs.NodeChangeListener;
2.14 +import java.util.prefs.PreferenceChangeEvent;
2.15 +import java.util.prefs.PreferenceChangeListener;
2.16 +import java.util.prefs.Preferences;
2.17 import javax.swing.event.ChangeEvent;
2.18 import javax.swing.event.ChangeListener;
2.19 import org.netbeans.junit.NbTestCase;
2.20 @@ -71,7 +79,60 @@
2.21 protected Level logLevel() {
2.22 return Level.ALL;
2.23 }
2.24 -
2.25 +
2.26 + /** Tests that exception is not logged when WeakListenerImpl tries to
2.27 + * remove listener on already removed node (#151415). */
2.28 + public void testPreferenceChangeListener() throws Exception {
2.29 + PreferenceChangeListener pcl = new PreferenceChangeListener() {
2.30 +
2.31 + public void preferenceChange(PreferenceChangeEvent evt) {
2.32 + }
2.33 + };
2.34 + NodeChangeListener ncl = new NodeChangeListener() {
2.35 +
2.36 + public void childAdded(NodeChangeEvent evt) {
2.37 + }
2.38 +
2.39 + public void childRemoved(NodeChangeEvent evt) {
2.40 + }
2.41 + };
2.42 + Preferences nbp = NbPreferences.forModule(WeakListeners.class);
2.43 + nbp.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, pcl, nbp));
2.44 + nbp.addNodeChangeListener(WeakListeners.create(NodeChangeListener.class, ncl, nbp));
2.45 + nbp.removeNode();
2.46 +
2.47 + Logger logger = Logger.getLogger(WeakListenerImpl.class.getName());
2.48 + final AtomicBoolean nodeRemovedException = new AtomicBoolean(false);
2.49 + logger.addHandler(new Handler() {
2.50 +
2.51 + @Override
2.52 + public void publish(LogRecord record) {
2.53 + Throwable t = record.getThrown();
2.54 + if (t != null) {
2.55 + if (t.getCause() instanceof IllegalStateException && t.getCause().getMessage().equals("Node has been removed.")) { //NOI18N
2.56 + nodeRemovedException.set(true);
2.57 + }
2.58 + }
2.59 + }
2.60 +
2.61 + @Override
2.62 + public void flush() {
2.63 + }
2.64 +
2.65 + @Override
2.66 + public void close() throws SecurityException {
2.67 + }
2.68 + });
2.69 + Reference<PreferenceChangeListener> ref = new WeakReference<PreferenceChangeListener>(pcl);
2.70 + pcl = null;
2.71 + assertGC("PreferenceChangeListener cannot be collected", ref);
2.72 + Reference<NodeChangeListener> ref1 = new WeakReference<NodeChangeListener>(ncl);
2.73 + ncl = null;
2.74 + assertGC("NodeChangeListener cannot be collected", ref1);
2.75 + Thread.sleep(2000);
2.76 + assertFalse("The \"Node has been removed\" exception should not be thrown from WeakListenerImpl.", nodeRemovedException.get());
2.77 + }
2.78 +
2.79 public void testOneCanCallHashCodeOrOnWeakListener () {
2.80 Listener l = new Listener ();
2.81 Object weak = WeakListeners.create (PropertyChangeListener.class, l, null);