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 20190
Collapse All | Expand All

(-)core/src/org/netbeans/core/LookupCache.java (+118 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.core;
15
16
import java.io.*;
17
18
import org.openide.ErrorManager;
19
import org.openide.filesystems.FileObject;
20
import org.openide.filesystems.Repository;
21
import org.openide.loaders.DataFolder;
22
import org.openide.loaders.FolderLookup;
23
import org.openide.util.Lookup;
24
import org.openide.util.io.NbObjectInputStream;
25
import org.openide.util.io.NbObjectOutputStream;
26
27
import org.netbeans.core.perftool.StartLog;
28
29
/**
30
 * Responsible for persisting the structure of folder lookup.
31
 * A cache is kept in serialized form in $userdir/cache/folder-lookup.ser.
32
 * Unless the cache is invalidated due to changes in module JARs or
33
 * files in $userdir/system/**, it is restored after a regular startup.
34
 * The actual objects in lookup are not serialized - only their classes,
35
 * instanceof information, position in the Services folder, and so on. This
36
 * permits us to avoid calling the XML parser for every .settings object etc.
37
 * Other forms of lookup like META-INF/services/* are not persisted.
38
 * @author Jesse Glick, Jaroslav Tulach
39
 * @see "#20190"
40
 */
41
class LookupCache {
42
    
43
    private static final boolean ENABLED = Boolean.valueOf(System.getProperty("netbeans.cache.lookup", "true")).booleanValue(); // NOI18N
44
    
45
    public static Lookup load() {
46
        if (ENABLED && cacheHit()) {
47
            try {
48
                return loadCache();
49
            } catch (Exception e) {
50
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
51
            }
52
        }
53
        return loadDirect();
54
    }
55
    
56
    private static Lookup loadDirect() {
57
        FileObject services = Repository.getDefault().getDefaultFileSystem().findResource("Services"); // NOI18N
58
        if (services != null) {
59
            StartLog.logProgress("Got Services folder"); // NOI18N
60
            FolderLookup f = new FolderLookup(DataFolder.findFolder(services), "SL["); // NOI18N
61
            StartLog.logProgress("created FolderLookup"); // NOI18N
62
            return f.getLookup();
63
        } else {
64
            return Lookup.EMPTY;
65
        }
66
    }
67
    
68
    private static boolean cacheHit() {
69
        // XXX timestamp check not yet implemented
70
        File f = cacheFile();
71
        return f != null && f.exists();
72
    }
73
    
74
    private static File cacheFile() {
75
        String ud = System.getProperty("netbeans.user");
76
        if (ud != null) {
77
            File cachedir = new File(ud, "cache"); // NOI18N
78
            cachedir.mkdirs();
79
            return new File(cachedir, "folder-lookup.ser"); // NOI18N
80
        } else {
81
            return null;
82
        }
83
    }
84
    
85
    private static Lookup loadCache() throws Exception {
86
        InputStream is = new FileInputStream(cacheFile());
87
        try {
88
            ObjectInputStream ois = new NbObjectInputStream(new BufferedInputStream(is));
89
            return (Lookup)ois.readObject();
90
        } finally {
91
            is.close();
92
        }
93
    }
94
    
95
    public static void store(Lookup l) throws IOException {
96
        if (!ENABLED) {
97
            return;
98
        }
99
        File f = cacheFile();
100
        OutputStream os = new FileOutputStream(f);
101
        try {
102
            try {
103
                ObjectOutputStream oos = new NbObjectOutputStream(new BufferedOutputStream(os));
104
                oos.writeObject(l);
105
                oos.flush();
106
            } finally {
107
                os.close();
108
            }
109
        } catch (IOException ioe) {
110
            // Delete corrupted cache.
111
            if (f.exists()) {
112
                f.delete();
113
            }
114
            throw ioe;
115
        }
116
    }
117
    
118
}
(-)core/src/org/netbeans/core/NbTopManager.java (-12 / +14 lines)
Lines 538-543 Link Here
538
                            }
538
                            }
539
                        }
539
                        }
540
                        org.netbeans.core.projects.XMLSettingsHandler.saveOptions();
