1 19 20 package org.openide.loaders; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.beans.PropertyChangeEvent ; 25 import java.util.HashSet ; 26 import java.util.Set ; 27 import java.beans.PropertyChangeListener ; 28 import java.lang.ref.WeakReference ; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 import org.openide.ErrorManager; 32 33 import org.openide.filesystems.*; 34 import org.openide.nodes.*; 35 36 39 44 public class DataObjectInvalidationTest extends LoggingTestCaseHid { 45 Logger log; 46 47 public DataObjectInvalidationTest(String name) { 48 super(name); 49 } 50 51 protected Level logLevel() { 52 return Level.FINE; 53 } 54 55 protected void setUp() throws IOException { 56 clearWorkDir(); 57 58 log = Logger.getLogger("TEST-" + getName()); 59 registerIntoLookup(new Pool()); 60 } 61 62 protected void tearDown() throws Exception { 63 WeakReference ref = new WeakReference (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 { 69 FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), new String [] { 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 implements Runnable { 78 private DataObject first; 79 80 private Throwable ex; 81 82 private Thread constructor; 83 84 public void runInMainThread () throws Throwable { 85 wait (); 87 constructor = Thread.currentThread(); 89 first = DataObject.find (file); 90 91 92 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 (); } 105 106 l.wait (); 109 110 assertNull (first); 113 } 114 115 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 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 (dtt, "Slow").start (); 136 dtt.runInMainThread (); 137 } 138 139 140 } 141 142 public void testNodeDelegateNotRequestedTillObjReady() throws Exception { 143 FileSystem lfs = TestUtilHid.createLocalFileSystem(getWorkDir (), new String [] { 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 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 163 public void testDataObjectInvalidatedAfterRootChange() throws Exception { 164 LocalFileSystem lfs = (LocalFileSystem)TestUtilHid.createLocalFileSystem(getWorkDir (), new String [] { 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 olddir = lfs.getRootDirectory(); 177 File newdir = new File (olddir, "folder"); 178 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 if (fo.isValid()) { 195 Thread.sleep(1000); 197 } 198 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 { 209 String [] arr = new String [] { 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 { 227 String [] arr = new String [] { 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 { 255 private final Set changes = new HashSet (); public synchronized void propertyChange(PropertyChangeEvent ev) { 257 changes.add(ev.getPropertyName()); 258 notifyAll(); 260 } 261 public synchronized boolean gotSomething(String prop) throws InterruptedException { 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 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 displayName() { 279 return "Slow"; 280 } 281 protected MultiDataObject createMultiObject(FileObject pf) throws IOException { 282 ERR.info("in createMultiObject for: " + pf); 283 SlowDataObject o = new SlowDataObject(pf, this); 284 ERR.info("created object : " + o); 285 return o; 287 } 288 } 289 public static final class SlowDataObject extends MultiDataObject { 290 public Thread ok; 291 public static int createCount = 0; 292 public SlowDataObject(FileObject pf, MultiFileLoader loader) throws IOException { 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 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 ie) { 310 throw new IOException (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 { 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 s) throws java.io.IOException { 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 ("getDataNode called too early"); 335 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 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 (p)); 360 } 361 } 362 } 363 | Popular Tags |