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.

Bug 46993 - Stack overflow in FilterNode.hashCode on 64-bit server VM
Summary: Stack overflow in FilterNode.hashCode on 64-bit server VM
Status: RESOLVED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: Nodes (show other bugs)
Version: 4.x
Hardware: PC Linux
: P2 blocker (vote)
Assignee: Petr Nejedly
URL:
Keywords:
: 49565 49825 50451 50939 51497 51517 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-08-08 12:03 UTC by lynggaard
Modified: 2014-02-22 17:24 UTC (History)
2 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
log frm netbeans (907.69 KB, text/plain)
2004-08-08 12:44 UTC, lynggaard
Details
new log showing the bug still present.note log is truncated it was 2.4 mb (913.51 KB, text/plain)
2004-09-04 21:50 UTC, lynggaard
Details
Log by Eamonn McManus shortened by removing 990 of hashCode() in stacktraces (122.54 KB, text/plain)
2004-09-21 10:06 UTC, Jaroslav Tulach
Details
shortend log from daily build 20/9 (31.68 KB, text/plain)
2004-09-21 20:06 UTC, lynggaard
Details
log from build 21/9 (205.57 KB, text/plain)
2004-09-22 20:01 UTC, lynggaard
Details
second log from daily build 21/9 (shortened) (217.06 KB, text/plain)
2004-09-22 20:38 UTC, lynggaard
Details
Modified FilterNode (32.92 KB, application/octet-stream)
2004-09-23 11:20 UTC, Jaroslav Tulach
Details
log from build 21/9 with patch (966.80 KB, text/plain)
2004-09-23 17:29 UTC, lynggaard
Details
log of patched 21/9 build, now with error. zipped (59.53 KB, application/octet-stream)
2004-09-23 21:53 UTC, lynggaard
Details
log of patched 21/9 build, another error. zipped (38.45 KB, application/octet-stream)
2004-09-23 22:04 UTC, lynggaard
Details

Note You need to log in before you can comment on or make changes to this bug.
Description lynggaard 2004-08-08 12:03:01 UTC
I had several tabs open (20+) and started closing
them one by one using CTRL + F4. After about half
of them I got a java.lang.InvocationTargetException.

Looking at the stacktrace is appears to code from
stackOverflow ecxeptions in
org.openide.nodes.FilterNode.hashCode()..

Im using NB 4.0, 2. august daily build,jdk 1.5
beta, gentoo linux amd64
Comment 1 lynggaard 2004-08-08 12:44:32 UTC
Created attachment 16686 [details]
log frm netbeans
Comment 2 Milos Kleint 2004-08-10 11:03:57 UTC
reassigning
Comment 3 Milos Kleint 2004-08-13 10:28:24 UTC
moving to openide/nodes.. seems to be a problem in FilterNode.hashcode() ?
Comment 4 Milos Kleint 2004-08-13 10:29:51 UTC
->nodes
Comment 5 Petr Hrebejk 2004-08-17 14:30:40 UTC
Something for Jarda to play with.
Comment 6 Jaroslav Tulach 2004-08-17 14:54:35 UTC
I think I can simulate the problem by doing 

FilterNode n = new FilterNode (Node.LEAF);
n.changeOriginal (n, ...);

but this should never happen. I'll add a check to filter node to
prevent itself to be assigned as original.
Comment 7 Jaroslav Tulach 2004-08-17 15:06:08 UTC
cvs -q ci -m "#46993: Forbiding setting itself as original"
Checking in src/org/openide/nodes/FilterNode.java;
/cvs/openide/src/org/openide/nodes/FilterNode.java,v  <--  FilterNode.java
new revision: 1.93; previous revision: 1.92
done
Processing log script arguments...
More commits to come...
Checking in test/unit/src/org/openide/nodes/FilterNodeTest.java;
/cvs/openide/test/unit/src/org/openide/nodes/FilterNodeTest.java,v 
<--  FilterNodeTest.java
new revision: 1.15;
Comment 8 lynggaard 2004-09-04 21:44:46 UTC
I'm reopening this, since this still occurs. Will attach new log..

I'm not sure it is triggered the same way, by I still get it quite
often. Once I get the first stack overflow in a session, a new
exception occures repeatedly (see log),so the program is rendered
unusable.

System:
NB 4.0 Daily build from 2. septemper
Java 1.5.0 rc.
Still gentoo and amd64

Comment 9 lynggaard 2004-09-04 21:50:21 UTC
Created attachment 17370 [details]
new log showing the bug still present.note log is truncated it was 2.4 mb
Comment 10 Jaroslav Tulach 2004-09-06 12:26:21 UTC
cvs ci -m "#46993: When started with -J-ea (probably in
etc/netbeans.conf) the system now performs StackOverflowError tests in
order to find the cause of issue 46993" - so next time you can report
exception with better annotations, but remember to run with -J-ea -
beta2 is not going to have this flag on by default!


Checking in src/org/openide/nodes/FilterNode.java;
/cvs/openide/src/org/openide/nodes/FilterNode.java,v  <--  FilterNode.java
new revision: 1.94; previous revision: 1.93
done
Processing log script arguments...
More commits to come...
Checking in test/unit/src/org/openide/nodes/FilterNodeTest.java;
/cvs/openide/test/unit/src/org/openide/nodes/FilterNodeTest.java,v 
<--  FilterNodeTest.java
new revision: 1.16; previous revision: 1.15
Comment 11 Jaroslav Tulach 2004-09-21 09:59:30 UTC
Eamonn McManus wrote to jtulach@netbeans.org:
> Hi,
> 
> I guess you added some instrumentation to this method to show what is 
> happening when it gets StackOverFlowError?  I downloaded the latest 
> qbuild (200409100847) and I still get the problem, but now it has some 
> extra information.  The log file is attached.  Hopefully this will 
> enable you to find the problem, if you haven't already.
Comment 12 Jaroslav Tulach 2004-09-21 10:06:27 UTC
Created attachment 17782 [details]
Log by Eamonn McManus shortened by removing 990 of hashCode() in stacktraces
Comment 13 Jaroslav Tulach 2004-09-21 10:16:55 UTC
As can be seen from a recent report by Eamonn McManus, the problem is
in java source hierachy that under certain (and unknown to me
conditions) succeeds in creating FilterNode that delegates to
CompatibleNode that delegates to the original FilterNode. So this is
not bug in openide/nodes, but somewhere in java source hierarchy.
Comment 14 Martin Matula 2004-09-21 10:20:11 UTC
Honzo, please evaluate.
Comment 15 Jan Pokorsky 2004-09-21 13:40:26 UTC
I have investigated code instantiating CompatibleNode, which is btw
private final class, and I found nothing suspicious. All usages of
CompatibleNode gets some subclass of AbstractNode as the original
node. So no possibility to create cycles. FilterNode.changeOriginal is
not used in the java module as well.

Unfortunatelly I am not able to reproduce this. So I would appreciate
some further help from openide developers as logging of cycles at time
of FilterNode construction or FilterNode.changeOriginal usage.
Comment 16 Jaroslav Tulach 2004-09-21 17:05:17 UTC
cvs ci -m "#46993: If run with -ea then a deep check is done in
changeOriginal to verify that nobody is creating any cycle"
Checking in src/org/openide/nodes/FilterNode.java;
/cvs/openide/src/org/openide/nodes/FilterNode.java,v  <--  FilterNode.java
new revision: 1.95; previous revision: 1.94
done
Processing log script arguments...
More commits to come...
Checking in test/unit/src/org/openide/nodes/FilterNodeTest.java;
/cvs/openide/test/unit/src/org/openide/nodes/FilterNodeTest.java,v 
<--  FilterNodeTest.java
new revision: 1.17; previous revision: 1.16
Comment 17 Jan Pokorsky 2004-09-21 17:58:57 UTC
To lynggaard: could you try to reproduce it and attach the ide log
file please?
Comment 18 lynggaard 2004-09-21 20:06:50 UTC
Created attachment 17796 [details]
shortend log from daily build 20/9
Comment 19 lynggaard 2004-09-21 20:12:54 UTC
Attached new log. Problem is still very obvious, happends within 5
minutes of use.

I did a fresh install using the 20/9 dialy build, wipe-ing both the
install dir and the user dir (~/.netbeans/)

I have shortend the log by removeing all the repeating
filternode.hashcode[] parts.

let me know if I should use a specific version or modify my install.

If you need the source code for what I'm coding it is available here:
http://cvs.sourceforge.net/viewcvs.py/moztrans/newsrc/

I am currently editing:
org.mozillatranslator.datamodel.GenericFile
org.mozillatranslator.datamodel.MozFile
org.mozillatranslator.io.glossary.PropertiesPersistence.


 
Comment 20 Jaroslav Tulach 2004-09-22 06:46:58 UTC
Ok, still shows the problem is in java/navigation. But we are not
getting closer to solution as we do not understand how that can happen.

Please try this on a newer build as the last patch with early failure
was integrated on Sep21.
Comment 21 lynggaard 2004-09-22 20:01:00 UTC
Created attachment 17812 [details]
log from build 21/9
Comment 22 lynggaard 2004-09-22 20:05:20 UTC
Okey this is what I did:

1. Download todays build 21/9
2. Clean install (wipe both install and settings dir)
3. start application and open projects
4. use the application for a while thinking the problem was gone, but
ran into http://www.netbeans.org/issues/show_bug.cgi?id=49438 
5. close netbeans and report the defect mentioned in item 4
6. remove the old log to have a clean one.

7. Start netbeans again, and while it was auto opening the last used
project I got the error again .
Comment 23 lynggaard 2004-09-22 20:38:10 UTC
Created attachment 17814 [details]
second log from daily build 21/9 (shortened)
Comment 24 lynggaard 2004-09-22 20:49:47 UTC
I have added a second log from todays build. This time it didn't choke
on application start and I was able to work for about 10 minutes
before it started to misbehave.

As you can see from the log, then once I had had one exception in a
session they just keep comming.Quite frankly it makes the program
unusable, if i cannot finish a sentence without an exception.

Note that in the log I also have a few null pointer exception from
http://www.netbeans.org/issues/show_bug.cgi?id=49438 I'm not sure if
they are related. The reason they are there is before I didn't kill
the app after the first exception, I wanted the log to show if they
came from differnt places.

