KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > loaders > DataObjectInvalidationTest


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.loaders;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.beans.PropertyChangeListener JavaDoc;
28 import java.lang.ref.WeakReference JavaDoc;
29 import java.util.logging.Level JavaDoc;
30 import java.util.logging.Logger JavaDoc;
31 import org.openide.ErrorManager;
32
33 import org.openide.filesystems.*;
34 import org.openide.nodes.*;
35
36 // XXX to do:
37
// - loaders are never asked to recognize an invalid file object (#13926)
38

39 /** Test invalidation of objects: getting of node delegate,
40  * whether folder instances include them, whether loaders are
41  * asked to recognize invalid objects, etc.
42  * @author Jesse Glick
43  */

44 public class DataObjectInvalidationTest extends LoggingTestCaseHid {
45     Logger JavaDoc log;
46     
47     public DataObjectInvalidationTest(String JavaDoc name) {
48         super(name);
49     }
50
51     protected Level JavaDoc logLevel() {
52         return Level.FINE;
53     }
54     
55     protected void setUp() throws IOException JavaDoc {
56         clearWorkDir();
57
58         log = Logger.getLogger("TEST-" + getName());
59         registerIntoLookup(new Pool());
60     }
61     
62     protected void tearDown() throws Exception JavaDoc {
63         WeakReference JavaDoc ref = new WeakReference JavaDoc(DataLoader.getLoader(SlowDataLoader.class));
64         Pool.setExtra(null);
65         assertGC("Let's cleanup all nodes, data objects created in previous test", ref);
66     }
67     
68     public void testNobodyCanAccessDataObjectWithUnfinishedConstructor () throws Throwable JavaDoc {
69         FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), new String JavaDoc[] {
70             "folder/file.slow",
71         });
72         final FileObject file = lfs.findResource("folder/file.slow");
73         assertNotNull(file);
74         
75         final DataLoader l = DataLoader.getLoader(SlowDataLoader.class);
76         Pool.setExtra(l);
77         class DoTheWork extends Object JavaDoc implements Runnable JavaDoc {
78             private DataObject first;
79             /** any eception from run method */
80             private Throwable JavaDoc ex;
81             /** thread that shall call into the constructor */
82             private Thread JavaDoc constructor;
83
84             public void runInMainThread () throws Throwable JavaDoc {
85                 wait (); // notified from HERE
86

87                 // I am going to be the constructor of the SlowDataObject
88
constructor = Thread.currentThread();
89                 first = DataObject.find (file);
90
91
92                 // waiting for results
93
wait ();
94                 if (ex != null) {
95                     throw ex;
96                 }
97             }
98
99             public void run () {
100                 try {
101                     synchronized (l) {
102                         synchronized (this) {
103                             notifyAll (); // HERE
104
}
105
106                         // this wait is notified from the midle of SlowDataObject
107
// constructor
108
l.wait ();
109
110                         // that means the thread in runInMainThread() have not finished
111
// the assignment to first variable yet
112
assertNull (first);
113                     }
114
115                     // now try to get the DataObject while its constructor
116
// is blocked in the case
117
DataObject obj = DataObject.find (file);
118                     assertEquals ("It is the slow obj", SlowDataObject.class, obj.getClass());
119                     SlowDataObject slow = (SlowDataObject)obj;
120
121                     assertEquals ("Constructor has to finish completely, by the main thread", constructor, slow.ok);
122
123                 } catch (Throwable JavaDoc ex) {
124                     this.ex = ex;
125                 } finally {
126                     synchronized (this) {
127                         notify ();
128                     }
129                 }
130             }
131         }
132
133         DoTheWork dtt = new DoTheWork();
134         synchronized (dtt) {
135             new Thread JavaDoc (dtt, "Slow").start ();
136             dtt.runInMainThread ();
137         }
138
139
140     }
141     
142     public void testNodeDelegateNotRequestedTillObjReady() throws Exception JavaDoc {
143         FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), new String JavaDoc[] {
144             "folder/file.slow",
145         });
146         FileObject folder = lfs.findResource("folder");
147         assertNotNull(folder);
148         DataLoader l = DataLoader.getLoader(SlowDataLoader.class);
149         Pool.setExtra(l);
150         DataFolder f = DataFolder.findFolder(folder);
151         Node foldernode = f.getNodeDelegate();
152         Children folderkids = foldernode.getChildren();
153         // Force it to recognize its children:
154
Node[] nodes = folderkids.getNodes(true);
155         assertEquals("Number of children", 1, nodes.length);
156         assertEquals("Correct node delegate", "slownode", nodes[0].getShortDescription());
157     }
158     
159     /** See #15902.
160      * If a filesystem changes root, existing file objects become invalid
161      * and any data objects from them must also become invalid quickly.
162      */

