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.

View | Details | Raw Unified | Return to bug 20022
Collapse All | Expand All

(-)loaders/src/org/openide/loaders/DataLoaderPool.java (-8 / +3 lines)
Lines 355-363 Link Here
355
        // try to find assigned loader
355
        // try to find assigned loader
356
        DataLoader pref = getPreferredLoader (fo);
356
        DataLoader pref = getPreferredLoader (fo);
357
        if (pref != null) {
357
        if (pref != null) {
358
            DataObject obj = pref.findDataObject (fo, r);
358
            DataObject obj = DataObjectPool.findDataObject (pref, fo, r);
359
            if (obj != null) {
359
            if (obj != null) {
360
                DataObjectPool.getPOOL().notifyCreation (obj);
361
                // file has been recognized
360
                // file has been recognized
362
                return obj;
361
                return obj;
363
            }
362
            }
Lines 367-379 Link Here
367
        java.util.Enumeration en = allLoaders ();
366
        java.util.Enumeration en = allLoaders ();
368
        while (en.hasMoreElements ()) {
367
        while (en.hasMoreElements ()) {
369
            DataLoader l = (DataLoader)en.nextElement ();
368
            DataLoader l = (DataLoader)en.nextElement ();
370
            DataObject obj = l.findDataObject (fo, r);
369
    
370
            DataObject obj = DataObjectPool.findDataObject (l, fo, r);
371
            if (obj != null) {
371
            if (obj != null) {
372
                // the loader recognized the file
373
                
374
                // notify it
375
                DataObjectPool.getPOOL().notifyCreation (obj);
376
                
377
                return obj;
372
                return obj;
378
            }
373
            }
379
        }
374
        }
(-)loaders/src/org/openide/loaders/DataObject.java (+1 lines)
Lines 448-453 Link Here
448
            if (obj != null) {
448
            if (obj != null) {
449
                return obj;
449
                return obj;
450
            }
450
            }
451
                
451
            throw new DataObjectNotFoundException (fo);
452
            throw new DataObjectNotFoundException (fo);
452
        } catch (DataObjectExistsException ex) {
453
        } catch (DataObjectExistsException ex) {
453
            return ex.getDataObject ();
454
            return ex.getDataObject ();
(-)loaders/src/org/openide/loaders/DataObjectPool.java (-57 / +30 lines)
Lines 32-38 Link Here
32
* @author Jaroslav Tulach
32
* @author Jaroslav Tulach
33
*/
33
*/
34
final class DataObjectPool extends Object
34
final class DataObjectPool extends Object
35
implements ChangeListener, RepositoryListener, PropertyChangeListener, Runnable {
35
implements ChangeListener, RepositoryListener, PropertyChangeListener {
36
    /** set to non null if the constructor is called from somewhere else than DataObject.find */
37
    private static final ThreadLocal FIND = new ThreadLocal ();
36
    /** validator */
38
    /** validator */
37
    private static final Validator VALIDATOR = new Validator ();
39
    private static final Validator VALIDATOR = new Validator ();
38
    
40
    
Lines 68-73 Link Here
68
        return POOL;
70
        return POOL;
69
    }
71
    }
70
    
72
    
73
    /** Calls into one loader. Setups security condition to allow DataObject ocnstructor
74
     * to succeed.
75
     */
76
    public static DataObject findDataObject (DataLoader loader, FileObject fo, DataLoader.RecognizedFiles rec) 
77
    throws java.io.IOException {
78
        DataObject ret;
79
        
80
        Object prev = FIND.get ();
81
        try {
82
            FIND.set (loader);
83
            
84
            ret = loader.findDataObject (fo, rec);
85
        } finally {
86
            FIND.set (prev);
87
        }
88
        
89
        // notify it
90
        if (ret != null) {
91
            DataObjectPool.getPOOL().notifyCreation (ret);
92
        }
93
        
94
        return ret;
95
    }
96
    
71
    /** Collection of all objects that has been created but their
97
    /** Collection of all objects that has been created but their
72
    * creation has not been yet notified to OperationListener.postCreate
98
    * creation has not been yet notified to OperationListener.postCreate
73
    * method.
99
    * method.
Lines 96-121 Link Here
96
     */
122
     */
97
    private ThreadLocal last = new ThreadLocal ();
123
    private ThreadLocal last = new ThreadLocal ();
98
    
124
    
99
    /** Time when the toNotify set has been modified.
100
     */
101
    private long toNotifyModified;
102
    /** A delay to check the notify modified content. It is expected that
125
    /** A delay to check the notify modified content. It is expected that
103
     * in 500ms each constructor can finish, so 500ms after the registration
126
     * in 500ms each constructor can finish, so 500ms after the registration
104
     * of object in a toNotify map, it should be ready and initialized.
127
     * of object in a toNotify map, it should be ready and initialized.
105
     */
128
     */
106
    private static final int SAFE_NOTIFY_DELAY = 500;
129
    private static final int SAFE_NOTIFY_DELAY = 0;
107
    
130
    
108
    private static final Integer ONE = new Integer(1);
131
    private static final Integer ONE = new Integer(1);
109
    
132
    
110
    /** A task to check toNotify content and notify that objects were created.
111
     */
112
    private RequestProcessor.Task task;
113
    
114
    /** Constructor.
133
    /** Constructor.
115
     */
134
     */
116
    private DataObjectPool () {
135
    private DataObjectPool () {
117
        task = RequestProcessor.createRequest (this);
118
        task.setPriority (Thread.MIN_PRIORITY);
119
    }
136
    }
120
137
121
138
Lines 230-240 Link Here
230
                return;
247
                return;
231
            }
248
            }