please let me know if there is anything specific you want me to try..
Comment 25 Jaroslav Tulach 2004-09-23 07:18:16 UTC
Seems like my fix did not get into this build. The
FilterNode.hashCodeLogging is supposed to be on line 810 and not 806.
Comment 26 lynggaard 2004-09-23 09:14:48 UTC
actually the changelog at
http://www.netbeans.org/download/4_0/daily/200409211800/netbeans-4_0-daily-log-200409211800-changelog-21_Sep_2004_1800.html

indicates it did:

2004-09-21 16:04 jtulach	
openide
#46993: If run with -ea then a deep check is done in changeOriginal to
verify that nobody is creating any cycle

    openide/:

        src/org/openide/nodes/FilterNode.java (1.95)  [ diff from 1.94 ],
        test/unit/src/org/openide/nodes/FilterNodeTest.java (1.17)  [
diff from 1.16 ] 


perhaps I'm just not hitting that code ?!
Comment 27 Jaroslav Tulach 2004-09-23 11:19:45 UTC
You are right and it is really bad that you are not hitting the code.
One would say, that it is impossible. There are two places where the
FilterNode.original field is changing - the constructor and the
changeOriginal method. My debug code is in changeOriginal and is not
called. So the wrong assignment must have happen in constructor. But
no valid constructor can pass instance of itself into own constructor!

I have to say I am lost. I will attach changed FilterNode class that
does a lot of logging. Replace the .class files in openide.jar by
these. And try to reproduce the problem.

Comment 28 Jaroslav Tulach 2004-09-23 11:20:22 UTC
Created attachment 17828 [details]
Modified FilterNode
Comment 29 Petr Nejedly 2004-09-23 12:42:29 UTC
BTW: Could you please try to reproduce the problem also on
a 32bit client VM?
Comment 30 lynggaard 2004-09-23 17:29:17 UTC
Created attachment 17847 [details]
log from build 21/9 with patch
Comment 31 lynggaard 2004-09-23 17:34:55 UTC
I have done the following

1. wiped my settings dir $HOME/.netbeans
2. replaced the original openide.jar with an patched version
3. started netbeans and tried again.

Result: I no longer get the popup warning me about stack errors, but
there are still plenty in  the log. The log is different so it appears
the patch is working, but blocking the popups.

The original log was 4.4 mb, I have just truncated it.

This was with the usual 64bit vm, I will try with a 32bit as requested
later.
Comment 32 Petr Nejedly 2004-09-23 18:03:38 UTC
The log is OK. Yarda just added desperate amount of logging that logs
even during normal conditions. He probably did nothing to fix the
problem, so I'd think it haven't yet manifested itself.

BTW: when testing on 32bit JVM, don't forget the _client_ part
(which is probably more important than 32b)...
Comment 33 lynggaard 2004-09-23 21:53:45 UTC
Created attachment 17852 [details]
log of patched 21/9 build, now with error. zipped
Comment 34 lynggaard 2004-09-23 21:59:48 UTC
I have now run into the problem with the patched version. I have
attached the full log, but since it is 3 MB I have zipped it.

Note that I run into a whole truck load of
http://www.netbeans.org/issues/show_bug.cgi?id=49438 first, so the
first filterNode exception is at approx line 46600.

I don't know if the bug are related in any way....
Comment 35 lynggaard 2004-09-23 22:04:59 UTC
Created attachment 17853 [details]
log of patched 21/9 build, another error. zipped
Comment 36 lynggaard 2004-09-23 22:07:17 UTC
I just hot the error again after about 2 minutes of usage. I have
attached the log for this one as well since it might be cleaner than
the previous zipped log.

This is still with the 64bit edition, I wont have a chance to test the
32bit client until this weekend.
Comment 37 Petr Nejedly 2004-09-26 21:59:26 UTC
*** Issue 49565 has been marked as a duplicate of this issue. ***
Comment 38 lynggaard 2004-09-27 17:28:25 UTC
I have been testing this issue during the weekend on my win32 box
(same hardware as the linux64)

If I install and use netbeans with the jdk 1.5 client VM then it
appears to work (alhough i might get other exceptions)

If I alter the ~$NETBEANS_INSTALL/etc/netbeans.conf and add -J-server
to run with the server VM,  I keep hitting the error.

Appaerently it has something to do with the server VM, but sadly
linux64 does not have a client VM :-\

Comment 39 Martin Matula 2004-10-04 09:22:58 UTC
*** Issue 49825 has been marked as a duplicate of this issue. ***
Comment 40 Jan Pokorsky 2004-10-04 13:50:22 UTC
This looks to be a generic problem of FilterNode, not just related to
the java module. See issue #49565 and the attached stack trace
(ProjectsRootNode$BadgingNode). I see nothing what can be done in the
java module to resolve this issue. Reassigning back
Comment 41 Jaroslav Tulach 2004-10-04 17:56:28 UTC
I have reported this as JVM bug #6173783. Should be accessible as 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6173783 I guess.

Until that bug is resolved, I do not think there is anything to be
done on NetBeans side.
Comment 42 Jaroslav Tulach 2004-10-05 07:14:33 UTC
Here is few suggestions from the hotspot guys:

0. Try "-Xint" to run only java interpreter.
   If you still have the problem - it is most likely in your code.
   If the problem does not show up - it may be VM problem, try the next:

1. Exclude the compilation of the method (well, we need to exlucde
whole class, I guess):
org.openide.nodes.FilterNode.hashCode:
-XX:CompileCommand=exclude,org/openide/nodes/FilterNode,hashCode

Please update this bug with your experience with -Xint.
Comment 43 Jaroslav Tulach 2004-10-06 15:01:17 UTC
Eamonn McManus napsal(a):
> Jaroslav,
> 
> I'm not sure whether you've been able to fix this problem recently.  I 
> find that it is still present in Beta 2.  Three different people
here as 
> well as myself have run into it.  All are using Solaris, which could 
> make a difference.  The symptom is that an exception window starts 
> appearing and it becomes impossible to do any work, because just moving 
> to a different line in the editor window is enough to make the
exception 
> window appear again several times.
> 
> I patched FilterNode.java to catch the problem.  It appears that the 
> current FilterNode.hashCode() is fragile since subclasses can easily 
> break it.  Since you don't control those subclasses the best solution 
> might be to use a ThreadLocal as I do in the patch here.

Subclasses can break it? I do not know how, the only way I can imagine
is to call changeOriginal method, but such method is not called at all.

> For information, this code prints the following shortly after netbeans 
> starts:
> RECURSIVE FilterNode.hashCode: original is a 
> org.openide.nodes.FilterNode; same as this: false
> stack: <<<org.netbeans.modules.java.ui.NavigationView$FNode[1216ee9]>>> 
> <loop>
> RECURSIVE FilterNode.hashCode: original is a 
> org.openide.nodes.FilterNode; same as this: false
> stack: <<<org.netbeans.modules.java.ui.NavigationView$FNode[14445b5]>>> 
> <loop>

Shortly after start? Maybe during some hotspot compilation... Please
try to reproduce the problem with options described at
http://www.netbeans.org/issues/show_bug.cgi?id=46993

-jst

