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

(-)core/settings/nbproject/project.xml (-40 / +45 lines)
Lines 75-81 Link Here
75
                    <build-prerequisite/>
75
                    <build-prerequisite/>
76
                    <compile-dependency/>
76
                    <compile-dependency/>
77
                    <run-dependency>
77
                    <run-dependency>
78
                        <specification-version>7.3</specification-version>
78
                        <implementation-version/>
79
                    </run-dependency>
79
                    </run-dependency>
80
                </dependency>
80
                </dependency>
81
                <dependency>
81
                <dependency>
Lines 87-131 Link Here
87
                    </run-dependency>
87
                    </run-dependency>
88
                </dependency>
88
                </dependency>
89
            </module-dependencies>
89
            </module-dependencies>
90
          <test-dependencies>
90
            <test-dependencies>
91
              <test-type>
91
                <test-type>
92
                  <name>unit</name>
92
                    <name>unit</name>
93
                  <test-dependency>
93
                    <test-dependency>
94
                      <code-name-base>org.netbeans.modules.settings</code-name-base>
94
                        <code-name-base>org.netbeans.core.startup</code-name-base>
95
                      <recursive/>
95
                        <compile-dependency/>
96
                      <compile-dependency/>
96
                        <test/>
97
                  </test-dependency>
97
                    </test-dependency>
98
                  <test-dependency>
98
                    <test-dependency>
99
                      <code-name-base>org.openide.actions</code-name-base>
99
                        <code-name-base>org.netbeans.core.ui</code-name-base>
100
                      <recursive/>
100
                        <recursive/>
101
                  </test-dependency>
101
                        <compile-dependency/>
102
                  <test-dependency>
102
                    </test-dependency>
103
                      <code-name-base>org.netbeans.core.startup</code-name-base>
103
                    <test-dependency>
104
                      <recursive/>
104
                        <code-name-base>org.netbeans.modules.editor.mimelookup.impl</code-name-base>
105
                      <compile-dependency/>
105
                        <recursive/>
106
                  </test-dependency>
106
                        <compile-dependency/>
107
                  <test-dependency>
107
                    </test-dependency>
108
                      <code-name-base>org.netbeans.core.ui</code-name-base>
108
                    <test-dependency>
109
                      <recursive/>
109
                        <code-name-base>org.netbeans.modules.progress.ui</code-name-base>
110
                      <compile-dependency/>
110
                        <compile-dependency/>
111
                  </test-dependency>
111
                    </test-dependency>
112
                  <test-dependency>
112
                    <test-dependency>
113
                      <code-name-base>org.openide.text</code-name-base>
113
                        <code-name-base>org.netbeans.modules.settings</code-name-base>
114
                      <compile-dependency/>
114
                        <recursive/>
115
                  </test-dependency>
115
                        <compile-dependency/>
116
                  <test-dependency>
116
                    </test-dependency>
117
                      <code-name-base>org.netbeans.modules.progress.ui</code-name-base>
117
                    <test-dependency>
118
                      <compile-dependency/>
118
                        <code-name-base>org.openide.actions</code-name-base>
119
                  </test-dependency>
119
                        <recursive/>
120
                  <test-dependency>
120
                    </test-dependency>
121
                      <code-name-base>org.netbeans.modules.editor.mimelookup.impl</code-name-base>
121
                    <test-dependency>
122
                      <recursive/>
122
                        <code-name-base>org.openide.text</code-name-base>
123
                      <compile-dependency/>
123
                        <compile-dependency/>
124
                  </test-dependency>
124
                    </test-dependency>
125
              </test-type>
125
                    <test-dependency>
126
              <test-type>
126
                        <code-name-base>org.openide.util</code-name-base>
127
                  <name>qa-functional</name>
127
                        <compile-dependency/>
128
              </test-type>
128
                        <test/>
129
                    </test-dependency>
130
                </test-type>
131
                <test-type>
132
                    <name>qa-functional</name>
133
                </test-type>
129
            </test-dependencies>
134
            </test-dependencies>
130
            <public-packages>
135
            <public-packages>
131
                <package>org.netbeans.spi.settings</package>
136
                <package>org.netbeans.spi.settings</package>
(-)core/settings/src/META-INF/services/org.netbeans.modules.openide.util.NamedServicesProvider (+4 lines)
Added Link Here
1
org.netbeans.modules.settings.RecognizeInstanceObjects
2
#position=200
3
#-org.netbeans.modules.startup.layers.RecognizeInstanceFiles
4
(-)core/settings/src/org/netbeans/modules/settings/RecognizeInstanceObjects.java (+91 lines)
Added Link Here
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. 
17
 *
18
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
19
 */
