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

(-)api/doc/org/openide/doc-files/services-api.html (-1 / +17 lines)
Lines 853-859 Link Here
853
<P>
853
<P>
854
854
855
<div class="nonnormative">
855
<div class="nonnormative">
856
    The Lookup supports a small extension to the 
856
    The Lookup supports two small extensions to the 
857
    <a href="http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#Service%20Provider">JDK's
857
    <a href="http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#Service%20Provider">JDK's
858
    standard</a>. It allows a module to remove class registered by
858
    standard</a>. It allows a module to remove class registered by
859
    another one. That is why it is possible to write a module that
859
    another one. That is why it is possible to write a module that
Lines 871-876 Link Here
871
    compatibility with JDK's implementation. The <em>#</em> means comment
871
    compatibility with JDK's implementation. The <em>#</em> means comment
872
    and thus JDK will not interpret the line and will not get confused by
872
    and thus JDK will not interpret the line and will not get confused by
873
    the <em>-</em> before class name.
873
    the <em>-</em> before class name.
874
    
875
    <p>Second extension allows ordering of items. The class implementing
876
    the interface can be followed by advisory position attribute. When 
877
    querying on an interface, items with a smaller position are guaranteed 
878
    to be returned before items with a larger position. Items with no defined 
879
    position are returned last. Example of content of 
880
    <font class="function-name">META-INF/services/org.me.MyService</font>
881
    file could be:
882
    <pre>
883
  <font class="type">org.you.MyServiceImpl</font>
884
  #position=10
885
    </pre>
886
    It is recommended to pick up larger numbers so that there is
887
    gap for other modules if they need to get in front of your item. And, 
888
    again, to keep compatibility the position attribute must starts with
889
    comment delimiter.</p>
874
</DIV>
890
</DIV>
875
891
876
<P>
892
<P>
(-)src/org/openide/util/lookup/MetaInfServicesLookup.java (-5 / +67 lines)
Lines 113-119 Link Here
113
        // has the same entry in it (and they load to the same class).
113
        // has the same entry in it (and they load to the same class).
114
        // Probably would not happen, assuming JARs only list classes
114
        // Probably would not happen, assuming JARs only list classes
115
        // they own, but just in case...
115
        // they own, but just in case...
116
        Collection foundClasses = new ArrayList (); // Collection<Class>
116
        List/*<Item>*/ foundClasses = new ArrayList();
117
        Collection removeClasses = new ArrayList (); // Collection<Class>
117
        Collection removeClasses = new ArrayList (); // Collection<Class>
118
118
119
        boolean foundOne = false;
119
        boolean foundOne = false;
Lines 152-157 Link Here
152
            }
152
            }
153
            
153
            
154
            URL url = (URL)en.nextElement();
154
            URL url = (URL)en.nextElement();
155
            Item currentItem = null;
155
            try {
156
            try {
156
                InputStream is = url.openStream();
157
                InputStream is = url.openStream();
157
                try {
158
                try {
Lines 160-167 Link Here
160
                        String line = reader.readLine();
161
                        String line = reader.readLine();
161
                        if (line == null) break;
162
                        if (line == null) break;
162
163
163
                        // Ignore blank lines and comments.
164
                        line = line.trim();
164
                        line = line.trim();
165
                        // is it position attribute?
166
                        if (line.startsWith("#position=")) {
167
                            if (currentItem == null) {
168
                                assert false : "Found line '"+line+"' but there is no item to associate it with!";
169
                            }
170
                            try {
171
                                currentItem.position = Integer.parseInt(line.substring(10));
172
                            } catch (NumberFormatException e) {
173
                                // do not use ErrorManager because we are in the startup code
174
                                // and ErrorManager might not be ready
175
                                e.printStackTrace();
176
                            }
177
                        }
178
                        if (currentItem != null) {
179
                            insertItem(currentItem, foundClasses);
180
                            currentItem = null;
181
                        }
182
                        
183
                        // Ignore blank lines and comments.
165
                        if (line.length() == 0) continue;
184
                        if (line.length() == 0) continue;
166
                        
185
                        
167
                        boolean remove = false;
186
                        boolean remove = false;
Lines 196-204 Link Here
196
                        if (remove) {
215
                        if (remove) {
197
                            removeClasses.add (inst);
216
                            removeClasses.add (inst);
198
                        } else {
217
                        } else {
199
                            foundClasses.add(inst);
218
                            // create new item here, but do not put it into
219
                            // foundClasses array yet because following line
220
                            // might specify its position
221
                            currentItem = new Item();
222
                            currentItem.clazz = inst;
200
                        }
223
                        }
201
                    }
224
                    }
225
                    if (currentItem != null) {
226
                        insertItem(currentItem, foundClasses);
227
                        currentItem = null;
228
                    }
202
                } finally {
229
                } finally {
203
                    is.close();
230
                    is.close();
204
                }
231
                }
Lines 217-225 Link Here
217
        foundClasses.removeAll (removeClasses);
244
        foundClasses.removeAll (removeClasses);
218
        Iterator it = foundClasses.iterator ();
