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

(-)a/openide.util.lookup/apichanges.xml (+21 lines)
Lines 49-54 Link Here
49
    <apidef name="lookup">Lookup API</apidef>
49
    <apidef name="lookup">Lookup API</apidef>
50
</apidefs>
50
</apidefs>
51
<changes>
51
<changes>
52
    <change id="named.service.definition">
53
        <api name="lookup"/>
54
        <summary>Easy and robust way to register named services</summary>
55
        <version major="8" minor="14"/>
56
        <date day="27" month="3" year="2012"/>
57
        <author login="jtulach"/>
58
        <compatibility
59
            addition="yes"
60
            binary="compatible" deletion="no" deprecation="no"
61
            modification="no" semantic="compatible" source="compatible"
62
        />
63
        <description>
64
            <p>
65
                Meta annotation <code>@NamedServiceDefinition</code> 
66
                for those who define their own annotations that register
67
                something into <code>Lookups.forPath</code>.
68
            </p>
69
        </description>
70
        <class package="org.openide.util.lookup" name="NamedServiceDefinition"/>
71
        <issue number="179289"/>
72
    </change>
52
    <change id="lazy.proxy.lookup">
73
    <change id="lazy.proxy.lookup">
53
        <api name="lookup"/>
74
        <api name="lookup"/>
54
        <summary><code>ProxyLookup</code> computes results lazily</summary>
75
        <summary><code>ProxyLookup</code> computes results lazily</summary>