20
21
package org.netbeans.modules.settings;
22
23
import java.io.IOException;
24
import java.util.Collection;
25
import java.util.Collections;
26
import java.util.logging.Logger;
27
import org.netbeans.modules.openide.util.NamedServicesProvider;
28
import org.openide.filesystems.FileObject;
29
import org.openide.filesystems.FileUtil;
30
import org.openide.filesystems.FileUtil;
31
import org.openide.filesystems.Repository;
32
import org.openide.loaders.DataFolder;
33
import org.openide.loaders.FolderLookup;
34
import org.openide.util.Lookup;
35
import org.openide.util.LookupEvent;
36
import org.openide.util.LookupListener;
37
import org.openide.util.WeakListeners;
38
import org.openide.util.lookup.Lookups;
39
import org.openide.util.lookup.ProxyLookup;
40
41
/** Use FolderLookup to find out intances of named services.
42
 *
43
 * @author Jaroslav Tulach
44
 */
45
public final class RecognizeInstanceObjects extends NamedServicesProvider {
46
    private static final Logger LOG = Logger.getLogger(RecognizeInstanceObjects.class.getName());
47
    
48
    
49
    public Lookup create(String path) {
50
        return new OverObjects(path);
51
    }        
52
    
53
    
54
    private static final class OverObjects extends ProxyLookup 
55
    implements LookupListener {
56
        private static Lookup.Result<ClassLoader> CL = Lookup.getDefault().lookupResult(ClassLoader.class);
57
        
58
        private final String path;
59
        
60
        public OverObjects(String path) {
61
            super(delegates(path));
62
            this.path = path;
63
            CL.addLookupListener(WeakListeners.create(LookupListener.class, this, CL));
64
        }
65
        
66
        @SuppressWarnings("deprecation")
67
        private static Lookup[] delegates(String path) {
68
            Collection<? extends ClassLoader> allCL = CL.allInstances();
69
            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
70
            if (ccl != null) {
71
                allCL = Collections.singleton(ccl);
72
            } else {
73
                if (allCL.isEmpty()) {
74
                    allCL = Collections.singleton(RecognizeInstanceObjects.class.getClassLoader());
75
                }
76
            }
77
            try {
78
                FileObject fo = FileUtil.createFolder(Repository.getDefault().getDefaultFileSystem().getRoot(), path);
79
                FolderLookup l = new FolderLookup(DataFolder.findFolder(fo));
80
                return new Lookup[] { l.getLookup(), Lookups.metaInfServices(allCL.iterator().next(), "META-INF/namedservices/" + path) }; // NOI18N
81
            } catch (IOException ex) {
82
                return new Lookup[] { Lookups.metaInfServices(allCL.iterator().next(), "META-INF/namedservices/" + path) }; // NOI18N
83
            }
84
            
85
        }
86
    
87
        public void resultChanged(LookupEvent ev) {
88
            setLookups(delegates(path));
89
        }
90
    } // end of OverObjects
91
}
(-)core/settings/test/unit/src/org/netbeans/modules/settings/RecognizeInstanceObjectsTest.java (+32 lines)
Added Link Here
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.netbeans.modules.settings;
21
22
import org.netbeans.core.startup.layers.NamedFSServicesLookupTest;
23
24
25
/** Test finding services from manifest and .instance files using FolderLookup.
26
 * @author Jaroslav Tulach
27
 */
28
public class RecognizeInstanceObjectsTest extends NamedFSServicesLookupTest{
29
    public RecognizeInstanceObjectsTest(String name) {
30
        super(name);
31
    }
32
}
(-)core/startup/nbproject/project.xml (+5 lines)
Lines 70-75 Link Here
70
                        <compile-dependency/>
70
                        <compile-dependency/>
71
                        <test/>
71
                        <test/>
72
                    </test-dependency>
72
                    </test-dependency>
73
                    <test-dependency>
74
                        <code-name-base>org.openide.util</code-name-base>
75
                        <compile-dependency/>
76
                        <test/>
77
                    </test-dependency>
73
                </test-type>
78
                </test-type>
74
                <test-type>
79
                <test-type>
75
                    <name>qa-functional</name>
80
                    <name>qa-functional</name>
(-)core/startup/src/META-INF/services/org.netbeans.modules.openide.util.NamedServicesProvider (+2 lines)
Added Link Here
1
org.netbeans.core.startup.layers.RecognizeInstanceFiles
2
#position=500
(-)core/startup/src/org/netbeans/core/startup/layers/RecognizeInstanceFiles.java (+265 lines)
Added Link Here
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. 
17
 *
18
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
19
 */