> It doesn't print any more messages, even after a long editing session.
> 
> Regards,
> 
> 
> ------------------------------------------------------------------------
> 
> /*
>  *                 Sun Public License Notice
>  * 
>  * The contents of this file are subject to the Sun Public License
>  * Version 1.0 (the "License"). You may not use this file except in
>  * compliance with the License. A copy of the License is available at
>  * http://www.sun.com/
>  * 
>  * The Original Code is NetBeans. The Initial Developer of the Original
>  * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
>  * Microsystems, Inc. All Rights Reserved.
>  */
> 
> package org.openide.nodes;
> 
> import java.awt.Image;
> import java.awt.datatransfer.Transferable;
> import java.beans.PropertyChangeEvent;
> import java.beans.PropertyChangeListener;
> import java.io.IOException;
> 
> 
> import java.util.*;
> import java.lang.ref.WeakReference;
> import java.lang.reflect.Method;
> import org.openide.ErrorManager;
> 
> import org.openide.util.datatransfer.NewType;
> import org.openide.util.datatransfer.PasteType;
> import org.openide.util.HelpCtx;
> import org.openide.util.Lookup;
> import org.openide.util.LookupEvent;
> import org.openide.util.LookupListener;
> import org.openide.util.actions.SystemAction;
> 
> /** A proxy for another node.
> * Unless otherwise mentioned, all methods of the original node are
delegated to.
> * If desired, you can disable delegation of certain methods which
are concrete in <code>Node</code>
> * by calling {@link #disableDelegation}.
> *
> * <p><strong>Note:</strong> it is fine to subclass this class and use
> * it to filter things. But please do not ever try to cast a node to
> * <code>FilterNode</code>: it probably means you are doing something
> * wrong. Instead, ask whatever <code>Node</code> you have for a proper
> * kind of cookie (e.g. <code>DataObject</code>).
> *
> * @author Jaroslav Tulach
> */
> public class FilterNode extends Node {
>     /** node to delegate to */
>     private Node original;
>     /** listener to property changes,
>     * accessible thru getPropertyChangeListener
>     */
>     private PropertyChangeListener propL;
>     /** listener to node changes
>     * Accessible thru get node listener
>     */
>     private NodeListener nodeL;
> 
>     // Note: int (not long) to avoid need to ever synchronize when
accessing it
>     // (Java VM spec does not guarantee that long's will be stored
atomically)
>     /** @see #delegating */
>     private int delegateMask;
> 
>     /** Whether to delegate <code>setName</code>. */
>     protected static final int DELEGATE_SET_NAME = 1 << 0;
>     /** Whether to delegate <code>getName</code>. */
>     protected static final int DELEGATE_GET_NAME = 1 << 1;
>     /** Whether to delegate <code>setDisplayName</code>. */
>     protected static final int DELEGATE_SET_DISPLAY_NAME = 1 << 2;
>     /** Whether to delegate <code>getDisplayName</code>. */
>     protected static final int DELEGATE_GET_DISPLAY_NAME = 1 << 3;
>     /** Whether to delegate <code>setShortDescription</code>. */
>     protected static final int DELEGATE_SET_SHORT_DESCRIPTION = 1 << 4;
>     /** Whether to delegate <code>getShortDescription</code>. */
>     protected static final int DELEGATE_GET_SHORT_DESCRIPTION = 1 << 5;
>     /** Whether to delegate <code>destroy</code>. */
>     protected static final int DELEGATE_DESTROY = 1 << 6;
>     /** Whether to delegate <code>getActions</code>. */
>     protected static final int DELEGATE_GET_ACTIONS = 1 << 7;
>     /** Whether to delegate <code>getContextActions</code>. */
>     protected static final int DELEGATE_GET_CONTEXT_ACTIONS = 1 << 8;
>     /** Whether to delegate <code>setValue</code>.
>      * @since 4.25
>      */
>     protected static final int DELEGATE_SET_VALUE = 1 << 9;
>     /** Whether to delegate <code>getValue</code>.
>      * @since 4.25
>      */
>     protected static final int DELEGATE_GET_VALUE = 1 << 10;
>     
>     
>     /** Mask indicating delegation of all possible methods. */
>     private static final int DELEGATE_ALL = DELEGATE_SET_NAME |
>                                             DELEGATE_GET_NAME |
>                                             DELEGATE_SET_DISPLAY_NAME |
>                                             DELEGATE_GET_DISPLAY_NAME |
>                                            
DELEGATE_SET_SHORT_DESCRIPTION |
>                                            
DELEGATE_GET_SHORT_DESCRIPTION |
>                                             DELEGATE_DESTROY |
>                                             DELEGATE_GET_ACTIONS |
>                                            
DELEGATE_GET_CONTEXT_ACTIONS |
>                                             DELEGATE_SET_VALUE |
>                                             DELEGATE_GET_VALUE;
> 
>     /** Is PropertyChangeListener attached to original node */
>     private boolean pchlAttached = false;
>     /** children provided or created the default ones? */
>     private boolean childrenProvided;
>     
>     /** Create proxy.
>     * @param original the node to delegate to
>     */
>     public FilterNode(Node original) {
>         this (original, null);
>     }
> 
>     /** Create proxy with a different set of children.
>     *
>     * @param original the node to delegate to
>     * @param children a set of children for this node
>     */
>     public FilterNode(
>         Node original,
>         org.openide.nodes.Children children
>     ) {
>         this (original, children, new FilterLookup ());
>     }    
>     
>     /** Constracts new filter node.
>      * @param original the node we delegate to
>      * @param children the children to use for the filter node or
<code>null</code> if 
>      *    default children should be provided
>      * @param lookup lookup to use
>      *
>      * @since 4.4
>      */
>     public FilterNode (Node original, org.openide.nodes.Children
children, Lookup lookup) {
>         super (
>             children == null ? 
>                 (original.isLeaf () ?
org.openide.nodes.Children.LEAF : new Children (original))
>                 :
>                 children,
>             lookup
>         );
>                 
>         this.childrenProvided = children != null;
>         this.original = original;
>         init ();
>         
>         Lookup lkp = internalLookup (false);
>         if (lkp instanceof FilterLookup) {
>             ((FilterLookup)lkp).ownNode (this);
>         } else {
>             if (lkp == null) {
>                 // rely on default NodeLookup around getCookie. 
>                 getNodeListener();
>             }
>         }
>     }
>     
>     private static final WeakHashMap overridesGetDisplayNameCache =
new WeakHashMap (27);
>     private static final WeakHashMap replaceProvidedLookupCache =
new WeakHashMap (27);
>     /** Overrides package private method of a node that allows us to
say 
>      * that the lookup provided in the constructor should be replaced by
>      * something else
>      *
>      * @param lookup
>      * @return lookup or null
>      */
>     final Lookup replaceProvidedLookup (Lookup lookup) {
>         synchronized (replaceProvidedLookupCache) {
>             Boolean b = (Boolean)replaceProvidedLookupCache.get
(getClass ());
>             if (b == null) {
>                 b = overridesAMethod ("getCookie", new Class[] {
Class.class }) ? Boolean.FALSE : Boolean.TRUE; // NOI18N
>                 replaceProvidedLookupCache.put (getClass (), b);
>             }
>             return b.booleanValue() ? lookup : null;
>         }
>     }
>     
>     /** Checks whether subclass overrides a method
>      */
>     private boolean overridesAMethod (String name, Class[] arguments) {
>         if (getClass () == FilterNode.class) {
>             return false;
>         }
>         
>         
>         // we are subclass of FilterNode
>         try {
>             java.lang.reflect.Method m = getClass ().getMethod
(name, arguments);
> 
>             if (m.getDeclaringClass () != FilterNode.class) {
>                 // ok somebody overriden getCookie method
>                 return true;
>             }
>         } catch (NoSuchMethodException ex) {
>             ErrorManager.getDefault().notify(ex);
>         }
>         
>         return false;
>     }
> 
>     /** Initializes the node.
>     */
>     private void init () {
>         delegateMask = DELEGATE_ALL;
>     }
> 
>     void notifyPropertyChangeListenerAdded( PropertyChangeListener l ) {
>         if ( !pchlAttached ) {
>             original.addPropertyChangeListener
(getPropertyChangeListener ());
>             pchlAttached = true;
>         }  
>     }
>     
>     void notifyPropertyChangeListenerRemoved( PropertyChangeListener
l ) {
>         if ( getPropertyChangeListenersCount() == 0 ) {
>             original.removePropertyChangeListener
(getPropertyChangeListener ());
>             pchlAttached = false;
>         }        
>     }
>     
>     /** Removes all listeners (property and node) on
>     * the original node. Called from {@link NodeListener#nodeDestroyed},
>     * but can be called by any subclass to stop reflecting changes
>     * in the original node.
>     */
>     protected void finalize () {
>         original.removePropertyChangeListener
(getPropertyChangeListener ());
>         original.removeNodeListener (getNodeListener ());
>     }
> 
>     /** Enable delegation of a set of methods.
>     * These will be delegated to the original node.
>     * Since all available methods are delegated by default, normally
you will not need to call this.
>     * @param mask bitwise disjunction of <code>DELEGATE_XXX</code>
constants
>     * @throws IllegalArgumentException if the mask is invalid
>     */
>     protected final void enableDelegation (int mask) {
>         if ((mask & ~DELEGATE_ALL) != 0) throw new
IllegalArgumentException ("Bad delegation mask: " + mask); // NOI18N
>         delegateMask |= mask;
>     }
> 
>     /** Disable delegation of a set of methods.
>     * The methods will retain their behavior from {@link Node}.
>     * <p>For example, if you wish to subclass
<code>FilterNode</code>, giving your
>     * node a distinctive display name and tooltip, and performing
some special
>     * action upon deletion, you may do so without risk of affecting
the original
>     * node as follows:
>     * <br><code><pre>
>     * public MyNode extends FilterNode {
>     *   public MyNode (Node orig) {
>     *     super (orig, new MyChildren (orig));
>     *     disableDelegation (DELEGATE_GET_DISPLAY_NAME |
DELEGATE_SET_DISPLAY_NAME |
>     *                        DELEGATE_GET_SHORT_DESCRIPTION |
DELEGATE_SET_SHORT_DESCRIPTION |
>     *                        DELEGATE_DESTROY);
>     *     // these will affect only the filter node:
>     *     setDisplayName ("Linking -> " + orig.getDisplayName ());
>     *     setShortDescription ("Something different.");
>     *   }
>     *   public boolean canRename () { return false; }
>     *   public void destroy () throws IOException {
>     *     doMyCleanup ();
>     *     super.destroy (); // calls Node.destroy(), not orig.destroy()
>     *   }
>     * }
>     * </pre></code>
>     * <br>You may still manually delegate where desired using {@link
#getOriginal}.
>     * Other methods abstract in <code>Node</code> may simply be
overridden without
>     * any special handling.
>     * @param mask bitwise disjunction of <code>DELEGATE_XXX</code>
constants
>     * @throws IllegalArgumentException if the mask is invalid
>     */
>     protected final void disableDelegation (int mask) {
>         if ((mask & ~DELEGATE_ALL) != 0) throw new
IllegalArgumentException ("Bad delegation mask: " + mask); // NOI18N
>         delegateMask &= ~mask;
>     }
> 
>     /** Test whether we are currently delegating to some method. */
>     private final boolean delegating (int what) {
>         return (delegateMask & what) != 0;
>     }
> 
>     /** Create new filter node for the original.
>     * Subclasses do not have to override this, but if they do not,
>     * the default implementation will filter the subclass filter,
which is not
>     * very efficient.
>     * @return copy of this node
>     */
>     public Node cloneNode () {
>         if (isDefault ()) {
>             // this is realy filter node without changed behaviour
>             // with the normal children => use normal constructor
for the
>             // original node
>             return new FilterNode (original);
>         } else {
>             // create filter node for this node to reflect changed
>             // behaviour
>             return new FilterNode (this);
>         }
>     }
>     
>     
>     /** Changes the original node for this node.
>      *@param original The new original node.
>      *@param changeChildren If set to <CODE>true</CODE> changes children
>      * of this node according to the new original node. If you pass 
>      * children which are not instance of class 
>      * <CODE>FilterNode.Children</CODE> into the constructor set this 
>      * parameter to <CODE>false</CODE>.
>      *@throws java.lang.IllegalStateException if children which are not
>      * instance of <CODE>FilterNode.Children</CODE> were passed
>      * into the constructor and the method was called with the parameter
>      * <CODE>changeChildren</CODE> set to <CODE>true</CODE>.
>      *@since 1.39
>      */
>     protected final void changeOriginal( Node original, boolean
changeChildren ) {
>         
>         if ( changeChildren && 
>             !(getChildren() instanceof FilterNode.Children) &&
>             !(getChildren() == Children.LEAF /* && original.isLeaf
() */)) {
>             throw new IllegalStateException( "Can't change
implicitly defined Children on FilterNode" ); // NOI18N
>         }
>         
>         if (original == this) {
>             throw new IllegalArgumentException ("Cannot be own
original: " + original); // NOI18N
>         }
>         
>         try {
>             Children.PR.enterWriteAccess();
> 
>             // First remove the listeners from current original node
>             this.original.removeNodeListener( getNodeListener() );
>             if ( pchlAttached ) {
>                 this.original.removePropertyChangeListener(
getPropertyChangeListener() );
>             }
> 
>             // Set the new original node
>             this.original = original;
>             
>             // attach listeners to new original node
>             this.original.addNodeListener( getNodeListener() );
>             if ( pchlAttached ) {
>                 this.original.addPropertyChangeListener(
getPropertyChangeListener() );
>             }
> 
>             // Reset children's original node.
>             if ( changeChildren /* && !original.isLeaf () */) {
>                 if ( original.isLeaf() && getChildren() !=
Children.LEAF ) {
>                     setChildren( Children.LEAF );
>                 }
>                 else if ( !original.isLeaf() && getChildren() ==
Children.LEAF ) {
>                     setChildren( new Children( original ) );
>                 }                    
>                 else if ( !original.isLeaf() && getChildren() !=
Children.LEAF) {
>                    
((FilterNode.Children)getChildren()).changeOriginal( original );
>                 }
>             }
>         }
>         finally {
>             Children.PR.exitWriteAccess();
>         }
>         
>         // Fire all sorts of events (everything gets changed after we
>         // reset the original node.)
>         Lookup lkp = internalLookup (false);
>         if (lkp instanceof FilterLookup) {
>             ((FilterLookup)lkp).checkNode();
>         }
>         fireCookieChange();
>         fireNameChange(null, null);
>         fireDisplayNameChange(null, null);
>         fireShortDescriptionChange(null, null);
>         fireIconChange();
>         fireOpenedIconChange();
>         firePropertySetsChange( null, null );
>                 
>     }
> 
>     // ------------- START OF DELEGATED METHODS ------------
> 
>     public void setValue(String attributeName, Object value) {
>         if (delegating (DELEGATE_SET_VALUE)) {
>             original.setValue (attributeName, value);
>         } else {
>             super.setValue (attributeName, value);
>         }
>     }
> 
>     public Object getValue(String attributeName) {
>         if (delegating (DELEGATE_GET_VALUE)) {
>             return original.getValue (attributeName);
>         } else {
>             return super.getValue (attributeName);
>         }
>     }
> 
>     
>     /* Setter for system name. Fires info about property change.
>     * @param s the string
>     */
>     public void setName (String s) {
>         if (delegating (DELEGATE_SET_NAME)) {
>             original.setName (s);
>         } else {
>             super.setName (s);
>         }
>     }
> 
>     /* @return the name of the original node
>     */
>     public String getName () {
>         if (delegating (DELEGATE_GET_NAME)) {
>             return original.getName ();
>         } else {
>             return super.getName ();
>         }
>     }
> 
>     /* Setter for display name. Fires info about property change.
>     * @param s the string
>     */
>     public void setDisplayName (String s) {
>         if (delegating (DELEGATE_SET_DISPLAY_NAME)) {
>             original.setDisplayName (s);
>         } else {
>             super.setDisplayName (s);
>         }
>     }
> 
>     /* @return the display name of the original node
>     */
>     public String getDisplayName () {
>         if (delegating (DELEGATE_GET_DISPLAY_NAME)) {
>             return original.getDisplayName ();
>         } else {
>             return super.getDisplayName ();
>         }
>     }
> 
>     /* Setter for short description. Fires info about property change.
>     * @param s the string
>     */
>     public void setShortDescription (String s) {
>         if (delegating (DELEGATE_SET_SHORT_DESCRIPTION)) {
>             original.setShortDescription (s);
>         } else {
>             super.setShortDescription (s);
>         }
>     }
> 
>     /* @return the description of the original node
>     */
>     public String getShortDescription () {
>         if (delegating (DELEGATE_GET_SHORT_DESCRIPTION)) {
>             return original.getShortDescription ();
>         } else {
>             return super.getShortDescription ();
>         }
>     }
> 
>     /* Finds an icon for this node. Delegates to the original.
>     *
>     * @see java.bean.BeanInfo
>     * @param type constants from <CODE>java.bean.BeanInfo</CODE>
>     * @return icon to use to represent the bean
>     */
>     public Image getIcon (int type) {
>         return original.getIcon (type);
>     }
> 
>     /* Finds an icon for this node. This icon should represent the node
>     * when it is opened (if it can have children). Delegates to
original.
>     *
>     * @see java.bean.BeanInfo
>     * @param type constants from <CODE>java.bean.BeanInfo</CODE>
>     * @return icon to use to represent the bean when opened
>     */
>     public Image getOpenedIcon (int type) {
>         return original.getOpenedIcon (type);
>     }
> 
>     public HelpCtx getHelpCtx () {
>         return original.getHelpCtx ();
>     }
> 
>     /* Can the original node be renamed?
>     *
>     * @return true if the node can be renamed
>     */
>     public boolean canRename () {
>         return original.canRename ();
>     }
> 
>     /* Can the original node be deleted?
>     * @return <CODE>true</CODE> if can, <CODE>false</CODE> otherwise
>     */
>     public boolean canDestroy () {
>         return original.canDestroy ();
>     }
> 
>     /* Degelates the delete operation to original.
>     */
>     public void destroy () throws java.io.IOException {
>         if (delegating (DELEGATE_DESTROY))
>             original.destroy ();
>         else
>             super.destroy ();
>     }
> 
>     /** Used to access the destroy method when original nodes
>     * has been deleted
>     */
>     private final void originalDestroyed () {
>         try {
>             super.destroy ();
>         } catch (IOException ex) {
>            
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
>         }
>     }
> 
>     /* Getter for the list of property sets. Delegates to original.
>     *
>     * @return the array of property sets.
>     */
>     public PropertySet[] getPropertySets () {
>         return original.getPropertySets ();
>     }
> 
>     /* Called when an object is to be copied to clipboard.
>     * @return the transferable object dedicated to represent the
>     *    content of clipboard
>     * @exception IOException is thrown when the
>     *    operation cannot be performed
>     */
>     public Transferable clipboardCopy () throws IOException {
>         return original.clipboardCopy ();
>     }
> 
>     /* Called when an object is to be cut to clipboard.
>     * @return the transferable object dedicated to represent the
>     *    content of clipboard
>     * @exception IOException is thrown when the
>     *    operation cannot be performed
>     */
>     public Transferable clipboardCut () throws IOException {
>         return original.clipboardCut ();
>     }
> 
>     /* Returns true if this object allows copying.
>     * @returns true if this object allows copying.
>     */
>     public boolean canCopy () {
>         return original.canCopy ();
>     }
> 
>     /* Returns true if this object allows cutting.
>     * @returns true if this object allows cutting.
>     */
>     public boolean canCut () {
>         return original.canCut ();
>     }
> 
>     public Transferable drag () throws IOException {
>         return original.drag ();
>     }
> 
>     /* Default implementation that tries to delegate the implementation
>     * to the createPasteTypes method. Simply calls the method and 
>     * tries to take the first provided argument. Ignores the action
>     * argument and index.
>     *
>     * @param t the transferable 
>     * @param action the drag'n'drop action to do
DnDConstants.ACTION_MOVE, ACTION_COPY, ACTION_LINK
>     * @param index index between children the drop occured at or -1
if not specified
>     * @return null if the transferable cannot be accepted or the
paste type
>     *    to execute when the drop occures
>     */
>     public PasteType getDropType (Transferable t, int action, int
index) {
>         return original.getDropType (t, action, index);
>     }
> 
>     /* Which paste operations are allowed when transferable t is in
clipboard?
>     * @param t the transferable in clipboard
>     * @return array of operations that are allowed
>     */
>     public PasteType[] getPasteTypes (Transferable t) {
>         return original.getPasteTypes (t);
>     }
> 
>     /* Support for new types that can be created in this node.
>     * @return array of new type operations that are allowed
>     */
>     public NewType[] getNewTypes () {
>         return original.getNewTypes ();
>     }
> 
>     /* Delegates to original.
>     *
>     * @return array of system actions that should be in popup menu
>     */
>     public SystemAction[] getActions () {
>         if (delegating (DELEGATE_GET_ACTIONS))
>             return original.getActions ();
>         else
>             return super.getActions ();
>     }
> 
>     /* Delegates to original
>     */
>     public SystemAction[] getContextActions () {
>         if (delegating (DELEGATE_GET_CONTEXT_ACTIONS))
>             return original.getContextActions ();
>         else
>             return super.getContextActions ();
>     }
> 
>     /*
>     * @return default action of the original node or null
>     */
>     public SystemAction getDefaultAction () {
>         return original.getDefaultAction ();
>     }
> 
>     public javax.swing.Action[] getActions(boolean context) {
>         if (context) {
>             if (!delegating (DELEGATE_GET_ACTIONS) ||
overridesAMethod ("getContextActions", new Class[0])) // NOI18N
>                 return super.getActions (context);
>         } else {
>             if (!delegating (DELEGATE_GET_CONTEXT_ACTIONS) ||
overridesAMethod ("getActions", new Class[0])) // NOI18N
>                 return super.getActions (context);
>         }
>         
>         javax.swing.Action[] retValue;
>         retValue = original.getActions(context);
>         return retValue;
>     }
>     
>     public javax.swing.Action getPreferredAction() {
>         javax.swing.Action retValue;
>         
>         if (overridesAMethod ("getDefaultAction", new Class[0])) {
// NOI18N
>             retValue = super.getPreferredAction();
>         } else {
>             retValue = original.getPreferredAction();
>         }
>         
>         return retValue;
>     }
>     
>     /** Get a display name containing HTML markup. 
<strong><b>Note:</b> If you subclass
>      * FilterNode and override <code>getDisplayName()</code>, this
method will
>      * always return null unless you override it as well (assuming
that if you're
>      * changing the display name, you don't want an HTML display
name constructed
>      * from the original node's display name to be what shows up in
views of
>      * this node).</strong>  If <code>getDisplayName()</code> is not
overridden,
>      * this method will return whatever the original node returns
from this 
>      * method.
>      * <p>
>      * Note that if you do override <code>getDisplayName</code>, you
should also override
>      * this method to return null.
>      *
>      * 
>      *
>      * @see org.openide.nodes.Node#getHtmlDisplayName
>      * @return An HTML display name, if available, or null if no
display name
>      * is available   */
>     public String getHtmlDisplayName() {
>         if (overridesGetDisplayName()) {
>             return null;
>         } else {
>             return delegating (DELEGATE_GET_DISPLAY_NAME) ? 
>                 original.getHtmlDisplayName() :
super.getHtmlDisplayName();
>         }
>     }
>     
>     private boolean overridesGetDisplayName() {
>         synchronized (overridesGetDisplayNameCache) {
>             Boolean b = (Boolean)overridesGetDisplayNameCache.get
(getClass ());
>             if (b == null) {
>                 b = overridesAMethod ("getDisplayName", null) ?
Boolean.TRUE : Boolean.FALSE; // NOI18N
>                 overridesGetDisplayNameCache.put (getClass (), b);
>             }
>             return b.booleanValue() ? true : false;
>         }
>     }
>     
>     /*
>     * @return <CODE>true</CODE> if the original has a customizer.
>     */
>     public boolean hasCustomizer () {
>         return original.hasCustomizer ();
>     }
> 
>     /* Returns the customizer component.
>     * @return the component or <CODE>null</CODE> if there is no
customizer
>     */
>     public java.awt.Component getCustomizer () {
>         return original.getCustomizer ();
>     }
> 
>     /* Delegates to original, if not special lookup provided in
constructor, 
>     * Otherwise it delegates to the lookup.
>     *
>     * @param type the class to look for
>     * @return instance of that class or null if this class of cookie
>     *    is not supported
>     */
>     public Node.Cookie getCookie (Class type) {
>         Lookup l = internalLookup (true);
>         if (l != null) {
>             Object o = l.lookup (type);
>             if (o instanceof Node.Cookie) {
>                 return (Node.Cookie)o;
>             }
>         }
>         return original.getCookie (type);
>     }
> 
>     /** If this is FilterNode without any changes (subclassed,
changed children)
>     * and the original provides handle, stores them and
>     * returns a new handle for the proxy.
>     * <p>Subclasses <strong>must</strong> override this if they wish
for their nodes to be
>     * properly serializable.
>     *
>     * @return the handle, or <code>null</code> if this node is
subclassed or
>     *    uses changed children
>     */
>     public Node.Handle getHandle () {
>         if (!isDefault ()) {
>             // subclasses has to implement the method by its own
>             return null;
>         }
>         Node.Handle original = this.original.getHandle ();
>         if (original == null) {
>             // no original handle => no handle here
>             return null;
>         }
> 
>         return new FilterHandle (original);
>     }
> 
>     /** Test equality of original nodes.
>     * Note that for subclasses of <code>FilterNode</code>, or filter
nodes with non-default children,
>     * the test reverts to object identity.
>     * <strong>Note:</strong> if you wish that the {@link Index}
cookie works correctly on
>     * filtered nodes and their subnodes, and you are subclassing
<code>FilterNode</code> or
>     * using non-default children, you will probably want to override
this method to test
>     * equality of the specified node with this filter node's
original node; otherwise Move Up
>     * and Move Down actions may be disabled.
>     * <p>Note though that it is often better to provide your own
index cookie from a filter
>     * node. Only then it is possible to change the number of
children relative to the original.
>     * And in many cases this is easier anyway, as for example with
>     * <code>DataFolder.Index</code> for data folders.
>     * @param o something to compare to, presumably a node or
<code>FilterNode</code> of one
>     * @return true if this node's original node is the same as the
parameter (or original node of parameter)
>     */
>     public boolean equals (Object o) {
>         // VERY DANGEROUS! Completely messes up visualizers and
often original node is displayed rather than filter.
>         // Jst: I know that it is dangerous, but some code probably
depends on it
> 
>         if (! (o instanceof Node)) return false; // something else
or null
>         
>         if (this == o) return true; // shortcut
>         
>         // get the "most original" ones....
>         Node left = getRepresentation(this);
>         Node right = getRepresentation((Node)o);
>         
>         // cover nondefault FilterNodes (possibly) deep in the stack
>         if ((left instanceof FilterNode) || (right instanceof
FilterNode)) {
>             return left == right;
>         }
>         
>         return left.equals(right);
>     }
>     
>     private static Node getRepresentation(Node n) {
>         while (n instanceof FilterNode) {
>             FilterNode fn = (FilterNode)n;
>             if ( ! fn.isDefault() ) return n;
>             n = fn.original;
>         }
>         return n; // either node or nondefault FilterNode
>     }
> 
>     private static ThreadLocal hashCodeObjects = new ThreadLocal();
> 
>     /** Hash by original nodes.
>     * Note that for subclasses of <code>FilterNode</code>, or filter
nodes with non-default children,
>     * the hash reverts to the identity hash code.
>     * @return the delegated hash code
>     */
>     public int hashCode () {
> 	Stack callers = (Stack) hashCodeObjects.get();
> 	if (callers == null) {
> 	    callers = new Stack();
> 	    hashCodeObjects.set(callers);
> 	}
> 	for (Iterator it = callers.iterator(); it.hasNext(); ) {
> 	    if (it.next() == this) {
> 		System.out.println("RECURSIVE FilterNode.hashCode: original is a "
+ original.getClass().getName() + "; same as this: " + (original ==
this));
> 		System.out.print("stack:");
> 		for (it = callers.iterator(); it.hasNext(); ) {
> 		    Object o = it.next();
> 		    System.out.print(" ");
> 		    if (o == this)
> 			System.out.print("<<<");
> 		    System.out.print(o.getClass().getName() + "[" +
Integer.toHexString(System.identityHashCode(o)) + "]");
> 		    if (o == this)
> 			System.out.print(">>>");
> 		}
> 		System.out.println(" <loop>");
> 		return super.hashCode();
> 	    }
> 	}
> 	callers.push(this);
>         try {
>             assert hashCodeLogging (true) : ""; // NOI18N
>             int result = isDefault () ? original.hashCode () :
super.hashCode ();
>             assert hashCodeLogging (false) : ""; // NOI18N
>             return result;
>         } catch (StackError err) {
>             err.add (this);
>             throw err;
>         } finally {
> 	    callers.pop();
> 	}
>     }
>     
>     /** Depth of stack trace.
>      */
>     private static volatile int hashCodeDepth;
>     /** Method for tracing the issue 46993. Counts the depth of
execution
>      * and if larger than 1000 throws debugging exception.
>      */
>     private static boolean hashCodeLogging (boolean enter) {
>         if (hashCodeDepth > 1000) {
>             hashCodeDepth = 0;
>             throw new StackError ();
>         }
>         if (enter) {
>             hashCodeDepth++;
>         } else {
>             hashCodeDepth--;
>         }
>         return true;
>     }
> 
>     /** An exception to be thrown from hashCode() to debug issue 46993.
>      */
>     private static class StackError extends StackOverflowError {
>         private java.util.IdentityHashMap nodes;
>         
>         public void add (FilterNode n) {
>             if (nodes == null) {
>                 nodes = new java.util.IdentityHashMap ();
>             }
>             if (nodes.get (n) == null) {
>                 nodes.put (n, n);
>             }
>         }
>         
>         public String getMessage () {
>             StringBuffer sb = new StringBuffer ();
>             sb.append ("StackOver in FilterNodes:\n"); // NOI18N
>             Iterator it = nodes.keySet ().iterator ();
>             while (it.hasNext ()) {
>                 FilterNode f = (FilterNode)it.next ();
>                 sb.append ("  class: "); // NOI18N
>                 sb.append (f.getClass ().getName());
>                 sb.append (" id: "); // NOI18N
>                 sb.append (Integer.toString (System.identityHashCode
(f), 16)); 
>                 sb.append ("\n"); // NOI18N
>             }
>             return sb.toString ();
>         }
>     }
> 
>     //  public String toString () {
>     //    return super.toString () + " original has children: " +
original.getChildren ().getNodesCount (); // NOI18N
>     //  }
> 
>     // ----------- END OF DELEGATED METHODS ------------
> 
>     /** Get the original node.
>     * <p><strong>Yes</strong> this is supposed to be protected! If you
>     * are not subclassing <code>FilterNode</code> yourself, you should
>     * not be calling it (nor casting to <code>FilterNode</code>). Use
>     * cookies instead.
>     * @return the node proxied to
>     */
>     protected Node getOriginal () {
>         return original;
>     }
> 
>     /** Create a property change listener that allows listening on the
>     * original node properties (contained in property sets) and
propagating
>     * them to the proxy.
>     * <P>
>     * This method is called during initialization and allows subclasses
>     * to modify the default behaviour.
>     *
>     * @return a {@link PropertyChangeAdapter} in the default
implementation
>     */
>     protected PropertyChangeListener createPropertyChangeListener () {
>         return new PropertyChangeAdapter (this);
>     }
> 
>     /** Creates a node listener that allows listening on the
>     * original node and propagating events to the proxy.
>     * <p>Intended for overriding by subclasses, as with {@link
#createPropertyChangeListener}.
>     *
>     * @return a {@link FilterNode.NodeAdapter} in the default
implementation
>     */
>     protected NodeListener createNodeListener () {
>         return new NodeAdapter (this);
>     }
> 
>     /** Getter for property change listener.
>     */
>     synchronized PropertyChangeListener getPropertyChangeListener () {
>         if (propL == null) {
>             propL = createPropertyChangeListener ();
>         }
>         return propL;
>     }
> 
>     /** Getter for node listener.
>     */
>     synchronized NodeListener getNodeListener () {
>         if (nodeL == null) {
>             nodeL = createNodeListener ();
>             getOriginal().addNodeListener(nodeL);
>         }
>         return nodeL;
>     }
>     
>     /** Notified from Node that a listener has been added. 
>      * Thus we force initialization of listeners.
>      */
>     final void listenerAdded () {
>         getNodeListener ();
>     }
>     
> 
>     /** Check method whether the node has default behaviour or
>     * if it is either subclass of uses different children.
>     * @return true if it is default
>     */
>     private boolean isDefault () {
>         //System.err.print ("FilterNode.isDefault: ");
>         if (getClass () != FilterNode.class) {
>             //System.err.println("false\n\tsubclass of FilterNode");
>             return false;
>         }
>         
>         return !childrenProvided;
>     }
> 
>     /**
>      * This method is used to change the Children from Children.LEAF
to Children
>      * typically used to when there is a setChildren() on the
original node 
>      * setChildren will fire the appropriate events
>      */
>     final void updateChildren () {
>         if (isDefault ()) {
>             org.openide.nodes.Children newChildren = null;
>             try {
>                 Children.PR.enterReadAccess();
>                 if ( original.hierarchy == Children.LEAF &&
hierarchy != Children.LEAF ) {
>                     newChildren = Children.LEAF;
>                 }
>                 else if ( original.hierarchy != Children.LEAF &&
hierarchy == Children.LEAF ) {
>                     newChildren = new Children (original);
>                 }                    
>             }
>             finally {
>                 Children.PR.exitReadAccess();
>             }
>             
>             if (newChildren != null) {
>                 final org.openide.nodes.Children set = newChildren;
>                 Children.MUTEX.postWriteRequest(new Runnable () {
>                     public void run () {
>                         setChildren (set);
>                     }
>                 });
>             }
>         }
>     }
>         
>     
>     
>     /** Adapter that listens on changes in an original node
>     * and refires them in a proxy.
>     * This adapter is created during
>     * initialization in  {@link
FilterNode#createPropertyChangeListener}. The method
>     * can be overriden and this class used as the super class for the
>     * new implementation.
>     * <P>
>     * A reference to the proxy is stored by weak reference, so it
does not
>     * prevent the node from being finalized.
>     */
>     protected static class PropertyChangeAdapter extends Object
implements PropertyChangeListener {
>         /** weak reference to filter node */
>         private WeakReference fn;
> 
>         /** Create a new adapter.
>         * @param fn the proxy
>         */
>         public PropertyChangeAdapter (FilterNode fn) {
>             this.fn = new WeakReference (fn);
>         }
> 
>         /* Find the node we are attached to. If it is not null call
property
>         * change method with two arguments.
>         */
>         public final void propertyChange (PropertyChangeEvent ev) {
>             FilterNode fn = (FilterNode)this.fn.get ();
>             if (fn == null) {
>                 return;
>             }
> 
>             propertyChange (fn, ev);
>         }
> 
>         /** Actually propagate the event.
>         * Intended for overriding.
>         * @param fn the proxy
>         * @param ev the event
>         */
>         protected void propertyChange (FilterNode fn,
PropertyChangeEvent ev) {
>             fn.firePropertyChange (
>                 ev.getPropertyName (), ev.getOldValue (),
ev.getNewValue ()
>             );
>         }
>     }
> 
>     /** Adapter that listens on changes in an original node and
refires them
>     * in a proxy. Created in {@link FilterNode#createNodeListener}.
>     * @see FilterNode.PropertyChangeAdapter
>     */
>     protected static class NodeAdapter extends Object implements
NodeListener {
>         /** weak reference to filter node */
>         private WeakReference fn;
> 
>         /** Create an adapter.
>         * @param fn the proxy
>         */
>         public NodeAdapter (FilterNode fn) {
>             this.fn = new WeakReference (fn);
>         }
> 
>         /* Tests if the reference to the node provided in costructor is
>         * still valid (it has not been finalized) and if so, calls
propertyChange (Node, ev).
>         */
>         public final void propertyChange (PropertyChangeEvent ev) {
>             FilterNode fn = (FilterNode)this.fn.get ();
>             if (fn == null) {
>                 return;
>             }
>             propertyChange (fn, ev);
>         }
> 
>         /** Actually refire the change event in a subclass.
>         * The default implementation ignores changes of the
<code>parentNode</code> property but refires
>         * everything else.
>         *
>         * @param fn the filter node
>         * @param ev the event to fire
>         */
>         protected void propertyChange (FilterNode fn,
PropertyChangeEvent ev) {
>             String n = ev.getPropertyName ();
>             if (n.equals (Node.PROP_PARENT_NODE)) {
>                 // does nothing
>                 return;
>             }
>             if (n.equals (Node.PROP_DISPLAY_NAME)) {
>                 fn.fireOwnPropertyChange (
>                     PROP_DISPLAY_NAME, (String)ev.getOldValue (),
(String)ev.getNewValue ()
>                 );
>                 return;
>             }
>             if (n.equals (Node.PROP_NAME)) {
>                 fn.fireOwnPropertyChange (
>                     PROP_NAME, (String)ev.getOldValue (),
(String)ev.getNewValue ()
>                 );
>                 return;
>             }
>             if (n.equals (Node.PROP_SHORT_DESCRIPTION)) {
>                 fn.fireOwnPropertyChange (
>                     PROP_SHORT_DESCRIPTION, (String)ev.getOldValue
(), (String)ev.getNewValue ()
>                 );
>                 return;
>             }
>             if (n.equals (Node.PROP_ICON)) {
>                 fn.fireIconChange ();
>                 return;
>             }
>             if (n.equals (Node.PROP_OPENED_ICON)) {
>                 fn.fireOpenedIconChange ();
>                 return;
>             }
>             if (n.equals (Node.PROP_PROPERTY_SETS)) {
>                 fn.firePropertySetsChange
((PropertySet[])ev.getOldValue (), (PropertySet[])ev.getNewValue ());
>                 return;
>             }
>             if (n.equals (Node.PROP_COOKIE)) {
>                 fn.fireCookieChange ();
>                 return;
>             }
>             if (n.equals(Node.PROP_LEAF)) {
>                 fn.updateChildren ();
>                 /*
>                 fn.fireOwnPropertyChange(
>                     Node.PROP_LEAF, ev.getOldValue(), ev.getNewValue() 
>                 );
>                  */
>             }
>         }
> 
>         /** Does nothing.
>         * @param ev event describing the action
>         */
>         public void childrenAdded (NodeMemberEvent ev) {
>         }
> 
>         /** Does nothing.
>         * @param ev event describing the action
>         */
>         public void childrenRemoved (NodeMemberEvent ev) {
>         }
> 
>         /** Does nothing.
>         * @param ev event describing the action
>         */
>         public void childrenReordered (NodeReorderEvent ev) {
>         }
> 
>         /* Does nothing.
>         * @param ev event describing the node
>         */
>         public final void nodeDestroyed (NodeEvent ev) {
>             FilterNode fn = (FilterNode)this.fn.get ();
>             if (fn == null) {
>                 return;
>             }
>             fn.originalDestroyed ();
>         }
>     }
> 
>     /** Children for a filter node. Listens on changes in subnodes of
>     * the original node and asks this filter node to creates
representants for
>     * these subnodes.
>     * <P>
>     * This class is used as the default for subnodes of filter node, but
>     * subclasses may modify it or provide a totally different
implementation.
>      * <p><code>FilterNode.Children</code> is not well suited to
cases where you need to insert
>      * additional nodes at the beginning or end of the list, or
where you may need
>      * to merge together multiple original children lists, or
reorder them, etc.
>      * That is because the keys are of type <code>Node</code>, one
for each original
>      * child, and the keys are reset during {@link #addNotify},
{@link #filterChildrenAdded},
>      * {@link #filterChildrenRemoved}, and {@link
#filterChildrenReordered}, so it is
>      * not trivial to use different keys: you would need to override
<code>addNotify</code>
>      * (calling super first!) and the other three update methods.
For such complex cases
>      * you will do better by creating your own
<code>Children.Keys</code> subclass, setting
>      * keys that are useful to you, and keeping a
<code>NodeListener</code> on the original
>      * node to handle changes.
>     */
>     public static class Children extends
>                 org.openide.nodes.Children.Keys
>         implements Cloneable {
>         /** Original node. Should not be modified. */
>         protected Node original;
>         /** node listener on original */
>         private ChildrenAdapter nodeL;
> 
>         /** Create children.
>          * @param or original node to take children from */
>         public Children (Node or) {
>             original = or;
>         }
> 
>         /** Sets the original children for this children
>          * @param original The new original node.
>          * @since 1.39
>          */
>         protected final void changeOriginal( Node original ) {
>             
>             
>             try {
>                 PR.enterWriteAccess();
> 
>                 boolean wasAttached = nodeL != null;
> 
>                 // uregister from the original node
>                 if ( wasAttached ) {
>                     this.original.removeNodeListener( nodeL );
>                     nodeL = null;
>                 }
> 
>                 // reset the original node
>                 this.original = original;            
> 
>                 if ( wasAttached ) {
>                     addNotifyImpl();
>                 }
>             }
>             finally {
>                 PR.exitWriteAccess();
>             }
>                 
>         }
>         
>         /** Closes the listener, if any, on the original node.
>         */
>         protected void finalize () {
>             if (nodeL != null) original.removeNodeListener (nodeL);
>             nodeL = null;
>         }
> 
>         /* Clones the children object.
>         */
>         public Object clone () {
>             return new Children (original);
>         }
> 
>         /** Initializes listening to changes in original node.
>         */
>         protected void addNotify () {
>             addNotifyImpl();
>         }
>         
>         private void addNotifyImpl () {
>             // add itself to reflect to changes children of original
node
>             nodeL = new ChildrenAdapter (this);
>             original.addNodeListener (nodeL);
> 
>             updateKeys ();
>         }
> 
>         /** Clears current keys, because all mirrored nodes disappeared.
>         */
>         protected void removeNotify () {
>             setKeys (Collections.EMPTY_SET);
> 
>             if (nodeL != null) {
>                 original.removeNodeListener (nodeL);
>                 nodeL = null;
>             }
>         }
> 
> 
> 
>         /** Allows subclasses to override
>         * creation of node representants for nodes in the mirrored
children
>         * list. The default implementation simply uses {@link
Node#cloneNode}.
>         * <p>Note that this method is only suitable for a 1-to-1
mirroring.
>         *
>         * @param node node to create copy of
>         * @return copy of the original node
>         */
>         protected Node copyNode (Node node) {
>             return node.cloneNode ();
>         }
> 
> 
>         /* Implements find of child by finding the original child
and then [PENDING]
>         * @param name of node to find
>         * @return the node or null
>         */
>         public Node findChild (String name) {
>             original.getChildren ().findChild (name);
>             return super.findChild (name);
>         }
> 
> 
>         /** Create nodes representing copies of the original node's
children.
>         * The default implementation returns exactly one
representative for each original node,
>         * as returned by {@link #copyNode}.
>         * Subclasses may override this to avoid displaying a copy of
an original child at all,
>         * or even to display multiple nodes representing the original.
>         * @param key the original child node
>         * @return zero or more nodes representing the original child
node
>         */
>         protected Node[] createNodes (Object key) {
>             Node n = (Node)key;
>             // is run under read access lock so nobody can change
children
>             return new Node[] { copyNode (n) };
>         }
> 
>         /* Delegates to children of the original node.
>         *
>         * @param arr nodes to add
>         * @return true/false
>         */
>         public boolean add (Node[] arr) {
>             return original.getChildren ().add (arr);
>         }
> 
>         /* Delegates to filter node.
>         * @param arr nodes to remove
>         * @return true/false
>         */
>         public boolean remove (Node[] arr) {
>             return original.getChildren ().remove (arr);
>         }
> 
>         /** Called when the filter node adds a new child.
>         * The default implementation makes a corresponding change.
>         * @param ev info about the change
>         */
>         protected void filterChildrenAdded (NodeMemberEvent ev) {
>             updateKeys ();
>         }
> 
>         /** Called when the filter node removes a child.
>         * The default implementation makes a corresponding change.
>         * @param ev info about the change
>         */
>         protected void filterChildrenRemoved (NodeMemberEvent ev) {
>             updateKeys ();
>         }
> 
>         /** Called when the filter node reorders its children.
>         * The default implementation makes a corresponding change.
>         * @param ev info about the change
>         */
>         protected void filterChildrenReordered (NodeReorderEvent ev) {
>             updateKeys ();
>         }
> 
>         /** variable to notify that there is a cyclic update.
>         * Used only in updateKeys method
>         */
>         //    private transient boolean cyclic;
> 
>         /** Update keys from original nodes */
>         private void updateKeys () {
>             ChildrenAdapter runnable = nodeL;
>             if (runnable != null) {
>                 runnable.run ();
>             }
>         }
>                 
>         /**
>          * Implementation that ensures the original node is fully
initialized
>          * if optimal result is requested.
>          *
>          * @param optimalResult if <code>true</code>, the method
will block
>          * until the original node is fully initialized.
>          * @since 3.9
>          */
>         public Node[] getNodes(boolean optimalResult) {
>             if (optimalResult) {
>                 setKeys (original.getChildren ().getNodes (true));
>             }           
>             return getNodes();
>         }
>     }
> 
>     /** Adapter that listens on changes in the original node and
fires them
>     * in this node.
>     * Used as the default listener in {@link FilterNode.Children},
>     * and is intended for refinement by its subclasses.
>     */
>     private static class ChildrenAdapter extends Object
>     implements NodeListener, Runnable {
>         /** children object to notify about addition of children.
>         * Can be null. Set from Children's initNodes method.
>         */
>         private WeakReference children;
> 
>         /** Create a new adapter.
>         * @param ch the children list
>         */
>         public ChildrenAdapter (Children ch) {
>             this.children = new WeakReference (ch);
>         }
>         
>         /** Called to update the content of children.
>          */
>         public void run () {
>             Children ch = (Children)children.get ();
>             if (ch != null) {
>                 Node[] arr = ch.original.getChildren ().getNodes ();
>                 ch.setKeys (arr);
>             }
>         }
> 
>         /** Does nothing.
>         * @param ev the event
>         */
>         public void propertyChange (PropertyChangeEvent ev) {
>         }
> 
>         /* Informs that a set of new children has been added.
>         * @param ev event describing the action
>         */
>         public void childrenAdded (NodeMemberEvent ev) {
>             Children children = (Children)this.children.get ();
>             if (children == null) return;
> 
>             children.filterChildrenAdded (ev);
>         }
> 
>         /* Informs that a set of children has been removed.
>         * @param ev event describing the action
>         */
>         public void childrenRemoved (NodeMemberEvent ev) {
>             Children children = (Children)this.children.get ();
>             if (children == null) return;
> 
>             children.filterChildrenRemoved (ev);
>         }
> 
>         /* Informs that a set of children has been reordered.
>         * @param ev event describing the action
>         */
>         public void childrenReordered (NodeReorderEvent ev) {
>             Children children = (Children)this.children.get ();
>             if (children == null) return;
> 
>             children.filterChildrenReordered (ev);
>         }
> 
> 
>         /** Does nothing.
>         * @param ev the event
>         */
>         public void nodeDestroyed (NodeEvent ev) {
>         }
>     }
> 
>     /** Filter node handle.
>     */
>     private static final class FilterHandle implements Node.Handle {
>         private Node.Handle original;
> 
>         static final long serialVersionUID =7928908039428333839L;
> 
>         public FilterHandle (Node.Handle original) {
>             this.original = original;
>         }
> 
>         public Node getNode () throws IOException {
>             return new FilterNode (original.getNode ());
>         }
> 
>         public String toString () {
>             return "FilterHandle[" + original + "]"; // NOI18N
>         }
>     }
>     
>     /** Special ProxyLookup 
>      */
>     private static final class FilterLookup extends
org.openide.util.Lookup {
>         /** node we belong to */
>         private FilterNode node;
>         /** lookup we delegate too */
>         private Lookup delegate;
>         /** set of all results associated to this lookup */
>         private org.openide.util.WeakSet results;
>         
> 
>         FilterLookup () {
>         }
>         
>         /** Registers own node.
>          */
>         public void ownNode (FilterNode n) {
>             this.node = n;
>         }
>         
>         /** A method that replaces instance of original node
>          * with a new one
>          */
>         private Object replaceNodes (Object orig, Class clazz ) {
>             if (isNodeQuery( clazz ) && orig == node.getOriginal()
&& clazz.isInstance( node )) {
>                 return node;
>             } else {
>                 return orig;
>             }
>         }
> 
>         /** Changes the node we delegate to if necessary.
>          * @param n the node to delegate to
>          */
>         public Lookup checkNode () {
>             Lookup l = node.getOriginal ().getLookup();
>             if (delegate == l) return l;
>             
>             Iterator toCheck = null;
>             synchronized (this) {
>                 if (l != delegate) {
>                     this.delegate = l;
>                     if (results != null) {
>                         toCheck = Arrays.asList (results.toArray
()).iterator();
>                     }
>                 }
>             }
> 
>             if (toCheck != null) {
>                 // update
>                 Iterator it = toCheck;
>                 while (it.hasNext()) {
>                     ProxyResult p = (ProxyResult)it.next ();
>                     if (p.updateLookup (l)) {
>                         p.resultChanged (null);
>                     }
>                 }
>             }
> 
>             return delegate;
>         }
> 
>         public Result lookup(Template template) {
>             ProxyResult p = new ProxyResult (template);
> 
>             synchronized (this) {
>                 if (results == null) {
>                     results = new org.openide.util.WeakSet ();
>                 }
>                 results.add (p);
>             }
> 
>             return p;
>         }
> 
>         public Object lookup(Class clazz) {
>             return replaceNodes (checkNode ().lookup (clazz), clazz );
>         }
> 
>         /** Finds out whether a query for a class can be influenced 
>          * by a state of the "nodes" lookup and whether we should 
>          * initialize listening
>          */
>         private static boolean isNodeQuery (Class c) {
>             return Node.class.isAssignableFrom (c) ||
c.isAssignableFrom (Node.class);
>         }
>         
>         public Item lookupItem(Template template) {
>             Item i = checkNode ().lookupItem (template);
>             return isNodeQuery (template.getType ()) ? new
FilterItem (i, template.getType()) : i;
>         }    
> 
>         /**
>          * Result used in SimpleLookup. It holds a reference to the
collection
>          * passed in constructor. As the contents of this lookup
result never
>          * changes the addLookupListener and removeLookupListener
are empty.
>          */
>         private final class ProxyResult extends Result 
>         implements LookupListener {
>             /** Template used for this result. It is never null.*/
>             private Template template;
>             /** result to delegate to */
>             private Lookup.Result delegate;
>             /** listeners set */
>             private javax.swing.event.EventListenerList listeners;
> 
>             /** Just remembers the supplied argument in variable
template.*/
>             ProxyResult (Template template) {
>                 this.template = template;
>             }
> 
>             /** Checks state of the result
>              */
>             private Result checkResult () {
>                 updateLookup (checkNode ());
>                 return this.delegate;
>             }
> 
>             /** Updates the state of the lookup.
>              * @return true if the lookup really changed
>              */
>             public boolean updateLookup (Lookup l) {
>                 Collection oldPairs = delegate != null ?
delegate.allItems () : null;
> 
>                 synchronized (this) {
>                     if (delegate != null) {
>                         delegate.removeLookupListener (this);
>                     }
>                     delegate = l.lookup (template);
>                     delegate.addLookupListener (this);
>                 }
> 
>                 if (oldPairs == null) {
>                     // nobody knows about a change
>                     return false;
>                 }
> 
>                 Collection newPairs = delegate.allItems ();
> 
>                 return !oldPairs.equals (newPairs);
>             }
> 
> 
>             public synchronized void
addLookupListener(LookupListener l) {
>                 if (listeners == null) {
>                     listeners = new
javax.swing.event.EventListenerList ();
>                 }
>                 listeners.add (LookupListener.class, l);
>             }
> 
>             public synchronized void
removeLookupListener(LookupListener l) {
>                 if (listeners != null) {
>                     listeners.remove (LookupListener.class, l);
>                 }
>             }
> 
>             public java.util.Collection allInstances() {
>                 java.util.Collection c = checkResult ().allInstances ();
>                 
>                 if (isNodeQuery (template.getType ())) {
>                     ArrayList ll = new ArrayList (c.size ());
>                     Iterator it = c.iterator();
>                     while (it.hasNext()) {
>                         ll.add (replaceNodes (it.next (),
template.getType()));
>                     }
>                     return ll;
>                 } else {
>                     return c;
>                 }
>             }
> 
>             public Set allClasses () {
>                 return checkResult ().allClasses ();
>             }
> 
>             public Collection allItems () {
>                 return checkResult ().allItems ();
>             }
> 
>             /** A change in lookup occured.
>              * @param ev event describing the change
>              *
>              */
>             public void resultChanged(LookupEvent anEvent) {
>                 javax.swing.event.EventListenerList l = this.listeners;
>                 if (l == null) return;
> 
>                 Object[] listeners = l.getListenerList();
>                 if (listeners.length == 0) return;
> 
>                 LookupEvent ev = new LookupEvent (this);
>                 for (int i = listeners.length - 1; i >= 0; i -= 2) {
>                     LookupListener ll = (LookupListener)listeners[i];
>                     ll.resultChanged(ev);
>                 }
>             }
>         }  // end of ProxyResult
>         
>         /** Item that exchanges the original node for the FilterNode */
>         private final class FilterItem extends Lookup.Item {
>             private Item delegate;
>             private Class clazz;
>             
>             FilterItem (Item d, Class clazz) {
>                 this.delegate = d;
>                 this.clazz = clazz;
>             }
>             
>             public String getDisplayName() {
>                 return delegate.getDisplayName ();
>             }
>             
>             public String getId() {
>                 return delegate.getId ();
>             }
>             
>             public Object getInstance() {
>                 return replaceNodes (delegate.getInstance (), clazz);
>             }
>             
>             public Class getType() {
>                 return delegate.getType ();
>             }
>         }
>     } // end of FilterLookup
> }

Comment 44 emcmanus 2004-10-07 10:47:03 UTC
This does appear to be a problem with the Hotspot server compiler.
It does not show up when running with -J-client.
It also does not show up if I replace super.hashCode() with 
System.identityHashCode(this).  My suspicion is that the compiler is
incorrectly specializing the hashCode() method in the subclass
org.netbeans.modules.java.ui.NavigationView.FNode (which inherits the
method from FilterNode) and leaving the call to super.hashCode() even
though super is now FilterNode rather than Node (which inherits the
default Object.hashCode()).
I'd suggest doing this replacement in the source code since it doesn't
cost anything and will prevent the problem from showing up with the 
5.0 JVM.
Comment 45 Petr Nejedly 2004-10-07 12:12:49 UTC
Will implement the suggested workaround.
Comment 46 Petr Nejedly 2004-10-07 13:36:46 UTC
Implemented the workaround. Thanks for finding it.
openide/src/org/openide/nodes/FilterNode.java,v1.98
Comment 47 _ rkubacki 2004-10-21 15:56:20 UTC
*** Issue 50451 has been marked as a duplicate of this issue. ***
Comment 48 Petr Hrebejk 2004-11-02 08:35:17 UTC
*** Issue 50939 has been marked as a duplicate of this issue. ***
Comment 49 Jan Chalupa 2004-11-16 08:14:15 UTC
*** Issue 51517 has been marked as a duplicate of this issue. ***
Comment 50 Jan Chalupa 2004-11-18 07:59:25 UTC
*** Issue 51497 has been marked as a duplicate of this issue. ***
Comment 51 scanti 2014-02-22 17:03:34 UTC
We are developing a RCP Application based on NB 7.4
A colleague of mine had this exception:  

org.openide.util.RequestProcessor$SlowItem: task failed due to: org.openide.nodes.FilterNode$StackError: StackOver in FilterNodes:
  class: com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel$CheckableSimulationLinkFilterNode id: 12b18231

	at org.openide.util.RequestProcessor$Task.schedule(RequestProcessor.java:1473)
	at org.openide.nodes.AsynchChildren.addNotify(AsynchChildren.java:89)
	at org.openide.nodes.Children.callAddNotify(Children.java:575)
	at org.openide.nodes.EntrySupportDefault.getArray(EntrySupportDefault.java:650)
	at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:121)
	at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:172)
	at org.openide.nodes.EntrySupportDefault.getNodesCount(EntrySupportDefault.java:176)
	at org.openide.nodes.Children.getNodesCount(Children.java:509)
	at org.openide.explorer.view.VisualizerNode.getChildren(VisualizerNode.java:258)
	at org.openide.explorer.view.VisualizerNode.getChildren(VisualizerNode.java:248)
	at org.openide.explorer.view.VisualizerNode.getChildCount(VisualizerNode.java:325)
	at javax.swing.tree.DefaultTreeModel.getChildCount(DefaultTreeModel.java:186)
	at org.netbeans.swing.outline.DefaultOutlineModel.getChildCount(DefaultOutlineModel.java:236)
	at javax.swing.tree.VariableHeightLayoutCache$TreeStateNode.expand(VariableHeightLayoutCache.java:1478)
	at javax.swing.tree.VariableHeightLayoutCache$TreeStateNode.expand(VariableHeightLayoutCache.java:1287)
	at javax.swing.tree.VariableHeightLayoutCache.rebuild(VariableHeightLayoutCache.java:742)
	at javax.swing.tree.VariableHeightLayoutCache.treeStructureChanged(VariableHeightLayoutCache.java:643)
	at org.netbeans.swing.outline.EventBroadcaster.treeStructureChanged(EventBroadcaster.java:409)
	at javax.swing.tree.DefaultTreeModel.fireTreeStructureChanged(DefaultTreeModel.java:580)
	at javax.swing.tree.DefaultTreeModel.nodeStructureChanged(DefaultTreeModel.java:365)
	at javax.swing.tree.DefaultTreeModel.setRoot(DefaultTreeModel.java:135)
	at org.openide.explorer.view.NodeTreeModel$1.run(NodeTreeModel.java:123)
	at org.openide.util.Mutex.doEvent(Mutex.java:1348)
	at org.openide.util.Mutex.readAccess(Mutex.java:355)
	at org.openide.explorer.view.NodeTreeModel.setNode(NodeTreeModel.java:108)
	at org.openide.explorer.view.NodeTreeModel.setNode(NodeTreeModel.java:104)
	at org.openide.explorer.view.OutlineView.synchronizeRootContext(OutlineView.java:849)
	at org.openide.explorer.view.OutlineView$TableSelectionListener.propertyChange(OutlineView.java:1359)
	at org.openide.util.WeakListenerImpl$PropertyChange.propertyChange(WeakListenerImpl.java:196)
	at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
	at org.openide.explorer.ExplorerManager$2.run(ExplorerManager.java:876)
	at org.openide.util.Mutex.doEvent(Mutex.java:1348)
	at org.openide.util.Mutex.readAccess(Mutex.java:355)
	at org.openide.explorer.ExplorerManager.fireInAWT(ExplorerManager.java:873)
	at org.openide.explorer.ExplorerManager$1SetRootContext.run(ExplorerManager.java:498)
	at org.openide.util.Mutex.readAccess(Mutex.java:372)
	at org.openide.util.Mutex$1R.run(Mutex.java:1314)
	at org.openide.nodes.Children$ProjectManagerDeadlockDetector.execute(Children.java:1921)
	at org.openide.util.Mutex.doWrapperAccess(Mutex.java:1333)
	at org.openide.util.Mutex.readAccess(Mutex.java:361)
	at org.openide.explorer.ExplorerManager.setRootContext(ExplorerManager.java:510)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel.refreshTTV(DataPointSetPanel.java:707)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel.access$400(DataPointSetPanel.java:73)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel$7.propertyChange(DataPointSetPanel.java:279)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel$7.propertyChange(DataPointSetPanel.java:266)
	at com.streamsim.toolpanel.spi.mvc.UpdatablePanel.refresh(UpdatablePanel.java:231)
	at com.streamsim.toolpanel.spi.mvc.UpdatablePanel.updateModel(UpdatablePanel.java:162)
	at com.streamsim.toolpanel.spi.mvc.UpdatablePanel.updateModel(UpdatablePanel.java:125)
	at com.streamsim.toolpanel.spi.mvc.ToolPanelPanelMVC.updateModel(ToolPanelPanelMVC.java:261)
	at com.streamsim.toolpanel.spi.mvc.ToolPanelPanelMVC.updateModel(ToolPanelPanelMVC.java:253)
	at com.streamsim.toolpanel.spi.mvc.ToolPanelPanelMVC.access$200(ToolPanelPanelMVC.java:30)
	at com.streamsim.toolpanel.spi.mvc.ToolPanelPanelMVC$1$1.run(ToolPanelPanelMVC.java:59)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
	at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: org.openide.nodes.FilterNode$StackError: StackOver in FilterNodes:
  class: com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel$CheckableSimulationLinkFilterNode id: 12b18231

	at org.openide.nodes.FilterNode.hashCodeLogging(FilterNode.java:940)
	at org.openide.nodes.FilterNode.hashCode(FilterNode.java:925)
	at java.util.HashMap.hash(HashMap.java:351)
	at java.util.HashMap.put(HashMap.java:471)
	at org.openide.nodes.Children$Dupl.updateListAndMap(Children.java:1731)
	at org.openide.nodes.Children$Dupl.updateList(Children.java:1704)
	at org.openide.nodes.Children$Keys.setKeys(Children.java:1503)
	at org.openide.nodes.AsynchChildren$1.add(AsynchChildren.java:190)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel.addNodesToList(DataPointSetPanel.java:1027)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel.access$3000(DataPointSetPanel.java:73)
	at com.streamsim.metricspaceplots.mds.panels.DataPointSetPanel$RunFactory.createKeys(DataPointSetPanel.java:1047)
	at org.openide.nodes.AsynchChildren.run(AsynchChildren.java:209)
	at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1432)
	at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2042)