163     public void testDataObjectInvalidatedAfterRootChange() throws Exception JavaDoc {
164         LocalFileSystem lfs = (LocalFileSystem)TestUtilHid.createLocalFileSystem(getWorkDir (), new String JavaDoc[] {
165             "folder/file.simple",
166         });
167         Repository.getDefault().addFileSystem(lfs);
168         try {
169             FileObject fo = lfs.findResource("folder/file.simple");
170             DataLoader l = DataLoader.getLoader(DataLoaderOrigTest.SimpleUniFileLoader.class);
171             Pool.setExtra(l);
172             DataObject dob = DataObject.find(fo);
173             assertEquals(l, dob.getLoader());
174             assertTrue(fo.isValid());
175             assertTrue(dob.isValid());
176             File JavaDoc olddir = lfs.getRootDirectory();
177             File JavaDoc newdir = new File JavaDoc(olddir, "folder");
178             //File newdir = olddir.getParentFile();
179
assertTrue(newdir.exists());
180             ExpectingListener el = new ExpectingListener();
181             lfs.addPropertyChangeListener(el);
182             lfs.setRootDirectory(newdir);
183             assertTrue("PROP_ROOT was fired", el.gotSomething(FileSystem.PROP_ROOT));
184             assertTrue("PROP_SYSTEM_NAME was fired", el.gotSomething(FileSystem.PROP_SYSTEM_NAME));
185             FileObject fo2 = lfs.findResource("file.simple");
186             assertNotNull(fo2);
187             assertTrue(fo != fo2);
188             DataObject dob2 = DataObject.find(fo2);
189             assertEquals(l, dob2.getLoader());
190             assertTrue(dob != dob2);
191             assertTrue("FileSystem is still valid after change in root directory", lfs.isValid());
192             assertTrue(fo == dob.getPrimaryFile());
193             //assertTrue(fo.getFileSystem() == lfs);
194
if (fo.isValid()) {
195                 // Just in case it needs time to be invalidated:
196
Thread.sleep(1000);
197             }
198             // Does nothing: lfs.getRoot().refresh()
199
// Currently this fails, not sure why:
200
assertTrue("FileObject invalidated after change in root directory", ! fo.isValid());
201             assertTrue("DataObject invalidated after change in root directory", ! dob.isValid());
202         } finally {
203             Repository.getDefault().removeFileSystem(lfs);
204         }
205         TestUtilHid.destroyLocalFileSystem(getName());
206     }
207     
208     public void testCopyAndTemplateWorks () throws Exception JavaDoc {
209         String JavaDoc[] arr = new String JavaDoc[] {
210             "folder/file.slow",
211         };
212         FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), arr);
213         FileObject file = lfs.findResource(arr[0]);
214         DataLoader l = DataLoader.getLoader(SlowDataLoader.class);
215         Pool.setExtra(l);
216         try {
217             DataObject obj = DataObject.find (file);
218             DataFolder f = DataFolder.findFolder(file.getFileSystem().getRoot());
219             obj.copy (f);
220             obj.createFromTemplate(f);
221         } finally {
222             TestUtilHid.destroyLocalFileSystem(getName());
223         }
224     }
225
226     public void testInvalidationHappensImmediatelly () throws Exception JavaDoc {
227         String JavaDoc[] arr = new String JavaDoc[] {
228             "folder/file.slow",
229         };
230         FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), arr);
231         FileObject file = lfs.findResource(arr[0]);
232         
233         DataObject obj = DataObject.find (file);
234         DataObject newObj;
235         
236         DataLoader l = DataLoader.getLoader(SlowDataLoader.class);
237         Pool.setExtra(l);
238         try {
239             assertFalse ("The previous data object is not valid anymore", obj.isValid ());
240             newObj = DataObject.find (file);
241             assertTrue ("This is valid", newObj.isValid ());
242         } finally {
243             TestUtilHid.destroyLocalFileSystem(getName());
244             Pool.setExtra(null);
245         }
246         
247         assertFalse ("After remove, it is invalidated", newObj.isValid ());
248         
249         DataObject again = DataObject.find (file);
250         
251         assertEquals ("The same loader as before", obj.getLoader (), again.getLoader ());
252     }
253     
254     private static final class ExpectingListener implements PropertyChangeListener JavaDoc {
255         private final Set JavaDoc changes = new HashSet JavaDoc(); // Set<String>
256
public synchronized void propertyChange(PropertyChangeEvent JavaDoc ev) {
257             changes.add(ev.getPropertyName());
258             //System.err.println("got: " + ev.getSource() + " " + ev.getPropertyName() + " " + ev.getOldValue() + " " + ev.getNewValue());//XXX
259
notifyAll();
260         }
261         public synchronized boolean gotSomething(String JavaDoc prop) throws InterruptedException JavaDoc {
262             if (changes.contains(prop)) return true;
263             wait(3000);
264             return changes.contains(prop);
265         }
266     }
267     
268     public static final class SlowDataLoader extends UniFileLoader {
269         public static int createCount = 0;
270         private static Logger JavaDoc ERR = Logger.getLogger("SlowDataLoader");
271         public SlowDataLoader() {
272             super(SlowDataObject.class.getName());
273         }
274         protected void initialize() {
275             super.initialize();
276             getExtensions().addExtension("slow");
277         }
278         protected String JavaDoc displayName() {
279             return "Slow";
280         }
281         protected MultiDataObject createMultiObject(FileObject pf) throws IOException JavaDoc {
282             ERR.info("in createMultiObject for: " + pf);
283             SlowDataObject o = new SlowDataObject(pf, this);
284             ERR.info("created object : " + o);
285             //new Exception("creating for: " + pf + " count=" + createCount).printStackTrace();
286
return o;
287         }
288     }
289     public static final class SlowDataObject extends MultiDataObject {
290         public Thread JavaDoc ok;
291         public static int createCount = 0;
292         public SlowDataObject(FileObject pf, MultiFileLoader loader) throws IOException JavaDoc {
293             super(pf, loader);
294             synchronized (loader) {
295                 SlowDataLoader.ERR.info("Incrementing SlowDataObject count to " + ++createCount);
296                 SlowDataLoader.ERR.info("Incrementing SlowDataLoader count to " + ++SlowDataLoader.createCount);
297                 
298                 // in case somebody is listening on the loader for our creation
299
// let him wake up
300
SlowDataLoader.ERR.info("Wake up sleepers");
301                 loader.notifyAll ();
302             }
303             
304             int cnt = 1;
305             
306             while (cnt-- > 0) {
307                 try {
308                     Thread.sleep(2000);
309                 } catch (InterruptedException JavaDoc ie) {
310                     throw new IOException JavaDoc(ie.toString());
311                 }
312             }
313             
314             
315             ok = Thread.currentThread();
316             SlowDataLoader.ERR.info("End of constructor");
317         }
318         protected Node createNodeDelegate() {
319             return new SlowDataNode(this);
320         }
321         
322         protected DataObject handleCopy (DataFolder df) throws java.io.IOException JavaDoc {
323             FileObject fo = this.getPrimaryEntry().copy (df.getPrimaryFile(), "slow");
324             return new SlowDataObject (fo, (MultiFileLoader)this.getLoader());
325         }
326         protected DataObject handleCreateFromTemplate (DataFolder df, String JavaDoc s) throws java.io.IOException JavaDoc {
327             FileObject fo = this.getPrimaryEntry().createFromTemplate (df.getPrimaryFile(), null);
328             return new SlowDataObject (fo, (MultiFileLoader)this.getLoader());
329         }
330     }
331     public static final class SlowDataNode extends DataNode {
332         public SlowDataNode(SlowDataObject o) {
333             super(o, Children.LEAF);
334             if (o.ok == null) throw new IllegalStateException JavaDoc("getDataNode called too early");
335             // Serve as a marker that this is the correct data node kind
336
// (instanceof will not work because of filter nodes):
337
setShortDescription("slownode");
338         }
339     }
340
341     private static final class Pool extends DataLoaderPool {
342         private static DataLoader extra;
343         
344         
345         protected java.util.Enumeration JavaDoc loaders () {
346             if (extra == null) {
347                 return org.openide.util.Enumerations.empty ();
348             } else {
349                 return org.openide.util.Enumerations.singleton (extra);
350             }
351         }
352
353         public static void setExtra(DataLoader aExtra) {
354             if (aExtra != null && extra != null) {
355                 fail("Cannot set extra loader while one is already there. 1: " + extra + " 2: " + aExtra);
356             }
357             extra = aExtra;
358             Pool p = (Pool)DataLoaderPool.getDefault();
359             p.fireChangeEvent(new javax.swing.event.ChangeEvent JavaDoc(p));
360         }
361     }
362 }
363
Popular Tags