20
21
package org.netbeans.core.startup.layers;
22
23
import java.lang.ref.Reference;
24
import java.lang.ref.WeakReference;
25
import java.util.ArrayList;
26
import java.util.Collections;
27
import java.util.LinkedList;
28
import java.util.List;
29
import java.util.logging.Level;
30
import java.util.logging.Logger;
31
import org.netbeans.modules.openide.util.NamedServicesProvider;
32
import org.openide.filesystems.FileAttributeEvent;
33
import org.openide.filesystems.FileChangeListener;
34
import org.openide.filesystems.FileEvent;
35
import org.openide.filesystems.FileObject;
36
import org.openide.filesystems.FileRenameEvent;
37
import org.openide.filesystems.FileStateInvalidException;
38
import org.openide.filesystems.FileSystem;
39
import org.openide.filesystems.FileUtil;
40
import org.openide.filesystems.FileUtil;
41
import org.openide.filesystems.Repository;
42
import org.openide.util.Lookup;
43
import org.openide.util.Utilities;
44
import org.openide.util.lookup.AbstractLookup;
45
import org.openide.util.lookup.Lookups;
46
import org.openide.util.lookup.ProxyLookup;
47
48
/** Interface for core/startup to provide lookup overt system filesystem.
49
 *
50
 * @author Jaroslav Tulach
51
 */
