Index: FolderChildren.java =================================================================== RCS file: /cvs/openide/src/org/openide/loaders/FolderChildren.java,v retrieving revision 1.62 diff -r1.62 FolderChildren.java 24a25 > import org.openide.util.NbBundle; 26a28 > import org.openide.nodes.AbstractNode; 39,42d40 < /** initialization of children task */ < private Task initTask; < /** last task that refreshes the children nodes */ < private Task refreshTask; 46a45,58 > > /** Private req processor for the refresh tasks */ > private static RequestProcessor refRP = > new RequestProcessor("FolderChildren_refresher"); > > /** The key used to denote the please wait node. > * It is also used as a lock for the lazy initializaiton > * of the pleaseWaitNode. > */ > private static final Object PLEASE_WAIT_KEY = new Object(); > > /** wait node - please use method getPleaseWaitNode() > * to get a lazy initialized instance */ > private static Node pleaseWaitNode; 96c108 < initialize (true, false); --- > refRP.post(new ChildrenRefreshRunnable(false)); 99,118c111,127 < /** Creates a key for given data object. < * This method is here to create something different then data object, < * because the data object should be finalized when not needed and < * that is why it should not be used as a key. < * < * @param obj data object < * @return key representing the data object. < */ < static Object createKey (DataObject obj) { < return new Pair (obj.getPrimaryFile ()); < } < < /** This method takes the key created by createKey and converts it < * into primary file. < * < * @param key the key < * @return primary file of the key < */ < private static FileObject getFile (Object key) { < return ((Pair)key).primaryFile; --- > /** Lazy initialization of the please wait node */ > private static Node getPleaseWaitNode() { > boolean created = false; > synchronized (PLEASE_WAIT_KEY) { > if (pleaseWaitNode == null) { > pleaseWaitNode = new AbstractNode(Children.LEAF); > created = true; > } > } > if (created) { > pleaseWaitNode.setName("wait"); // NOI18N > pleaseWaitNode.setDisplayName( > NbBundle.getBundle(FolderChildren.class).getString("LBL_Wait") > ); > ((AbstractNode)pleaseWaitNode).setIconBase("org/openide/resources/wait"); //NOI18N > } > return pleaseWaitNode; 120c129 < --- > 124a134,136 > if (key == PLEASE_WAIT_KEY) { > return new Node[] { getPleaseWaitNode() }; > } 126c138 < FileObject fo = getFile (key); --- > FileObject fo = ((Pair)key).primaryFile; 141,183c153,158 < < /** Improves the searching capability to wait till all children < * are found and then searching thru them. < */ < public Node findChild (final String name) { < // start the initialization < Node[] forget = getNodes (); // DO NOT DELETE < < // waits till the list of children is created < < // JST: the folowing code is replacement for < // initialize (false, false).waitFinished () < // < // the orgiginal code caused deadlocks when called with readAccess, < // because the refreshChildren (which we wait for to be finished) < // method calls setKeys and they require write request < // < // this code could probably be replaced by < // Children.MUTEX.isReadAccess, if such call would be added to Mutex < class Jst implements Runnable { < public boolean checkReadOrWrite; < public boolean inReadAccess = true; < public boolean inWriteAccess = true; < public void run () { < if (checkReadOrWrite) { < inReadAccess = false; < } else { < inWriteAccess = false; < } < } < } < Jst t = new Jst (); < // the code will run either immediatally or after we leave readAccess < // section < Children.MUTEX.postWriteRequest(t); < t.checkReadOrWrite = true; < Children.MUTEX.postReadRequest(t); < < if (!t.inReadAccess && !t.inWriteAccess) { < // if we are not in readAccess we can safely wait till < // refreshChildren finishes and sets new keys for the < initialize (name == null, false).waitFinished (); < refreshTask.waitFinished (); --- > > public Node[] getNodes(boolean optimalResult) { > if (optimalResult) { > Task t = refRP.post(new ChildrenRefreshRunnable(false)); > t.waitFinished(); > return getNodes(); 185,188c160 < < // do the regular child lookup < Node node = super.findChild (name); < return node; --- > return super.getNodes(optimalResult); 190c162 < --- > 194c166,167 < initialize (true, true); --- > // set the please wait node > setKeys (java.util.Collections.singleton(PLEASE_WAIT_KEY)); 196a170,171 > // start the refresh task > refreshChildren(); 204,234d178 < setKeys (java.util.Collections.EMPTY_SET); < } < < /** Ensures that the content of children will be filled sometime. < * @param force true if the content should be filled immediatelly < */ < private Task initialize (boolean force, boolean waitFirst) { < < Task t = initTask; < < if (t != null && t.isFinished()) { < // if the original refresh task is finished we whould check if there are < // some new changes in progress and wait for them to finish < FolderList l = FolderList.find (folder.getPrimaryFile(), true); < l.waitProcessingFinished (); < < t = initTask; < } < < if (t != null && !force) { < return t; < } < < // if (t != null) { < // t.waitFinished (); < // refreshTask.waitFinished (); < // return t; < // } < < final Addition add = new Addition (waitFirst); < refreshTask = add.refTask; 236,243c180,184 < initTask = t = folder.computeChildrenList (add); < t.addTaskListener (add); < < if (waitFirst) { < add.waitFirst (); < } < < return t; --- > // the parameter true means to set the children to empty > // we don't call the setKeys directly here because > // there can be a task spawned by refreshChildren - so > // we want to clear the children after that task is finished > refRP.post(new ChildrenRefreshRunnable(true)); 251,365c192,203 < /** time delay between two inserts of nodes */ < private static final int TIME_DELAY = 1024; < < /** Private req processor for Addition's refresh tasks */ < private static RequestProcessor refRP = < new RequestProcessor("FolderChildren_refresher"); < < /** Support for incremental adding of new nodes. < * < *
< * There is a deadlock warning: < *