232
            
249
            
233
            if (toNotify.isEmpty ()) {
234
                // ok, we do not need the task
235
                task.cancel ();
236
            }
237
            
238
            // if somebody is caught in waitNotified then wake him up
250
            // if somebody is caught in waitNotified then wake him up
239
            notifyAll ();
251
            notifyAll ();
240
        }
252
        }
Lines 272-320 Link Here
272
    }
284
    }
273
        
285
        
274
    
286
    
275
    /** Invoked to periodicaly check whether some data objects are not notified
276
     * to be created. In such case it notifies about their creation.
277
     */
278
    public void run () {
279
        Item arr []; 
280
281
        synchronized (this) {
282
            if (toNotify.isEmpty()) {
283
                return;
284
            }
285
            
286
            if (System.currentTimeMillis () < toNotifyModified + SAFE_NOTIFY_DELAY) {
287
                task.schedule (SAFE_NOTIFY_DELAY);
288
                return;
289
            }
290
            arr = (Item [])toNotify.toArray (new Item [toNotify.size ()]);
291
        }
292
293
        // notify each created object
294
        for (int i = 0; i < arr.length; i++) {
295
            DataObject obj = arr[i].getDataObjectOrNull ();
296
            
297
            // notifyCreation removes object from toNotify queue,
298
            // if object was already invalidated then remove it as well
299
            if (obj != null) {
300
                notifyCreation (obj);
301
            } else {
302
                synchronized (this) {
303
                    toNotify.remove (arr[i]);
304
                }
305
            }
306
        }
307
    }
308
309
    /** Add to list of created objects.
287
    /** Add to list of created objects.
310
     */
288
     */
311
    private void notifyAdd (Item item) {
289
    private void notifyAdd (Item item) {
312
        if (toNotify.isEmpty()) {
313
            task.schedule (SAFE_NOTIFY_DELAY);
314
        }
315
        toNotify.add (item);
290
        toNotify.add (item);
316
        last.set (item);
291
        last.set (item);
317
        toNotifyModified = System.currentTimeMillis ();
318
    }
292
    }
319
293
320
    
294
    
Lines 398-403 Link Here
398
    * @exception DataObjectExistsException if the file object is already registered
372
    * @exception DataObjectExistsException if the file object is already registered
399
    */
373
    */
400
    public Item register (FileObject fo, DataLoader loader) throws DataObjectExistsException {
374
    public Item register (FileObject fo, DataLoader loader) throws DataObjectExistsException {
375
        if (FIND.get () == null) throw new IllegalStateException ("DataObject constructor can be called only thru DataObject.find - use that method"); // NOI18N
376
        
401
        // here we're registering a listener on fo's FileSystem so we can deliver
377
        // here we're registering a listener on fo's FileSystem so we can deliver
402
        // fo changes to DO without lots of tiny listeners on folders
378
        // fo changes to DO without lots of tiny listeners on folders
403
        // The new DS bound to a repository can simply place a single listener
379
        // The new DS bound to a repository can simply place a single listener
Lines 490-498 Link Here
490
            // (e.g. BB/AAA/A1) is left in the toNotify pool forever. This
466
            // (e.g. BB/AAA/A1) is left in the toNotify pool forever. This
491
            // point is reached; remove it now. -jglick
467
            // point is reached; remove it now. -jglick
492
            if (toNotify.remove(item)) {
468
            if (toNotify.remove(item)) {
493
                if (toNotify.isEmpty()) {
494
                    task.cancel();
495
                }
496
                notifyAll();
469
                notifyAll();
497
            }
470
            }
498
            return;
471
            return;
(-)loaders/src/org/openide/loaders/MultiDataObject.java (-5 / +1 lines)
Lines 801-812 Link Here
801
        if (loader != null) {
801
        if (loader != null) {
802
            obj = loader.createMultiObject (fo);
802
            obj = loader.createMultiObject (fo);
803
        } else {
803
        } else {
804
            obj = (MultiDataObject)getLoader ().findDataObject (fo, RECOGNIZER);
804
            obj = (MultiDataObject)DataObjectPool.findDataObject (getLoader (), fo, RECOGNIZER);
805
        }
805
        }
806
807
        // notifies that the object has been created
808
        DataObjectPool.getPOOL ().notifyCreation (obj);
809
        
810
        return obj;
806
        return obj;
811
    }
807
    }