There was a high number of nodes, more than 900. He was using a server jre
Here more information:

Diagnostic information
Input arguments:
	-Dnetbeans.logger.console=true
	-ea
	-server
	-Xss2m
	-Xms128m
	-XX:PermSize=128m
	-XX:MaxPermSize=200m
	-Xverify:none
	-XX:+UseAdaptiveSizePolicy
	-Djava.net.useSystemProxies=true
	-Dorg.netbeans.ProxyClassLoader.level=1000
	-Dnetbeans.logger.console=true
	-Dorg.netbeans.modules.autoupdate.level=INFO
	-Dnetbeans.keep.expansion=false
	-XX:+UseCompressedStrings
	-XX:+UseStringCache
	-Djdk.home=C:\Program Files\Java\jdk1.7.0_25
	-splash:C:\Users\Darryl\Code\trunk\studioSL\suite_studioSL\build\testuserdir\var\cache\splash.png
	-Dnetbeans.home=C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\platform
	-Dnetbeans.user=C:\Users\Darryl\Code\trunk\studioSL\suite_studioSL\build\testuserdir
	-Dnetbeans.default_userdir_root=
	-XX:+HeapDumpOnOutOfMemoryError
	-XX:HeapDumpPath=C:\Users\Darryl\Code\trunk\studioSL\suite_studioSL\build\testuserdir\var\log\heapdump.hprof
	-Dsun.awt.keepWorkingSetOnMinimize=true
	-Dnetbeans.dirs=C:\Users\Darryl\Code\trunk\studioSL\suite_studioSL\build\cluster;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\dlight;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\extide;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\harness;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\ide;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\java;C:\Users\Darryl\Code\netbeans-7.4p2\netbeans\platform;C:\Users\Darryl\Code\trunk\commons\suite_commons\build\cluster
	exit
Compiler: HotSpot 64-Bit Tiered Compilers
Heap memory usage: initial 128.0MB maximum 2723.6MB
Non heap memory usage: initial 130.4MB maximum 248.0MB
Garbage collector: PS Scavenge (Collections=10 Total time spent=0s)
Garbage collector: PS MarkSweep (Collections=1 Total time spent=0s)
Classes: loaded=7083 total loaded=7083 unloaded 0
INFO [org.netbeans.core.ui.warmup.DiagnosticTask]: Total memory 12,846,387,200
Comment 52 Ondrej Vrabec 2014-02-22 17:24:37 UTC
please do not reopen prehistoric issues, in case you see something similar, file a new issue with a complete IDE log attached.