(-)a/openide.util.lookup/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.util.lookup
2
OpenIDE-Module: org.openide.util.lookup
3
OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
4
OpenIDE-Module-Specification-Version: 8.13
4
OpenIDE-Module-Specification-Version: 8.14
5
5
(-)a/openide.util.lookup/src/META-INF/services/javax.annotation.processing.Processor (+1 lines)
Line 1 Link Here
1
org.netbeans.modules.openide.util.ServiceProviderProcessor
1
org.netbeans.modules.openide.util.ServiceProviderProcessor
2
org.netbeans.modules.openide.util.NamedServiceProcessor
(-)9e26a4666530 (+213 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.openide.util;
43
44
import java.io.BufferedReader;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.io.InputStreamReader;
48
import java.lang.annotation.Annotation;
49
import java.net.URL;
50
import java.util.ArrayList;
51
import java.util.Enumeration;
52
import java.util.HashSet;
53
import java.util.List;
54
import java.util.Set;
55
import java.util.regex.Matcher;
56
import java.util.regex.Pattern;
57
import javax.annotation.processing.RoundEnvironment;
58
import javax.annotation.processing.SupportedSourceVersion;
59
import javax.lang.model.SourceVersion;
60
import javax.lang.model.element.Element;
61
import javax.lang.model.element.TypeElement;
62
import javax.lang.model.type.TypeMirror;
63
import javax.tools.Diagnostic;
64
import org.openide.util.lookup.NamedServiceDefinition;
65
import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor;
66
67
@SupportedSourceVersion(SourceVersion.RELEASE_6)
68
public final class NamedServiceProcessor extends AbstractServiceProviderProcessor {
69
    private static final String PATH = "META-INF/namedservices.index"; // NOI18N
70
71
    @Override
72
    public Set<String> getSupportedAnnotationTypes() {
73
        Set<String> all = new HashSet<String>();
74
        all.add(NamedServiceDefinition.class.getName());
75
        searchAnnotations(all, true);
76
        return all;
77
    }
78
    
79
80
    @Override
81
    protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
82
        for (Element e : roundEnv.getElementsAnnotatedWith(NamedServiceDefinition.class)) {
83
            NamedServiceDefinition nsd = e.getAnnotation(NamedServiceDefinition.class);
84
            register(e, PATH);
85
        }
86
        
87
        Set<String> index = new HashSet<String>();
88
        searchAnnotations(index, false);
89
        for (String className : index) {
90
            Class<? extends Annotation> c;
91
            try {
92
                c = Class.forName(className).asSubclass(Annotation.class);
93
            } catch (ClassNotFoundException ex) {
94
                throw new IllegalStateException(ex);
95
            }
96
            for (Element e : roundEnv.getElementsAnnotatedWith(c)) {
97
                Annotation a = e.getAnnotation(c);
98
                NamedServiceDefinition nsd = c.getAnnotation(NamedServiceDefinition.class);
99
                int cnt = 0;
100
                for (Class<?> type : nsd.serviceType()) {
101
                    TypeMirror typeMirror = asType(type);
102
                    if (processingEnv.getTypeUtils().isSubtype(e.asType(), typeMirror)) {
103
                        cnt++;
104
                        for (String p : findPath(nsd.path(), a)) {
105
                            register(
106
                                e, c, typeMirror, p,
107
                                findPosition(nsd.position(), a)
108
                            );
109
                        }
110
                    }
111
                    if (cnt == 0) {
112
                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Not right subclass!", e);
113
                    }
114
                }
115
            }
116
        }
117
        return true;
118
    }
119
120
    private TypeMirror asType(Class<?> type) {
121
        return processingEnv.getElementUtils().getTypeElement(type.getName()).asType();
122
    }
123
124
    private static Pattern reference;
125
    private List<String> findPath(String path, Annotation a) {
126
        if (reference == null) {
127
            reference = Pattern.compile("@([^/]+)\\(\\)"); // NOI18N
128
        }
129
        List<String> arr = new ArrayList<String>();
130
        arr.add(path);
131
        RESTART: for (;;) {
132
            for (int i = 0; i < arr.size(); i++) {
133
                Matcher m = reference.matcher(arr.get(i));
134
                if (m.find()) {
135
                    String methodName = m.group(1);
136
                    System.err.println("search for " + m.group(1) + " in " + path);
137
                    Object obj;
138
                    try {
139
                        obj = a.getClass().getMethod(methodName).invoke(a);
140
                    } catch (Exception ex) {
141
                        throw new IllegalStateException(methodName, ex);
142
                    }
143
                    if (obj instanceof String) {
144
                        arr.set(i, substitute(path, m, (String)obj));
145
                    } else if (obj instanceof String[]) {
146
                        String[] subs = (String[])obj;
147
                        arr.set(i, substitute(path, m, subs[0]));
148
                        for (int j = 1; j < subs.length; j++) {
149
                            arr.add(substitute(path, m, subs[j]));
150
                        }
151
                    } else {
152
                        throw new IllegalStateException("Wrong return value " + obj); // NOI18N
153
                    }
154
                    continue RESTART;
155
                }
156
            }
157
            break RESTART;
158
        }
159
        return arr;
160
    }
161
    
162
    private Integer findPosition(String posDefinition, Annotation a) {
163
        if (posDefinition.length() == 1 && posDefinition.charAt(0) == 0) {
164
            try {
165
                return (Integer)a.getClass().getMethod("position").invoke(a);
166
            } catch (NoSuchMethodException ex) {
167
                return Integer.MAX_VALUE;
168
            } catch (Exception ex) {
169
                throw new IllegalStateException(ex);
170
            }
171
        }
172
        try {
173
            return (Integer)a.getClass().getMethod(posDefinition).invoke(a);
174
        } catch (Exception ex) {
175
            throw new IllegalStateException(ex);
176
        }
177
    }
178
    
179
    private static void searchAnnotations(Set<String> found, boolean canonicalName) {
180
181
        try {
182
            Enumeration<URL> en = NamedServiceProcessor.class.getClassLoader().getResources(PATH);
183
            while (en.hasMoreElements()) {
184
                URL url = en.nextElement();
185
                InputStream is = url.openStream();
186
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
187
188
                // XXX consider using ServiceLoaderLine instead
189
                while (true) {
190
                    String line = reader.readLine();
191
192
                    if (line == null) {
193
                        break;
194
                    }
195
                    line = line.trim();
196
                    if (line.startsWith("#")) { // NOI18N
197
                        continue;
198
                    }
199
                    if (canonicalName) {
200
                        line = line.replace('$', '.');
201
                    }
202
                    found.add(line);
203
                }
204
            }
205
        } catch (IOException ex) {
206
            throw new IllegalStateException(ex);
207
        }
208
    }
209
210
    private static String substitute(String path, Matcher m, String obj) {
211
        return path.substring(0, m.start(0)) + obj + path.substring(m.end(0));
212
    }
213
}
(-)9e26a4666530 (+95 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.openide.util.lookup;
43
44
import java.lang.annotation.ElementType;
45
import java.lang.annotation.Retention;
46
import java.lang.annotation.RetentionPolicy;
47
import java.lang.annotation.Target;
48
49
/** Annotation to simplify creation and add robustness to usage of
50
 * various named service registration annotations. For example
51
 * the {@code @}<a href="@org-openide-util@/org/openide/util/URLStreamHandlerRegistration.html">
52
 * URLStreamHandlerRegistration</a> annotation uses the {@link NamedServiceDefinition}
53
 * as: <pre>
54
 * {@code @NamedServiceDefinition(path="URLStreamHandler/@protocol()", serviceType=URLStreamHandler.class)}
55
 * </pre>
56
 * The above instructs the annotation processor that handles {@link NamedServiceDefinition}s
57
 * to verify the annotated type is subclass of <code>URLStreamHandler</code> and
58
 * if so, register it into <code>URLStreamHandler/@protocol</code> where the
59
 * value of <code>@protocol()</code> is replaced by the value of annotation's
60
 * <a href="@org-openide-util@/org/openide/util/URLStreamHandlerRegistration.html#protocol()">
61
 * protocol attribute</a>. The registration can later be found by using
62
 * {@link Lookups#forPath(java.lang.String) Lookups.forPath("URLStreamHandler/ftp")}
63
 * (in case the protocol was ftp).
64
 *
65
 * @author Jaroslav Tulach <jtulach@netbeans.org>
66
 * @since 8.14
67
 */
68
@Retention(RetentionPolicy.RUNTIME)
69
@Target(ElementType.ANNOTATION_TYPE)
70
public @interface NamedServiceDefinition {
71
    /** Type, or array of types that the registered type
72
     * has to implement.
73
     */
74
    public Class<?>[] serviceType();
75
    /** Path to register the annotation to, so it can later be found by
76
     * using {@link Lookups#forPath(java.lang.String) Lookups.forPath(theSamePath)}.
77
     * The path may reference attributes of the annotated annotation by prefixing
78
     * them with {@code @}. To reuse attribute named <code>location</code> one
79
     * can for example use <code>"how/to/get/to/@location/please"</code>
80
     * These attributes must be of type <code>String</code>
81
     * or array of <code>String</code>s.
82
     */
83
    public String path();
84
    /** Name of attribute that specifies position. By default the system tries
85
     * to find <code>int position()</code> attribute in the defined annotation
86
     * and use it to specify the order of registrations. In case a different
87
     * attribute should be used to specify position, can be provide its
88
     * name by specifying non-default here. Should the position be ignored,
89
     * specify empty string.
90
     * 
91
     * @param name of attribute in the annotated annotation to use for defining
92
     *   position of the registration. The attribute should return int value.
93
     */
94
    public String position() default "\u0000";
95
}
(-)a/openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java (-11 / +29 lines)
Lines 97-105 Link Here
97
            // OK subclass
97
            // OK subclass
98
            return;
98
            return;
99
        }