52
public final class RecognizeInstanceFiles extends NamedServicesProvider {
53
    private static final Logger LOG = Logger.getLogger(RecognizeInstanceFiles.class.getName());
54
    
55
    
56
    public Lookup create(String path) {
57
        return new OverFiles(path);
58
    }        
59
    
60
    
61
    private static final class OverFiles extends ProxyLookup 
62
    implements FileChangeListener {
63
        private final String path;
64
        private final FileChangeListener weakL;
65
        private final AbstractLookup.Content content;
66
        private final AbstractLookup lkp;
67
        
68
        public OverFiles(String path) {
69
            this(path, new ArrayList<FOItem>(), new AbstractLookup.Content());
70
        }
71
72
        private OverFiles(String path, List<FOItem> items, AbstractLookup.Content cnt) {
73
            this(path, items, new AbstractLookup(cnt), cnt);
74
        }
75
        
76
        private OverFiles(String path, List<FOItem> items, AbstractLookup lkp, AbstractLookup.Content cnt) {
77
            super(computeDelegates(path, items, lkp));
78
            this.path = path;
79
            this.lkp = lkp;
80
            this.content = cnt;
81
            this.content.setPairs(items);
82
            
83
            FileSystem fs = Repository.getDefault().getDefaultFileSystem();
84
            this.weakL = FileUtil.weakFileChangeListener(this, fs);
85
            fs.addFileChangeListener(weakL);
86
        }
87
        
88
        private void refresh() {
89
            List<FOItem> items = new ArrayList<FOItem>();
90
            Lookup[] delegates = computeDelegates(path, items, lkp);
91
            
92
            this.content.setPairs(items);
93
            this.setLookups(delegates);
94
        }
95
        
96
        private static Lookup[] computeDelegates(String p, List<FOItem> items, Lookup lkp) {
97
            FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(p);
98
            List<Lookup> delegates = new LinkedList<Lookup>();
99
            delegates.add(lkp);
100
            if (fo != null) {
101
                for (FileObject f : fo.getChildren()) {
102
                    if (f.isFolder()) {
103
                        delegates.add(new OverFiles(f.getPath()));
104
                    } else {
105
                        items.add(new FOItem(f));
106
                    }
107
                }
108
109
            }
110
            delegates.add(
111
                Lookups.metaInfServices(Thread.currentThread().getContextClassLoader(), "META-INF/namedservices/" + p) // NOI18N
112
            );
113
            return delegates.toArray(new Lookup[0]);
114
        }
115
    
116
        public void fileFolderCreated(FileEvent fe) {
117
            refresh();
118
        }
119
120
        public void fileDataCreated(FileEvent fe) {
121
            refresh();
122
        }
123
124
        public void fileChanged(FileEvent fe) {
125
            refresh();
126
        }
127
128
        public void fileDeleted(FileEvent fe) {
129
            refresh();
130
        }
131
132
        public void fileRenamed(FileRenameEvent fe) {
133
            refresh();
134
        }
135
136
        public void fileAttributeChanged(FileAttributeEvent fe) {
137
            refresh();
138
        }
139
    } // end of OverFiles
140
    
141
    
142
    private static final class FOItem extends AbstractLookup.Pair<Object> {
143
        private static Reference<Object> EMPTY = new WeakReference<Object>(null);
144
        private FileObject fo;
145
        private Reference<Object> ref = EMPTY;
146
        
147
        public FOItem(FileObject fo) {
148
            this.fo = fo;
149
        }
150
151
        protected boolean instanceOf(Class<?> c) {
152
            Object r = ref.get();
153
            if (r != null) {
154
                return c.isInstance(r);
155
            } else {
156
                return c.isAssignableFrom(getType());
157
            }
158
        }
159
160
        protected boolean creatorOf(Object obj) {
161
            return ref.get() == obj;
162
        }
163
164
        public synchronized Object getInstance() {
165
            Object r = ref.get();
166
            if (r == null) {
167
                r = fo.getAttribute("instanceCreate");
168
                if (r != null) {
169
                    ref = new WeakReference<Object>(r);
170
                }
171
            }
172
            return r;
173
        }
174
175
        public Class<? extends Object> getType() {
176
            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
177
            if (l == null) {
178
                l = FOItem.class.getClassLoader();
179
            }
180
            try {
181
                return Class.forName(getClassName(fo), false, l);
182
            } catch (ClassNotFoundException ex) {
183
                LOG.log(Level.INFO, ex.getMessage(), ex);
184
                return Object.class;
185
            }
186
        }
187
188
        public String getId() {
189
            return fo.getPath();
190
        }
191
192
        public String getDisplayName() {
193
            String n = fo.getName();
194
            try {
195
                n = fo.getFileSystem().getStatus().annotateName(n, Collections.singleton(fo));
196
            } catch (FileStateInvalidException ex) {
197
                LOG.log(Level.WARNING, ex.getMessage(), ex);
198
            }
199
            return n;
200
        }
201
        
202
        /** get class name from specified file object*/
203
        private static String getClassName(FileObject fo) {
204
            // first of all try "instanceClass" property of the primary file
205
            Object attr = fo.getAttribute ("instanceClass");
206
            if (attr instanceof String) {
207
                return Utilities.translate((String) attr);
208
            } else if (attr != null) {
209
                LOG.warning(
210
                    "instanceClass was a " + attr.getClass().getName()); // NOI18N
211
            }
212
213
            attr = fo.getAttribute("instanceCreate");
214
            if (attr != null) {
215
                return attr.getClass().getName();
216
            }
217
218
            // otherwise extract the name from the filename
219
            String name = fo.getName ();
220
221
            int first = name.indexOf('[') + 1;
222
            if (first != 0) {
223
                LOG.log(Level.WARNING, "Cannot understand {0}", fo);
224
            }
225
226
            int last = name.indexOf (']');
227
            if (last < 0) {
228
                last = name.length ();
229
            }
230
231
            // take only a part of the string
232
            if (first < last) {
233
                name = name.substring (first, last);
234
            }
235
236
            name = name.replace ('-', '.');
237
            name = Utilities.translate(name);
238
239
            //System.out.println ("Original: " + getPrimaryFile ().getName () + " new one: " + name); // NOI18N
240
            return name;
241
        }
242
243
        public boolean equals(Object obj) {
244
            if (obj == null)
245
                return false;
246
            if (getClass() != obj.getClass())
247
                return false;
248
            final FOItem other = (FOItem) obj;
249
250
            if (this.fo != other.fo &&
251
                (this.fo == null || !this.fo.equals(other.fo)))
252
                return false;
253
            return true;
254
        }
255
256
        public int hashCode() {
257
            int hash = 3;
258
259
            hash = 11 * hash + (this.fo != null ? this.fo.hashCode()
260
                                                : 0);
261
            return hash;
262
        }
263
264
    } // end of FOItem
265
}
(-)core/startup/test/unit/src/org/netbeans/core/startup/layers/NamedFSServicesLookupTest.java (+71 lines)
Added Link Here
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.netbeans.core.startup.layers;
21
22
import org.netbeans.core.startup.MainLookup;
23
import org.openide.filesystems.FileObject;
24
import org.openide.filesystems.FileUtil;
25
import org.openide.filesystems.Repository;
26
import org.openide.modules.ModuleInfo;
27
import org.openide.util.Lookup;
28
import org.openide.util.lookup.Lookups;
29
import org.openide.util.lookup.NamedServicesLookupTest;
30
31
32
/** Test finding services from manifest and .instance files.
33
 * @author Jaroslav Tulach
34
 */