245
        Iterator it = foundClasses.iterator ();
219
        while (it.hasNext ()) {
246
        while (it.hasNext ()) {
220
            Class inst = (Class)it.next ();
247
            Item item = (Item)it.next ();
221
            result.add(new P(inst));
248
            if (removeClasses.contains(item.clazz)) {
249
                continue;
250
            }
251
            result.add(new P(item.clazz));
252
        }
253
    }
254
    
255
    /**
256
     * Insert item to the list according to item.position value.
257
     */
258
    private void insertItem(Item item, List list) {
259
        // no position? -> add it to the end
260
        if (item.position == -1) {
261
            list.add(item);
262
            return;
263
        }
264
        int index = -1;
265
        Iterator it = list.iterator();
266
        while (it.hasNext()) {
267
            index++;
268
            Item i = (Item)it.next();
269
            if (i.position == -1) {
270
                list.add(index, item);
271
                return;
272
            } else {
273
                if (i.position > item.position) {
274
                    list.add(index, item);
275
                    return;
276
                }
277
            }
222
        }
278
        }
279
        list.add(item);
280
    }
281
    
282
    private static class Item {
283
        private Class clazz;
284
        private int position = -1;
223
    }
285
    }
224
    
286
    
225
    /** Pair that holds name of a class and maybe the instance.
287
    /** Pair that holds name of a class and maybe the instance.
(-)test/unit/src/org/openide/util/MetaInfServicesLookupTest.java (+24 lines)
Lines 100-105 Link Here
100
        assertNull ("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup (Runnable.class));
100
        assertNull ("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup (Runnable.class));
101
    }
101
    }
102
    
102
    
103
    public void testOrdering() throws Exception {
104
        Lookup l = Lookups.metaInfServices(c1);
105
        Class xface = c1.loadClass("java.util.Comparator");
106
        List results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
107
        assertEquals(1, results.size());
108
        
109
        l = Lookups.metaInfServices(c2);
110
        xface = c2.loadClass("java.util.Comparator");
111
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
112
        assertEquals(2, results.size());
113
        // Test order:
114
        assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
115
        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
116
117
        // test that items without position are always at the end
118
        l = Lookups.metaInfServices(c2);
119
        xface = c2.loadClass("java.util.Iterator");
120
        results = new ArrayList(l.lookup(new Lookup.Template(xface)).allInstances());
121
        assertEquals(2, results.size());
122
        // Test order:
123
        assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
124
        assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
125
    }
126
    
103
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035 () throws Exception {
127
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035 () throws Exception {
104
        final Lookup l = Lookups.metaInfServices(c2);
128
        final Lookup l = Lookups.metaInfServices(c2);
105
        final Class xface = c1.loadClass("org.foo.Interface");
129
        final Class xface = c1.loadClass("org.foo.Interface");
(-)test/unit/src/org/openide/util/data/services-jar-1/META-INF/services/java.util.Comparator (+4 lines)
Added Link Here
1
#some comment
2
org.foo.impl.Comparator1
3
#position=10
4
#som comment2
(-)test/unit/src/org/openide/util/data/services-jar-1/META-INF/services/java.util.Iterator (+1 lines)
Added Link Here
1
org.foo.impl.Iterator1
(-)test/unit/src/org/openide/util/data/services-jar-1/org/foo/impl/Comparator1.java (+7 lines)
Added Link Here
1
2
package org.foo.impl;
3
4
public class Comparator1 implements java.util.Comparator {
5
    public int compare(Object o1, Object o2) {return 0;}
6
    public boolean equals(Object obj) {return true;}
7
}
(-)test/unit/src/org/openide/util/data/services-jar-1/org/foo/impl/Iterator1.java (+11 lines)
Added Link Here
1
2
package org.foo.impl;
3
4
public class Iterator1 implements java.util.Iterator {
5
    public boolean hasNext() {return false;}
6
    
7
    public Object next() {return null;}
8
    
9
    public void remove() {}
10
   
11
}
(-)test/unit/src/org/openide/util/data/services-jar-2/META-INF/services/java.util.Comparator (+2 lines)
Added Link Here
1
org.bar.Comparator2
2
#position=5
(-)test/unit/src/org/openide/util/data/services-jar-2/META-INF/services/java.util.Iterator (+2 lines)
Added Link Here
1
org.bar.Iterator2
2
#position=100
(-)test/unit/src/org/openide/util/data/services-jar-2/org/bar/Comparator2.java (+7 lines)
Added Link Here
1
2
package org.bar;
3
4
public class Comparator2 implements java.util.Comparator {
5
    public int compare(Object o1, Object o2) {return 0;}
6
    public boolean equals(Object obj) {return true;}
7
}
(-)test/unit/src/org/openide/util/data/services-jar-2/org/bar/Iterator2.java (+11 lines)
Added Link Here
1
2
package org.bar;
3
4
public class Iterator2 implements java.util.Iterator {
5
    public boolean hasNext() {return false;}
6
    
7
    public Object next() {return null;}
8
    
9
    public void remove() {}
10
   
11
}

Return to bug 41606