812
808
(-)test/unit/src/org/openide/loaders/DataObjectInvalidationTest.java (-4 / +84 lines)
Lines 83-88 Link Here
83
        TestUtilHid.destroyLocalFileSystem(name());
83
        TestUtilHid.destroyLocalFileSystem(name());
84
    }
84
    }
85
    */
85
    */
86
87
    public void testNobodyCanAccessDataObjectWithUnfinishedConstructor () throws Throwable {
88
        FileSystem lfs = TestUtilHid.createLocalFileSystem(getName(), new String[] {
89
            "folder/file.slow",
90
        });
91
        final FileObject file = lfs.findResource("folder/file.slow");
92
        assertNotNull(file);
93
        
94
        final DataLoader l = DataLoader.getLoader(SlowDataLoader.class);
95
        AddLoaderManuallyHid.addRemoveLoader(l, true);
96
        try {
97
            class DoTheTest extends Object implements Runnable {
98
                private DataObject first;
99
                /** any eception from run method */
100
                private Throwable ex;
101
                
102
                public synchronized void runInMainThread () throws Throwable {
103
                    first = DataObject.find (file);
104
                    
105
                    
106
                    // waiting for results
107
                    wait ();
108
                    if (ex != null) {
109
                        throw ex;
110
                    }
111
                }
112
                
113
                public void run () {
114
                    try {
115
                        synchronized (l) {
116
                            // this wait is notified from the midle of SlowDataObject
117
                            // constructor
118
                            l.wait (700);
119
120
                            // that means the thread in runInMainThread() have not finished
121
                            // the assignment to first variable yet
122
                            assertNull (first);
123
                        }
124
                    
125
                        // now try to get the DataObject while its constructor
126
                        // is blocked in the case
127
                        DataObject obj = DataObject.find (file);
128
                        assertEquals ("It is the slow obj", SlowDataObject.class, obj.getClass());
129
                        SlowDataObject slow = (SlowDataObject)obj;
130
131
                        assertNull ("The second thread still has not finished the constructor", first);
132
                        assertTrue ("Constructor has to finish completely", slow.ok);
133
134
                    } catch (Throwable ex) {
135
                        this.ex = ex;
136
                    } finally {
137
                        synchronized (this) {
138
                            notify ();
139
                        }
140
                    }
141
                }
142
            }
143
            
144
            DoTheTest dtt = new DoTheTest ();
145
            new Thread (dtt, "Slow").start ();
146
            dtt.runInMainThread ();
147
            
148
            
149
        } finally {
150
            AddLoaderManuallyHid.addRemoveLoader(l, false);
151
        }
152
        TestUtilHid.destroyLocalFileSystem(getName());
153
    }
86
    
154
    
87
    public void testNodeDelegateNotRequestedTillObjReady() throws Exception {
155
    public void testNodeDelegateNotRequestedTillObjReady() throws Exception {
88
        FileSystem lfs = TestUtilHid.createLocalFileSystem(getName(), new String[] {
156
        FileSystem lfs = TestUtilHid.createLocalFileSystem(getName(), new String[] {
Lines 226-236 Link Here
226
        public static int createCount = 0;
294
        public static int createCount = 0;
227
        public SlowDataObject(FileObject pf, MultiFileLoader loader) throws IOException {
295
        public SlowDataObject(FileObject pf, MultiFileLoader loader) throws IOException {
228
            super(pf, loader);
296
            super(pf, loader);
229
            try {
297
            synchronized (loader) {
230
                Thread.sleep(2000);
298
                // in case somebody is listening on the loader for our creation
231
            } catch (InterruptedException ie) {
299
                // let him wake up
232
                throw new IOException(ie.toString());
300
                loader.notifyAll ();
301
            }
302
            
303
            int cnt = 1;
304
            
305
            while (cnt-- > 0) {
306
                try {
307
                    Thread.sleep(2000);
308
                } catch (InterruptedException ie) {
309
                    throw new IOException(ie.toString());
310
                }
233
            }
311
            }
312
            
313
            
234
            ok = true;
314
            ok = true;
235
            createCount++;
315
            createCount++;
236
        }
316
        }

Return to bug 20022