35
public class NamedFSServicesLookupTest extends NamedServicesLookupTest{
36
    private FileObject root;
37
    
38
    public NamedFSServicesLookupTest(String name) {
39
        super(name);
40
    }
41
    
42
    @Override
43
    protected void setUp() throws Exception {
44
        Lookup.getDefault().lookup(ModuleInfo.class);
45
        assertEquals(MainLookup.class, Lookup.getDefault().getClass());
46
47
        root = Repository.getDefault().getDefaultFileSystem().getRoot();
48
        
49
        super.setUp();
50
    }
51
    
52
    public void testLoadFromTheSFS() throws Exception {
53
        doLoad("inst/sub");
54
    }
55
    public void testLoadFromSubdirTheSFS() throws Exception {
56
        doLoad("inst");
57
    }
58
    
59
    private void doLoad(String lkpName) throws Exception {
60
        FileObject inst = FileUtil.createData(root, "inst/sub/X.instance");
61
        inst.setAttribute("instanceCreate", Long.valueOf(1000));
62
        
63
        Lookup l = Lookups.namedServices(lkpName);
64
        Long lng = l.lookup(Long.class);
65
        assertNotNull("A value found", lng);
66
        
67
        inst.delete();
68
        
69
        assertNull("Now it is null", l.lookup(Long.class));
70
    }
71
}
(-)openide/loaders/src/org/openide/loaders/FolderLookup.java (+2 lines)
Lines 38-44 Link Here
38
 * in the lookup system easily.
38
 * in the lookup system easily.
39
 * @author  Jaroslav Tulach
39
 * @author  Jaroslav Tulach
40
 * @since 1.11
40
 * @since 1.11
41
 * @deprecated use {@link Lookup#namedService} instead.
41
 */
42
 */
43
@Deprecated
42
public class FolderLookup extends FolderInstance {
44
public class FolderLookup extends FolderInstance {
43
    
45
    
44
    /** Lock for initiliazation of lookup. */
46
    /** Lock for initiliazation of lookup. */
(-)openide/util/nbproject/project.properties (-1 / +1 lines)
Lines 19-25 Link Here
19
javac.source=1.5
19
javac.source=1.5
20
module.jar.dir=lib
20
module.jar.dir=lib
21
21
22
spec.version.base=7.7.0
22
spec.version.base=7.8.0
23
23
24
# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
24
# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
25
25
(-)openide/util/src/org/netbeans/modules/openide/util/NamedServicesProvider.java (+69 lines)
Added Link Here
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. 
17
 *
18
 * Portions Copyrighted 2006 Sun Microsystems, Inc.
19
 */
20
21
package org.netbeans.modules.openide.util;
22
23
import java.lang.ref.Reference;
24
import java.lang.ref.WeakReference;
25
import java.util.HashMap;
26
import java.util.Map;
27
import org.openide.util.Lookup;
28
import org.openide.util.Lookup;
29
import org.openide.util.lookup.Lookups;
30
31
/** Interface for core/startup to provide lookup overt system filesystem.
32
 *
33
 * @author Jaroslav Tulach
34
 */
35
public abstract class NamedServicesProvider {
36
    private static volatile Map<String,Reference<Lookup>> map = new HashMap<String,Reference<Lookup>>();
37
    
38
    
39
    public abstract Lookup create(String path);
40
    
41
    public static synchronized Lookup find(String path) {
42
        if (!path.endsWith("/")) {
43
            path = path + "/";
44
        }
45
        
46
        Reference<Lookup> ref = map.get(path);
47
        Lookup lkp = ref == null ? null : ref.get();
48
        if (lkp != null) {
49
            return lkp;
50
        }
51
        NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
52
        if (prov != null) {
53
            lkp = prov.create(path);
54
        } else {
55
            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
56
            if (l == null) {
57
                l = Thread.currentThread().getContextClassLoader();
58
                if (l == null) {
59
                    l = NamedServicesProvider.class.getClassLoader();
60
                }
61
            }
62
            lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
63
        }
64
        
65
        map.put(path, new WeakReference<Lookup>(lkp));
66
        return lkp;
67
    }
68
    
69
}
(-)openide/util/src/org/openide/util/lookup/Lookups.java (-1 / +31 lines)
Lines 21-26 Link Here
21
21
22
import java.util.Arrays;
22
import java.util.Arrays;
23
import java.util.Collections;
23
import java.util.Collections;
24
import org.netbeans.modules.openide.util.NamedServicesProvider;
24
import org.openide.util.Lookup;
25
import org.openide.util.Lookup;
25
26
26
/**
27
/**
Lines 134-142 Link Here
134
     * @since 3.35
135
     * @since 3.35
135
     */
136
     */
136
    public static Lookup metaInfServices(ClassLoader classLoader) {
137
    public static Lookup metaInfServices(ClassLoader classLoader) {
137
        return new MetaInfServicesLookup(classLoader);
138
        return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
138
    }
139
    }
139
140
141
    /** Returns a lookup that behaves exactly as the one
142
     * created <code>metaInfServices(ClassLoader)</code> except that
143
     * it does not read data from META-INF/services, but instead
144
     * from the specified <code>prefix</code>.
145
     * @param classLoader class loader to use for loading
146
     * @param prefix prefix to prepend to the class name when searching
147
     * @since JST-PENDING
148
     */
149
    public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
150
        return new MetaInfServicesLookup(classLoader, prefix);
151
    }
152
    
153
    /** Creates a <q>named</q> lookup. It is a lookup identified by a 
154
     * given path. Two lookups with the same path are going to have 
155
     * the same content. It is expected that each <q>named</q> lookup
156
     * will contain a superset of what would lookup created by
157
     * <code>metaInfServices(theRightLoader, "META-INF/namedservices/" + path)</code>
158
     * contain. However various environments can add their own
159
     * extensions to its content. For example when running inside NetBeans Runtime
160
     * Container, the content of system file system under the given
161
     * <code>path</code> is also present in the returned lookup.
162
     * 
163
     * @param path the path identifying the lookup, for example <q>Databases/</q>, etc.
164
     * @since JST-PENDING
165
     */
166
    public static Lookup namedServices(String path) {
167
        return NamedServicesProvider.find(path);
168
    }
169
    
140
    /** Creates a lookup that wraps another one and filters out instances
170
    /** Creates a lookup that wraps another one and filters out instances
141
     * of specified classes. If you have a lookup and
171
     * of specified classes. If you have a lookup and
142
     * you want to remove all instances of ActionMap you can use:
172
     * you want to remove all instances of ActionMap you can use:
(-)openide/util/src/org/openide/util/lookup/MetaInfServicesLookup.java (-9 / +5 lines)
Lines 68-85 Link Here
68
68
69
    /** class loader to use */
69
    /** class loader to use */
70
    private final ClassLoader loader;
70
    private final ClassLoader loader;
71
71
    /** prefix to prepend */
72
    /** Create a lookup reading from the classpath.
72
    private final String prefix;
73
     * That is, the same classloader as this class itself.
74
     */
75
    public MetaInfServicesLookup() {
76
        this(MetaInfServicesLookup.class.getClassLoader());
77
    }
78
73
79
    /** Create a lookup reading from a specified classloader.
74
    /** Create a lookup reading from a specified classloader.
80
     */
75
     */
81
    public MetaInfServicesLookup(ClassLoader loader) {
76
    public MetaInfServicesLookup(ClassLoader loader, String prefix) {
82
        this.loader = loader;
77
        this.loader = loader;
78
        this.prefix = prefix;
83
79
84
        LOGGER.log(Level.FINE, "Created: {0}", this);
80
        LOGGER.log(Level.FINE, "Created: {0}", this);
85
    }
81
    }
Lines 123-129 Link Here
123
            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
119
            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
124
        }
120
        }