540
                        org.netbeans.core.projects.XMLSettingsHandler.saveOptions();
541
                        try {
542
                            ((Lkp)Lookup.getDefault()).storeCache();
543
                        } catch (IOException ioe) {
544
                            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
545
                        }
541
                        org.netbeans.core.projects.SessionManager.getDefault().close();
546
                        org.netbeans.core.projects.SessionManager.getDefault().close();
542
                    } catch (ThreadDeath td) {
547
                    } catch (ThreadDeath td) {
543
                        throw td;
548
                        throw td;
Lines 804-820 Link Here
804
        
809
        
805
        private final void doInitializeLookup () {
810
        private final void doInitializeLookup () {
806
            //System.err.println("doInitializeLookup");
811
            //System.err.println("doInitializeLookup");
807
            FileObject services = Repository.getDefault().getDefaultFileSystem()
808
                    .findResource("Services");
809
            Lookup nue;
810
            if (services != null) {
811
                StartLog.logProgress("Got Services folder"); // NOI18N
812
                FolderLookup f = new FolderLookup(DataFolder.findFolder(services), "SL["); // NOI18N
813
                StartLog.logProgress("created FolderLookup"); // NOI18N
814
                nue = f.getLookup();
815
            } else {
816
                nue = Lookup.EMPTY;
817
            }
818
812
819
            // extend the lookup
813
            // extend the lookup
820
            Lookup[] arr = new Lookup[] {
814
            Lookup[] arr = new Lookup[] {
Lines 823-829 Link Here
823
                getLookups()[2], // ModuleInfo lookup
817
                getLookups()[2], // ModuleInfo lookup
824
                // XXX figure out how to put this ahead of MetaInfServicesLookup (for NonGuiMain):
818
                // XXX figure out how to put this ahead of MetaInfServicesLookup (for NonGuiMain):
825
                NbTopManager.get ().getInstanceLookup (),
819
                NbTopManager.get ().getInstanceLookup (),
826
                nue,
820
                LookupCache.load(),
827
            };
821
            };
828
            StartLog.logProgress ("prepared other Lookups"); // NOI18N
822
            StartLog.logProgress ("prepared other Lookups"); // NOI18N
829
823
Lines 831-836 Link Here
831
            StartLog.logProgress ("Lookups set"); // NOI18N
825
            StartLog.logProgress ("Lookups set"); // NOI18N
832
826
833
	    //StartLog.logEnd ("NbTopManager$Lkp: initialization of FolderLookup"); // NOI18N
827
	    //StartLog.logEnd ("NbTopManager$Lkp: initialization of FolderLookup"); // NOI18N
828
        }
829
        
830
        public void storeCache() throws IOException {
831
            Lookup[] ls = getLookups();
832
            if (ls.length == 5) {
833
                // modulesClassPathInitialized has been called, so store folder lookup
834
                LookupCache.store(ls[4]);
835
            }
834
        }
836
        }
835
        
837
        
836
        protected void beforeLookup(Lookup.Template templ) {
838
        protected void beforeLookup(Lookup.Template templ) {
(-)openide/src/org/openide/loaders/FolderLookup.java (-7 / +92 lines)
Lines 16-21 Link Here
16
16
17
17
18
import java.io.IOException;
18
import java.io.IOException;
19
import java.io.ObjectInputStream;
20
import java.io.ObjectOutputStream;
21
import java.io.Serializable;
19
import java.lang.ref.WeakReference;
22
import java.lang.ref.WeakReference;
20
import java.util.ArrayList;
23
import java.util.ArrayList;
21
import java.util.Collection;
24
import java.util.Collection;
Lines 23-28 Link Here
23
26
24
import org.openide.cookies.InstanceCookie;
27
import org.openide.cookies.InstanceCookie;
25
import org.openide.ErrorManager;
28
import org.openide.ErrorManager;
29
import org.openide.filesystems.FileObject;
26
import org.openide.loaders.DataObject;
30
import org.openide.loaders.DataObject;
27
import org.openide.util.Lookup;
31
import org.openide.util.Lookup;
28
import org.openide.util.lookup.AbstractLookup;
32
import org.openide.util.lookup.AbstractLookup;
Lines 247-260 Link Here
247
251
248
    
252
    
249
    /** <code>ProxyLookup</code> delegate so we can change the lookups on fly. */
253
    /** <code>ProxyLookup</code> delegate so we can change the lookups on fly. */
250
    private static final class ProxyLkp extends ProxyLookup {
254
    private static final class ProxyLkp extends ProxyLookup implements Serializable {
255
        
256
        private static final long serialVersionUID = 1L;
251
257
252
        /** <code>FolderLookup</code> we are associated with. */
258
        /** <code>FolderLookup</code> we are associated with. */
253
        private FolderLookup fl;
259
        private transient FolderLookup fl;
254
        
260
        
255
        /** Content to control the abstract lookup. */
261
        /** Content to control the abstract lookup. */
256
        private AbstractLookup.Content content;
262
        private transient AbstractLookup.Content content;
257
        
263
        
264
        private transient boolean readFromStream;
258
265
259
        /** Constructs lookup which holds all items+lookups from underlying world.
266
        /** Constructs lookup which holds all items+lookups from underlying world.
260
         * @param folder <code>FolderLookup</code> to associate to */
267
         * @param folder <code>FolderLookup</code> to associate to */
Lines 270-281 Link Here
270
            this.content = content;
277
            this.content = content;
271
        }
278
        }
272
        
279
        
280
        private void writeObject (ObjectOutputStream oos) throws IOException {
281
            Lookup[] ls = getLookups();
282
            for (int i = 0; i < ls.length; i++) {
283
                oos.writeObject(ls[i]);
284
            }
285
            oos.writeObject(null);
286
            oos.writeObject (fl.folder);
287
            oos.writeObject (fl.rootName);
288
            oos.writeObject (content);
289
        }
290
        
291
        private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException {
292
            List ls = new ArrayList(); // List<Lookup>
293
            Lookup l;
294
            while ((l = (Lookup)ois.readObject()) != null) {
295
                ls.add(l);
296
            }
297
            Lookup[] arr = (Lookup[])ls.toArray(new Lookup[ls.size()]);
298
            DataFolder df = (DataFolder)ois.readObject ();
299
            String root = (String)ois.readObject ();
300
            
301
            fl = new FolderLookup (df, root, true);
302
            fl.lookup = this;
303
            
304
            content = (AbstractLookup.Content)ois.readObject ();
305
            
306
            setLookups (arr);
307
            
308
            readFromStream = true;
309
        }
310
        
273
        
311
        
274
        /** Updates internal data. 
312
        /** Updates internal data. 
275
         * @param items Items to assign to all pairs
313
         * @param items Items to assign to all pairs
276
         * @param lookups delegates to delegate to (first item is null)
314
         * @param lookups delegates to delegate to (first item is null)
277
         */
315
         */
278
        public void update(Collection items, List lookups) {
316
        public void update(Collection items, List lookups) {
317
            readFromStream = false;
318
            
279
            // remember the instance lookup 
319
            // remember the instance lookup 
280
            Lookup pairs = getLookups ()[0];
320
            Lookup pairs = getLookups ()[0];
281
321
Lines 292-297 Link Here
292
        
332
        
293
        /** Waits before the processing of changes is finished. */
333
        /** Waits before the processing of changes is finished. */
294
        protected void beforeLookup (Template template) {
334
        protected void beforeLookup (Template template) {
335
            if (readFromStream) {
336
                // ok
337
                return;
338
            }
339
            
295
            // do not wait in folder recognizer, but in all other cases
340
            // do not wait in folder recognizer, but in all other cases
296
            if (!FolderList.isFolderRecognizerThread ()) {
341
            if (!FolderList.isFolderRecognizerThread ()) {
297
                fl.instanceFinished ();
342
                fl.instanceFinished ();
Lines 303-314 Link Here
303
    
348
    
304
    /** Item that delegates to <code>InstanceCookie</code>. Item which 
349
    /** Item that delegates to <code>InstanceCookie</code>. Item which 
305
     * the internal lookup data structure is made from. */
350
     * the internal lookup data structure is made from. */
306
    private static final class ICItem extends AbstractLookup.Pair {
351
    private static final class ICItem extends AbstractLookup.Pair implements Serializable {
307
        private InstanceCookie ic;
352
        static final long serialVersionUID = 10L;
353
354
        /** when deserialized only primary file is stored */
355
        private FileObject fo;
356
        
357
        private transient InstanceCookie ic;
308
        /** source data object */
358
        /** source data object */
309
        private DataObject obj;
359
        private transient DataObject obj;
310
        /** reference to created object */
360
        /** reference to created object */
311
        private WeakReference ref;
361
        private transient WeakReference ref;
312
        /** root folder */
362
        /** root folder */
313
        private String rootName;
363
        private String rootName;
314
364
Lines 317-322 Link Here
317
            this.ic = ic;
367
            this.ic = ic;
318
            this.obj = obj;
368
            this.obj = obj;
319
            this.rootName = rootName;
369
            this.rootName = rootName;
370
            this.fo = obj.getPrimaryFile();
371
        }
372
        
373
        /** Initializes the item
374
         */
375
        public void init () {
376
            if (ic != null) return;
377
            
378
            ic = (InstanceCookie)obj.getCookie (InstanceCookie.class);
379
            if (ic == null) {
380
                // XXX handle more gracefully
381
                throw new IllegalStateException ("No cookie: " + obj);
382
            }
383
        }
384
            
385
        
386
        /** Initializes the cookie from data object.
387
         */
388
        private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException {
389
            ois.defaultReadObject();
390
            obj = DataObject.find (fo);
320
        }
391
        }
321
392
322
393
Lines 324-329 Link Here
324
         * @return the class of the item
395
         * @return the class of the item
325
         */
396
         */
326
        protected boolean instanceOf (Class clazz) {
397
        protected boolean instanceOf (Class clazz) {
398
            init ();
399
            
327
            if (ic instanceof InstanceCookie.Of) {
400
            if (ic instanceof InstanceCookie.Of) {
328
                // special handling for special cookies
401
                // special handling for special cookies
329
                InstanceCookie.Of of = (InstanceCookie.Of)ic;
402
                InstanceCookie.Of of = (InstanceCookie.Of)ic;
Lines 345-350 Link Here
345
         * @return the instance of the object or null if it cannot be created
418
         * @return the instance of the object or null if it cannot be created
346
         */
419
         */
347
        public Object getInstance() {
420
        public Object getInstance() {
421
            init ();
422
            
348
            try {
423
            try {
349
                Object obj = ic.instanceCreate();
424
                Object obj = ic.instanceCreate();
350
                ref = new WeakReference (obj);
425
                ref = new WeakReference (obj);
Lines 359-364 Link Here
359
434
360
        /** Hash code is the <code>InstanceCookie</code>'s code. */
435
        /** Hash code is the <code>InstanceCookie</code>'s code. */
361
        public int hashCode () {
436
        public int hashCode () {
437
            init ();
438
            
362
            return System.identityHashCode (ic);
439
            return System.identityHashCode (ic);
363
        }
440
        }
364
441
Lines 366-371 Link Here
366
        public boolean equals (Object obj) {
443
        public boolean equals (Object obj) {
367
            if (obj instanceof ICItem) {
444
            if (obj instanceof ICItem) {
368
                ICItem i = (ICItem)obj;
445
                ICItem i = (ICItem)obj;
446
                i.init ();
447
                init ();
369
                return ic == i.ic;
448
                return ic == i.ic;
370
            }
449
            }
371
            return false;
450
            return false;
Lines 375-385 Link Here
375
         * @return string representing the item, that can be used for
454
         * @return string representing the item, that can be used for
376
         *   persistance purposes to locate the same item next time */
455
         *   persistance purposes to locate the same item next time */
377
        public String getId() {
456
        public String getId() {
457
            init ();
458
            
378
            return objectName(rootName, obj);
459
            return objectName(rootName, obj);
379
        }
460
        }
380
461
381
        /** Display name is extracted from name of the objects node. */
462
        /** Display name is extracted from name of the objects node. */
382
        public String getDisplayName () {
463
        public String getDisplayName () {
464
            init ();
465
            
383
            return obj.getNodeDelegate ().getDisplayName ();
466
            return obj.getNodeDelegate ().getDisplayName ();
384
        }
467
        }
385
468
Lines 399-404 Link Here
399
         * @return the correct class
482
         * @return the correct class
400
         */
483
         */
401
        public Class getType() {
484
        public Class getType() {
485
            init ();
486
            
402
            try {
487
            try {
403
                return ic.instanceClass ();
488
                return ic.instanceClass ();
404
            } catch (IOException ex) {
489
            } catch (IOException ex) {
(-)openide/src/org/openide/loaders/XMLDataObject.java (-10 / +35 lines)
Lines 1022-1027 Link Here
1022
        /** result used for this lookup */
1022
        /** result used for this lookup */
1023
        private Lookup.Result result;
1023
        private Lookup.Result result;
1024
        
1024
        
1025
        private ThreadLocal QUERY = new ThreadLocal ();
1026
        
1025
        //~~~~~~~~~~~~~~~~~~~~~ Task body and control of queue ~~~~~~~~~~~~~~~~~~~
1027
        //~~~~~~~~~~~~~~~~~~~~~ Task body and control of queue ~~~~~~~~~~~~~~~~~~~
1026
        
1028
        
1027
        /** Getter for public ID of the document.
1029
        /** Getter for public ID of the document.
Lines 1037-1054 Link Here
1037
         *
1039
         *
1038
         * @param class to look for
1040
         * @param class to look for
1039
         */
1041
         */
1040
        public Object lookupCookie (Class clazz) {
1042
        public Object lookupCookie (final Class clazz) {
1041
            waitFinished ();
1043
            if (QUERY.get () == clazz) {
1042
            
1044
                // somebody is querying for the same cookie in the same thread
1043
            Lookup l = lookup != null ? lookup : Lookup.EMPTY;
1045
                // probably neverending-loop - ignore
1046
                return new InstanceCookie () {
1047
                    public Class instanceClass () {
1048
                        return clazz;
1049
                    }
1050
                    
1051
                    public Object instanceCreate () throws IOException {
1052
                        throw new IOException ("Cyclic reference, sorry: " + clazz);
1053
                    }
1054
                    
1055
                    public String instanceName () {
1056
                        return clazz.getName ();
1057
                    }
1058
                };
1059
            }
1044
            
1060
            
1045
            Lookup.Result r = result;
1061
            Object previous = QUERY.get ();
1046
            if (r != null) {
1062
            try {
1047
                // just to initialize all listeners
1063
                QUERY.set (clazz);
1048
                r.allItems ();
1064
                waitFinished ();
1065
1066
                Lookup l = lookup != null ? lookup : Lookup.EMPTY;
1067
1068
                Lookup.Result r = result;
1069
                if (r != null) {
1070
                    // just to initialize all listeners
1071
                    r.allItems ();
1072
                }
1073
                return l.lookup (clazz);
1074
            } finally {
1075
                QUERY.set (previous);
1049
            }
1076
            }
1050
         
1051
            return l.lookup (clazz);
1052
        }
1077
        }
1053
           
1078
           
1054
        /*
1079
        /*
(-)openide/src/org/openide/util/lookup/AbstractLookup.java (-6 / +12 lines)
Lines 13-19 Link Here
13
13
14
package org.openide.util.lookup;
14
package org.openide.util.lookup;
15
15
16
16
import java.io.Serializable;
17
import java.lang.ref.*;
17
import java.lang.ref.*;
18
import java.util.*;
18
import java.util.*;
19
19
Lines 29-35 Link Here
29
 * @author  Jaroslav Tulach
29
 * @author  Jaroslav Tulach
30
 * @since 1.9
30
 * @since 1.9
31
 */
31
 */
32
public class AbstractLookup extends Lookup {
32
public class AbstractLookup extends Lookup implements Serializable {
33
    static final long serialVersionUID = 5L;
34
    
33
    /** lock for initialization of the map */
35
    /** lock for initialization of the map */
34
    private Content treeLock;
36
    private Content treeLock;
35
    /** the tree that registers all items */
37
    /** the tree that registers all items */
Lines 40-46 Link Here
40
    /** set (Class, List (Reference (Result)) of all listeners that are waiting in 
42
    /** set (Class, List (Reference (Result)) of all listeners that are waiting in 
41
     * changes in class Class
43
     * changes in class Class
42
     */
44
     */
43
    private Map reg;
45
    private transient Map reg;
44
    /** count of items in to lookup */
46
    /** count of items in to lookup */
45
    private int count;
47
    private int count;
46
    
48
    
Lines 447-453 Link Here
447
    /** Extension to the default lookup item that offers additional information
449
    /** Extension to the default lookup item that offers additional information
448
     * for the data structures use in AbstractLookup
450
     * for the data structures use in AbstractLookup
449
     */
451
     */
450
    public static abstract class Pair extends Lookup.Item {
452
    public static abstract class Pair extends Lookup.Item implements Serializable {
453
        private static final long serialVersionUID = 1L;
454
        
451
        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
455
        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
452
        int index = -1;
456
        int index = -1;
453
457
Lines 641-652 Link Here
641
     *
645
     *
642
     * @since 1.25
646
     * @since 1.25
643
     */
647
     */
644
    public static class Content extends Object {
648
    public static class Content extends Object implements Serializable {
649
        
650
        private static final long serialVersionUID = 1L;
645
        
651
        
646
        // one of them is always null (except attach stage)
652
        // one of them is always null (except attach stage)
647
        /** abstract lookup we are connected to */
653
        /** abstract lookup we are connected to */
648
        private AbstractLookup al = null;
654
        private AbstractLookup al = null;
649
        private ArrayList earlyPairs = new ArrayList(3);
655
        private transient ArrayList earlyPairs = new ArrayList(3);
650
        
656
        
651
        /** A lookup attaches to this object.
657
        /** A lookup attaches to this object.
652
         */
658
         */
(-)openide/src/org/openide/util/lookup/InheritanceTree.java (-22 / +83 lines)
Lines 14-35 Link Here
14
14
15
package org.openide.util.lookup;
15
package org.openide.util.lookup;
16
16
17
17
import java.io.*;
18
import java.lang.ref.WeakReference;
18
import java.lang.ref.WeakReference;
19
import java.util.ArrayList;
19
import java.util.*;
20
import java.util.Collection;
20
21
import java.util.Collections;
21
import org.openide.util.Lookup;
22
import java.util.Enumeration;
22
import org.openide.util.enum.*;
23
import java.util.Iterator;
24
import java.util.Map;
25
import java.util.WeakHashMap;
26
import java.util.List;
27
28
import org.openide.util.enum.AlterEnumeration;
29
import org.openide.util.enum.EmptyEnumeration;
30
import org.openide.util.enum.QueueEnumeration;
31
import org.openide.util.enum.SequenceEnumeration;
32
import org.openide.util.enum.SingletonEnumeration;
33
23
34
24
35
/** A tree to represent classes with inheritance. Description of the
25
/** A tree to represent classes with inheritance. Description of the
Lines 96-106 Link Here
96
 *
86
 *
97
 * @author  Jaroslav Tulach
87
 * @author  Jaroslav Tulach
98
 */
88
 */
99
final class InheritanceTree extends Object implements java.util.Comparator {
89
final class InheritanceTree extends Object implements Comparator, Serializable {
90
    private static final long serialVersionUID = 1L;
91
100
    /** the root item (represents Object) */
92
    /** the root item (represents Object) */
101
    private Node object;
93
    private transient Node object;
102
    /** map of queried interfaces (Class, Set) */
94
    /** Map of queried interfaces.
103
    private Map interfaces;
95
     * <p>Type: <code>Map&lt;Class, (Collection&lt;AbstractLookup.Pair&gt; | AbstractLookup.Pair)&gt;</code>
96
     */
97
    private transient Map interfaces;
104
98
105
    /** Constructor
99
    /** Constructor
106
     */
100
     */
Lines 108-113 Link Here
108
        object = new Node (java.lang.Object.class);
102
        object = new Node (java.lang.Object.class);
109
    }
103
    }
110
104
105
    private void writeObject (ObjectOutputStream oos) throws IOException {
106
        oos.writeObject(object);
107
        Iterator it = interfaces.entrySet().iterator();
108
        while (it.hasNext()) {
109
            Map.Entry e = (Map.Entry)it.next();
110
            Class c = (Class)e.getKey();
111
            oos.writeObject(c.getName());
112
            Object o = e.getValue();
113
            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) throw new ClassCastException(String.valueOf(o));
114
            oos.writeObject(o);
115
        }
116
        oos.writeObject(null);
117
    }
118
119
    private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException {
120
        object = (Node)ois.readObject();
121
        interfaces = new WeakHashMap();
122
        String clazz;
123
        ClassLoader l = (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class);
124
        while ((clazz = (String)ois.readObject()) != null) {
125
            Object o = ois.readObject();
126
            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) throw new ClassCastException(String.valueOf(o));
127
            Class c = Class.forName(clazz, false, l);
128
            interfaces.put(c, o);
129
        }
130
    }
131
        
111
132
112
    /** Adds an item into the tree.
133
    /** Adds an item into the tree.
113
    * @param item to add
134
    * @param item to add
Lines 745-756 Link Here
745
766
746
    /** Node in the tree.
767
    /** Node in the tree.
747
    */
768
    */
748
    static final class Node extends WeakReference {
769
    static final class Node extends WeakReference implements Serializable {
770
        static final long serialVersionUID = 3L;
749
        /** children nodes */
771
        /** children nodes */
750
        public ArrayList children;
772
        public ArrayList children; // List<Node>
751
773
752
        /** list of items assigned to this node (suspect to be subclasses) */
774
        /** list of items assigned to this node (suspect to be subclasses) */
753
        public ArrayList items;
775
        public ArrayList items; // List<AbstractLookup.Pair>
754
776
755
        /** Constructor.
777
        /** Constructor.
756
        */
778
        */
Lines 807-811 Link Here
807
            items.add (item);
829
            items.add (item);
808
            return true;
830
            return true;
809
        }
831
        }
832
        
833
        private Object writeReplace () {
834
            return new R (this);
835
        }
836
        
810
    } // End of class Node.
837
    } // End of class Node.
838
    
839
    private static final class R implements Serializable {
840
        static final long serialVersionUID = 1L;
841
        
842
        private static ClassLoader l;
843
        
844
        private String clazzName;
845
        private transient Class clazz;
846
        private ArrayList children;
847
        private ArrayList items;
848
        
849
        public R (Node n) {
850
            this.clazzName = n.getType ().getName();
851
            this.children = n.children;
852
            this.items = n.items;
853
        }
854
        
855
        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
856
            ois.defaultReadObject();
857
            if (l == null) {
858
                l = (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class);
859
            }
860
            clazz = Class.forName(clazzName, false, l);
861
        }
862
        
863
        private Object readResolve () throws ObjectStreamException {
864
            Node n = new Node (clazz);
865
            n.children = children;
866
            n.items = items;
867
            
868
            return n;
869
        }
870
            
871
    } // end of R
811
}
872
}
(-)openide/src/org/openide/util/lookup/ProxyLookup.java (+9 lines)
Lines 40-45 Link Here
40
        this.lookups = lookups;
40
        this.lookups = lookups;
41
    }
41
    }
42
    
42
    
43
    /**
44
     * Create a lookup initially proxying to no others.
45
     * Permits serializable subclasses.
46
     * @since XXX
47
     */
48
    protected ProxyLookup() {
49
        this(new Lookup[0]);
50
    }
51
    
43
    public String toString() {
52
    public String toString() {
44
        return "ProxyLookup" + Arrays.asList(lookups); // NOI18N
53
        return "ProxyLookup" + Arrays.asList(lookups); // NOI18N
45
    }
54
    }

Return to bug 20190