99
        }
100
        if (getClass().getName().equals("org.netbeans.modules.openide.util.NamedServiceProcessor")) { // NOI18N
101
            // OK subclass
102
            return;
103
        }
100
        throw new IllegalStateException();
104
        throw new IllegalStateException();
101
    }
105
    }
102
106
    
103
    public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
107
    public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
104
        if (roundEnv.errorRaised()) {
108
        if (roundEnv.errorRaised()) {
105
            return false;
109
            return false;
Lines 135-147 Link Here
135
     * @param supersedes possibly empty list of implementation to supersede
139
     * @param supersedes possibly empty list of implementation to supersede
136
     * @since 8.8
140
     * @since 8.8
137
     */
141
     */
138
    protected final void register(Element el, Class<? extends Annotation> annotation,
142
    protected final void register(
139
            TypeMirror type, String path, int position, String[] supersedes) {
143
        Element el, Class<? extends Annotation> annotation,
144
        TypeMirror type, String path, int position, String... supersedes
145
    ) {
140
        if (el.getKind() != ElementKind.CLASS) {
146
        if (el.getKind() != ElementKind.CLASS) {
141
            processingEnv.getMessager().printMessage(Kind.ERROR, annotation.getName() + " is not applicable to a " + el.getKind(), el);
147
            processingEnv.getMessager().printMessage(Kind.ERROR, annotation.getName() + " is not applicable to a " + el.getKind(), el);
142
            return;
148
            return;
143
        }
149
        }
144
        TypeElement clazz = (TypeElement) el;
150
        TypeElement clazz = (TypeElement) el;
151
        String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
152
        String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
153
        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
154
            AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
155
            processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
156
                    clazz, ann, findAnnotationValue(ann, "service"));
157
            return;
158
        }
159
        String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
145
        Boolean verify = verifiedClasses.get(clazz);
160
        Boolean verify = verifiedClasses.get(clazz);
146
        if (verify == null) {
161
        if (verify == null) {
147
            verify = verifyServiceProviderSignature(clazz, annotation);
162
            verify = verifyServiceProviderSignature(clazz, annotation);
Lines 150-168 Link Here
150
        if (!verify) {
165
        if (!verify) {
151
            return;
166
            return;
152
        }
167
        }
168
        registerImpl(clazz, impl, rsrc, position, supersedes);
169
    }
170
    
171
    protected final void register(Element el, String path) {
172
        TypeElement clazz = (TypeElement)el;
153
        String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
173
        String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
154
        String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
174
        registerImpl(clazz, impl, path, Integer.MAX_VALUE);
155
        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
175
    }
156
            AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
176
    
157
            processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
177
    private void registerImpl(
158
                    clazz, ann, findAnnotationValue(ann, "service"));
178
        TypeElement clazz, String impl, String rsrc, int position, String... supersedes
159
            return;
179
    ) {
160
        }
161
        /*
180
        /*
162
        processingEnv.getMessager().printMessage(Kind.NOTE,
181
        processingEnv.getMessager().printMessage(Kind.NOTE,
163
                impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
182
                impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
164
        */
183
        */
165
        String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
166
        Filer filer = processingEnv.getFiler();
184
        Filer filer = processingEnv.getFiler();
167
        {
185
        {
168
            Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(filer);
186
            Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(filer);
(-)9e26a4666530 (+132 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.openide.util.lookup;
43
44
import java.lang.annotation.Retention;
45
import java.lang.annotation.RetentionPolicy;
46
import java.net.URL;
47
import java.net.URLClassLoader;
48
import java.util.concurrent.Callable;
49
import org.netbeans.junit.NbTestCase;
50
import org.openide.util.Lookup;
51
import org.openide.util.test.AnnotationProcessorTestUtils;
52
53
/**
54
 *
55
 * @author Jaroslav Tulach <jtulach@netbeans.org>
56
 */
57
public class NamedServiceDefinitionTest extends NbTestCase {
58
    
59
    public NamedServiceDefinitionTest(String n) {
60
        super(n);
61
    }
62
63
    @Override
64
    protected void setUp() throws Exception {
65
        clearWorkDir();
66
    }
67
    
68
    public void testNamedDefinition() throws Exception {
69
        System.setProperty("executed", "false");
70
        String content = "import org.openide.util.lookup.NamedServiceDefinitionTest.RunTestReg;\n"
71
            + "@RunTestReg(position=10,when=\"now\")\n"
72
            + "public class Test implements Runnable {\n"
73
            + "  public void run() { System.setProperty(\"executed\", \"true\"); }\n"
74
            + "}\n";
75
        AnnotationProcessorTestUtils.makeSource(getWorkDir(), "x.Test", content);
76
        assertTrue("Compiles OK",
77
            AnnotationProcessorTestUtils.runJavac(getWorkDir(), null, getWorkDir(), null, System.err)
78
            );
79
        
80
        URLClassLoader l = new URLClassLoader(new URL[] { getWorkDir().toURI().toURL() }, NamedServiceDefinitionTest.class.getClassLoader());
81
        Lookup lkp = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/now/below/");
82
        for (Runnable r : lkp.lookupAll(Runnable.class)) {
83
            r.run();
84
        }
85
        assertEquals("Our runnable was executed", "true", System.getProperty("executed"));
86
    }
87
    
88
    public void testNamedDefinitionWithArray() throws Exception {
89
        System.setProperty("executed", "false");
90
        String content = "import org.openide.util.lookup.NamedServiceDefinitionTest.RunTestArray;\n"
91
            + "@RunTestArray(position=10,array={\"now\", \"then\" })\n"
92
            + "public class Test implements Runnable {\n"
93
            + "  public void run() { System.setProperty(\"executed\", \"true\"); }\n"
94
            + "}\n";
95
        AnnotationProcessorTestUtils.makeSource(getWorkDir(), "x.Test", content);
96
        assertTrue("Compiles OK",
97
            AnnotationProcessorTestUtils.runJavac(getWorkDir(), null, getWorkDir(), null, System.err)
98
            );
99
        
100
        URLClassLoader l = new URLClassLoader(new URL[] { getWorkDir().toURI().toURL() }, NamedServiceDefinitionTest.class.getClassLoader());
101
        Lookup lkp = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/now/");
102
        for (Runnable r : lkp.lookupAll(Runnable.class)) {
103
            r.run();
104
        }
105
        assertEquals("Our runnable was executed", "true", System.getProperty("executed"));
106
        System.setProperty("executed", "false");
107
        Lookup lkp2 = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/then/");
108
        for (Runnable r : lkp2.lookupAll(Runnable.class)) {
109
            r.run();
110
        }
111
        assertEquals("Our runnable was executed again", "true", System.getProperty("executed"));
112
    }
113
    
114
    @NamedServiceDefinition(
115
        path="runtest/@when()/below",
116
        serviceType={ Runnable.class, Callable.class }
117
    )
118
    @Retention(RetentionPolicy.SOURCE)
119
    public static @interface RunTestReg {
120
        public int position();
121
        public String when();
122
    }
123
    @NamedServiceDefinition(
124
        path="runtest/@array()",
125
        serviceType={ Runnable.class, Callable.class }
126
    )
127
    @Retention(RetentionPolicy.SOURCE)
128
    public static @interface RunTestArray {
129
        public int position();
130
        public String[] array();
131
    }
132
}
(-)a/openide.util/nbproject/project.xml (-1 / +1 lines)
Lines 54-60 Link Here
54
                    <build-prerequisite/>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
55
                    <compile-dependency/>
56
                    <run-dependency>
56
                    <run-dependency>
57
                        <specification-version>8.8</specification-version>
57
                        <specification-version>8.14</specification-version>
58
                    </run-dependency>
58
                    </run-dependency>
59
                </dependency>
59
                </dependency>
60
            </module-dependencies>
60
            </module-dependencies>
(-)a/openide.util/src/org/netbeans/modules/openide/util/ProxyURLStreamHandlerFactory.java (-2 / +1 lines)
Lines 62-68 Link Here
62
 */
62
 */
63
@ServiceProvider(service=URLStreamHandlerFactory.class)
63
@ServiceProvider(service=URLStreamHandlerFactory.class)
64
public final class ProxyURLStreamHandlerFactory implements URLStreamHandlerFactory {
64
public final class ProxyURLStreamHandlerFactory implements URLStreamHandlerFactory {
65
66
    /** prevents GC only */
65
    /** prevents GC only */
67
    private final Map<String, Lookup.Result<URLStreamHandler>> results = new HashMap<String, Lookup.Result<URLStreamHandler>>();
66
    private final Map<String, Lookup.Result<URLStreamHandler>> results = new HashMap<String, Lookup.Result<URLStreamHandler>>();
68
    private final Map<String, URLStreamHandler> handlers = new HashMap<String, URLStreamHandler>();
67
    private final Map<String, URLStreamHandler> handlers = new HashMap<String, URLStreamHandler>();
Lines 74-80 Link Here
74
            return null;
73
            return null;
75
        }
74
        }
76
        if (!results.containsKey(protocol)) {
75
        if (!results.containsKey(protocol)) {
77
            final Lookup.Result<URLStreamHandler> result = Lookups.forPath(URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX + protocol).lookupResult(URLStreamHandler.class);
76
            final Lookup.Result<URLStreamHandler> result = Lookups.forPath("URLStreamHandler/" + protocol).lookupResult(URLStreamHandler.class);
78
            LookupListener listener = new LookupListener() {
77
            LookupListener listener = new LookupListener() {
79
                public @Override void resultChanged(LookupEvent ev) {
78
                public @Override void resultChanged(LookupEvent ev) {
80
                    synchronized (ProxyURLStreamHandlerFactory.this) {
79
                    synchronized (ProxyURLStreamHandlerFactory.this) {
(-)a/openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java (-82 lines)
Removed Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.openide.util;
44
45
import java.net.URLStreamHandler;
46
import java.util.Collections;
47
import java.util.Set;
48
import javax.annotation.processing.Processor;
49
import javax.annotation.processing.RoundEnvironment;
50
import javax.annotation.processing.SupportedSourceVersion;
51
import javax.lang.model.SourceVersion;
52
import javax.lang.model.element.Element;
53
import javax.lang.model.element.TypeElement;
54
import javax.lang.model.type.TypeMirror;
55
import org.openide.util.URLStreamHandlerRegistration;
56
import org.openide.util.lookup.ServiceProvider;
57
import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor;
58
59
@ServiceProvider(service=Processor.class)
60
@SupportedSourceVersion(SourceVersion.RELEASE_6)
61
public class URLStreamHandlerRegistrationProcessor extends AbstractServiceProviderProcessor {
62
63
    public @Override Set<String> getSupportedAnnotationTypes() {
64
        return Collections.singleton(URLStreamHandlerRegistration.class.getCanonicalName());
65
    }
66
67
    public static final String REGISTRATION_PREFIX = "URLStreamHandler/"; // NOI18N
68
69
    protected @Override boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
70
        for (Element el : roundEnv.getElementsAnnotatedWith(URLStreamHandlerRegistration.class)) {
71
            URLStreamHandlerRegistration r = el.getAnnotation(URLStreamHandlerRegistration.class);
72
            TypeMirror type = processingEnv.getTypeUtils().getDeclaredType(
73
                    processingEnv.getElementUtils().getTypeElement(URLStreamHandler.class.getName()));
74
            for (String protocol : r.protocol()) {
75
                register(el, URLStreamHandlerRegistration.class, type,
76
                        REGISTRATION_PREFIX + protocol, r.position(), new String[0]);
77
            }
78
        }
79
        return true;
80
    }
81
82
}
(-)a/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java (+2 lines)
Lines 49-54 Link Here
49
import java.net.URL;
49
import java.net.URL;
50
import java.net.URLStreamHandler;
50
import java.net.URLStreamHandler;
51
import java.net.URLStreamHandlerFactory;
51
import java.net.URLStreamHandlerFactory;
52
import org.openide.util.lookup.NamedServiceDefinition;
52
53
53
/**
54
/**
54
 * Replacement for {@link URLStreamHandlerFactory} within the NetBeans platform.
55
 * Replacement for {@link URLStreamHandlerFactory} within the NetBeans platform.
Lines 62-67 Link Here
62
 * from a unit test or otherwise without the module system active.
63
 * from a unit test or otherwise without the module system active.
63
 * @since org.openide.util 7.31
64
 * @since org.openide.util 7.31
64
 */
65
 */
66
@NamedServiceDefinition(path="URLStreamHandler/@protocol()", serviceType=URLStreamHandler.class)
65
@Retention(RetentionPolicy.SOURCE)
67
@Retention(RetentionPolicy.SOURCE)
66
@Target(ElementType.TYPE)
68
@Target(ElementType.TYPE)
67
public @interface URLStreamHandlerRegistration {
69
public @interface URLStreamHandlerRegistration {

Return to bug 209780