125
121
126
        String res = "META-INF/services/" + clazz.getName(); // NOI18N
122
        String res = prefix + clazz.getName(); // NOI18N
127
        Enumeration<URL> en;
123
        Enumeration<URL> en;
128
124
129
        try {
125
        try {
(-)openide/util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java (-14 / +47 lines)
Lines 24-35 Link Here
24
import java.io.IOException;
24
import java.io.IOException;
25
import java.io.InputStream;
25
import java.io.InputStream;
26
import java.io.InputStreamReader;
26
import java.io.InputStreamReader;
27
import java.lang.ref.Reference;
28
import java.lang.ref.WeakReference;
27
import java.net.URL;
29
import java.net.URL;
28
import java.net.URLClassLoader;
30
import java.net.URLClassLoader;
29
import java.util.ArrayList;
31
import java.util.ArrayList;
30
import java.util.Collections;
32
import java.util.Collections;
31
import java.util.Enumeration;
33
import java.util.Enumeration;
34
import java.util.HashMap;
35
import java.util.HashSet;
32
import java.util.List;
36
import java.util.List;
37
import java.util.Map;
33
import java.util.Set;
38
import java.util.Set;
34
import java.util.Set;
39
import java.util.Set;
35
import java.util.TreeSet;
40
import java.util.TreeSet;
Lines 44-69 Link Here
44
import org.openide.util.LookupEvent;
49
import org.openide.util.LookupEvent;
45
import org.openide.util.LookupListener;
50
import org.openide.util.LookupListener;
46
import org.openide.util.RequestProcessor;
51
import org.openide.util.RequestProcessor;
52
import org.openide.util.WeakSet;
47
53
48
/** Test finding services from manifest.
54
/** Test finding services from manifest.
49
 * @author Jesse Glick
55
 * @author Jesse Glick
50
 */
56
 */
51
public class MetaInfServicesLookupTest extends NbTestCase {
57
public class MetaInfServicesLookupTest extends NbTestCase {
52
    private Logger LOG;
58
    private Logger LOG;
59
    private Map<ClassLoader,Lookup> lookups = new HashMap<ClassLoader,Lookup>();
53
    
60
    
54
    public MetaInfServicesLookupTest(String name) {
61
    public MetaInfServicesLookupTest(String name) {
55
        super(name);
62
        super(name);
56
        LOG = Logger.getLogger("Test." + name);
63
        LOG = Logger.getLogger("Test." + name);
57
    }
64
    }
58
    
65
    
59
    private String prefix() {
66
    protected String prefix() {
60
        return "META-INF/services/";
67
        return "META-INF/services/";
61
    }
68
    }
62
    
69
    
70
    protected Lookup createLookup(ClassLoader c) {
71
        return Lookups.metaInfServices(c);
72
    }
73
    
63
    protected Level logLevel() {
74
    protected Level logLevel() {
64
        return Level.INFO;
75
        return Level.INFO;
65
    }
76
    }
66
77
78
    private Lookup getTestedLookup(ClassLoader c) {
79
        Lookup l = lookups.get(c);
80
        if (l == null) {
81
            l = createLookup(c);
82
            lookups.put(c, l);
83
        }
84
        return l;
85
    }
86
67
    private URL findJar(String n) throws IOException {
87
    private URL findJar(String n) throws IOException {
68
        LOG.info("Looking for " + n);
88
        LOG.info("Looking for " + n);
69
        File jarDir = new File(getWorkDir(), "jars");
89
        File jarDir = new File(getWorkDir(), "jars");
Lines 154-161 Link Here
154
        }, c0);
174
        }, c0);
155
    }
175
    }
156
176
177
    protected void tearDown() throws Exception {
178
        Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
179
        for (Lookup l : lookups.values()) {
180
            weak.add(new WeakReference<Lookup>(l));
181
        }
182
        
183
        lookups = null;
184
        
185
        for(Reference<Lookup> ref : weak) {
186
            assertGC("Lookup can disappear", ref);
187
        }
188
    }
189
157
    public void testBasicUsage() throws Exception {
190
    public void testBasicUsage() throws Exception {
158
        Lookup l = Lookups.metaInfServices(c2);
191
        Lookup l = getTestedLookup(c2);
159
        Class xface = c1.loadClass("org.foo.Interface");
192
        Class xface = c1.loadClass("org.foo.Interface");
160
        List results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
193
        List results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
161
        assertEquals(2, results.size());
194
        assertEquals(2, results.size());
Lines 169-179 Link Here
169
202
170
    public void testLoaderSkew() throws Exception {
203
    public void testLoaderSkew() throws Exception {
171
        Class xface1 = c1.loadClass("org.foo.Interface");
204
        Class xface1 = c1.loadClass("org.foo.Interface");
172
        Lookup l3 = Lookups.metaInfServices(c3);
205
        Lookup l3 = getTestedLookup(c3);
173
        // If we cannot load Interface, there should be no impls of course... quietly!
206
        // If we cannot load Interface, there should be no impls of course... quietly!
174
        assertEquals(Collections.EMPTY_LIST,
207
        assertEquals(Collections.EMPTY_LIST,
175
                new ArrayList(l3.lookup(new Lookup.Template(xface1)).allInstances()));
208
                new ArrayList(l3.lookup(new Lookup.Template(xface1)).allInstances()));
176
        Lookup l4 = Lookups.metaInfServices(c4);
209
        Lookup l4 = getTestedLookup(c4);
177
        // If we can load Interface but it is the wrong one, ignore it.
210
        // If we can load Interface but it is the wrong one, ignore it.
178
        assertEquals(Collections.EMPTY_LIST,
211
        assertEquals(Collections.EMPTY_LIST,
179
                new ArrayList(l4.lookup(new Lookup.Template(xface1)).allInstances()));
212
                new ArrayList(l4.lookup(new Lookup.Template(xface1)).allInstances()));
Lines 183-200 Link Here
183
    }
216
    }
184
217
185
    public void testStability() throws Exception {
218
    public void testStability() throws Exception {
186
        Lookup l = Lookups.metaInfServices(c2);
219
        Lookup l = getTestedLookup(c2);
187
        Class xface = c1.loadClass("org.foo.Interface");
220
        Class xface = c1.loadClass("org.foo.Interface");
188
        Object first = l.lookup(new Lookup.Template(xface)).allInstances().iterator().next();
221
        Object first = l.lookup(new Lookup.Template(xface)).allInstances().iterator().next();
189
        l = Lookups.metaInfServices(c2a);
222
        l = getTestedLookup(c2a);
190
        Object second = l.lookup(new Lookup.Template(xface)).allInstances().iterator().next();
223
        Object second = l.lookup(new Lookup.Template(xface)).allInstances().iterator().next();
191
        assertEquals(first, second);
224
        assertEquals(first, second);
192
    }
225
    }
193
226
194
    public void testMaskingOfResources() throws Exception {
227
    public void testMaskingOfResources() throws Exception {
195
        Lookup l1 = Lookups.metaInfServices(c1);
228
        Lookup l1 = getTestedLookup(c1);
196
        Lookup l2 = Lookups.metaInfServices(c2);
229
        Lookup l2 = getTestedLookup(c2);
197
        Lookup l4 = Lookups.metaInfServices(c4);
230
        Lookup l4 = getTestedLookup(c4);
198
231
199
        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
232
        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
200
        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
233
        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
Lines 202-213 Link Here
202
    }
235
    }
203
236
204
    public void testOrdering() throws Exception {
237
    public void testOrdering() throws Exception {
205
        Lookup l = Lookups.metaInfServices(c1);
238
        Lookup l = getTestedLookup(c1);
206
        Class xface = c1.loadClass("java.util.Comparator");
239
        Class xface = c1.loadClass("java.util.Comparator");
207
        List results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
240
        List results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
208
        assertEquals(1, results.size());
241
        assertEquals(1, results.size());
209
242
210
        l = Lookups.metaInfServices(c2);
243
        l = getTestedLookup(c2);
211
        xface = c2.loadClass("java.util.Comparator");
244
        xface = c2.loadClass("java.util.Comparator");
212
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
245
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
213
        assertEquals(2, results.size());
246
        assertEquals(2, results.size());
Lines 216-222 Link Here
216
        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
249
        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
217
250
218
        // test that items without position are always at the end
251
        // test that items without position are always at the end
219
        l = Lookups.metaInfServices(c2);
252
        l = getTestedLookup(c2);
220
        xface = c2.loadClass("java.util.Iterator");
253
        xface = c2.loadClass("java.util.Iterator");
221
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
254
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
222
        assertEquals(2, results.size());
255
        assertEquals(2, results.size());
Lines 251-257 Link Here
251
            }
284
            }
252
        }
285
        }
253
        Loader loader = new Loader();
286
        Loader loader = new Loader();
254
        Lookup l = Lookups.metaInfServices(loader);
287
        Lookup l = getTestedLookup(loader);
255
288
256
        Object no = l.lookup(String.class);
289
        Object no = l.lookup(String.class);
257
        assertNull("Not found of course", no);
290
        assertNull("Not found of course", no);
Lines 259-265 Link Here
259
    }
292
    }
260
293
261
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035() throws Exception {
294
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035() throws Exception {
262
        final Lookup l = Lookups.metaInfServices(c2);
295
        final Lookup l = getTestedLookup(c2);
263
        final Class xface = c1.loadClass("org.foo.Interface");
296
        final Class xface = c1.loadClass("org.foo.Interface");
264
        final Lookup.Result res = l.lookup(new Lookup.Template(Object.class));
297
        final Lookup.Result res = l.lookup(new Lookup.Template(Object.class));
265
298
(-)openide/util/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java (+70 lines)
Added Link Here
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.util.lookup;
21
22
import org.openide.util.Lookup;
23
24
25
/** Test finding services from manifest.
26
 * @author Jaroslav Tulach
27
 */
28
public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
29
    public NamedServicesLookupTest(String name) {
30
        super(name);
31
    }
32
    
33
    protected String prefix() {
34
        return "META-INF/namedservices/sub/path/";
35
    }
36
    
37
    protected Lookup createLookup(ClassLoader c) {
38
        ClassLoader prev = Thread.currentThread().getContextClassLoader();
39
        Thread.currentThread().setContextClassLoader(c);
40
        Lookup l = Lookups.namedServices("sub/path");
41
        Thread.currentThread().setContextClassLoader(prev);
42
        return l;
43
    }
44
    
45
    //
46
    // this is not much inheriting test, as we mask most of the tested methods
47
    // anyway, but the infrastructure to generate the JAR files is useful
48
    //
49
    
50
    public void testLoaderSkew() throws Exception {
51
    }
52
53
    public void testStability() throws Exception {
54
    }
55
56
    public void testMaskingOfResources() throws Exception {
57
    }
58
59
    public void testOrdering() throws Exception {
60
    }
61
62
    public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
63
    }
64
65
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035() throws Exception {
66
    }
67
    
68
    
69
    
70
}
(-)openide/util/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java (+41 lines)
Added Link Here
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.util.lookup;
21
22
import org.openide.util.Lookup;
23
24
25
/** Test finding services from manifest.
26
 * @author Jaroslav Tulach
27
 */
28
public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
29
    public PrefixServicesLookupTest(String name) {
30
        super(name);
31
    }
32
    
33
    protected String prefix() {
34
        return "META-INF/netbeans/prefix/services/test/";
35
    }
36
    
37
    protected Lookup createLookup(ClassLoader c) {
38
        return Lookups.metaInfServices(c, prefix());
39
    }
40
    
41
}

Return to bug 98426