diff -r 9e26a4666530 openide.util.lookup/apichanges.xml --- a/openide.util.lookup/apichanges.xml Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util.lookup/apichanges.xml Tue Mar 20 10:58:38 2012 +0100 @@ -49,6 +49,27 @@ Lookup API + + + Easy and robust way to register named services + + + + + +

+ Meta annotation @NamedServiceDefinition + for those who define their own annotations that register + something into Lookups.forPath. +

+
+ + +
ProxyLookup computes results lazily diff -r 9e26a4666530 openide.util.lookup/manifest.mf --- a/openide.util.lookup/manifest.mf Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util.lookup/manifest.mf Tue Mar 20 10:58:38 2012 +0100 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.util.lookup OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties -OpenIDE-Module-Specification-Version: 8.13 +OpenIDE-Module-Specification-Version: 8.14 diff -r 9e26a4666530 openide.util.lookup/src/META-INF/services/javax.annotation.processing.Processor --- a/openide.util.lookup/src/META-INF/services/javax.annotation.processing.Processor Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util.lookup/src/META-INF/services/javax.annotation.processing.Processor Tue Mar 20 10:58:38 2012 +0100 @@ -1,1 +1,2 @@ org.netbeans.modules.openide.util.ServiceProviderProcessor +org.netbeans.modules.openide.util.NamedServiceProcessor \ No newline at end of file diff -r 9e26a4666530 openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServiceProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServiceProcessor.java Tue Mar 20 10:58:38 2012 +0100 @@ -0,0 +1,213 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.openide.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.annotation.Annotation; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; +import org.openide.util.lookup.NamedServiceDefinition; +import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor; + +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public final class NamedServiceProcessor extends AbstractServiceProviderProcessor { + private static final String PATH = "META-INF/namedservices.index"; // NOI18N + + @Override + public Set getSupportedAnnotationTypes() { + Set all = new HashSet(); + all.add(NamedServiceDefinition.class.getName()); + searchAnnotations(all, true); + return all; + } + + + @Override + protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getElementsAnnotatedWith(NamedServiceDefinition.class)) { + NamedServiceDefinition nsd = e.getAnnotation(NamedServiceDefinition.class); + register(e, PATH); + } + + Set index = new HashSet(); + searchAnnotations(index, false); + for (String className : index) { + Class c; + try { + c = Class.forName(className).asSubclass(Annotation.class); + } catch (ClassNotFoundException ex) { + throw new IllegalStateException(ex); + } + for (Element e : roundEnv.getElementsAnnotatedWith(c)) { + Annotation a = e.getAnnotation(c); + NamedServiceDefinition nsd = c.getAnnotation(NamedServiceDefinition.class); + int cnt = 0; + for (Class type : nsd.serviceType()) { + TypeMirror typeMirror = asType(type); + if (processingEnv.getTypeUtils().isSubtype(e.asType(), typeMirror)) { + cnt++; + for (String p : findPath(nsd.path(), a)) { + register( + e, c, typeMirror, p, + findPosition(nsd.position(), a) + ); + } + } + if (cnt == 0) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Not right subclass!", e); + } + } + } + } + return true; + } + + private TypeMirror asType(Class type) { + return processingEnv.getElementUtils().getTypeElement(type.getName()).asType(); + } + + private static Pattern reference; + private List findPath(String path, Annotation a) { + if (reference == null) { + reference = Pattern.compile("@([^/]+)\\(\\)"); // NOI18N + } + List arr = new ArrayList(); + arr.add(path); + RESTART: for (;;) { + for (int i = 0; i < arr.size(); i++) { + Matcher m = reference.matcher(arr.get(i)); + if (m.find()) { + String methodName = m.group(1); + System.err.println("search for " + m.group(1) + " in " + path); + Object obj; + try { + obj = a.getClass().getMethod(methodName).invoke(a); + } catch (Exception ex) { + throw new IllegalStateException(methodName, ex); + } + if (obj instanceof String) { + arr.set(i, substitute(path, m, (String)obj)); + } else if (obj instanceof String[]) { + String[] subs = (String[])obj; + arr.set(i, substitute(path, m, subs[0])); + for (int j = 1; j < subs.length; j++) { + arr.add(substitute(path, m, subs[j])); + } + } else { + throw new IllegalStateException("Wrong return value " + obj); // NOI18N + } + continue RESTART; + } + } + break RESTART; + } + return arr; + } + + private Integer findPosition(String posDefinition, Annotation a) { + if (posDefinition.length() == 1 && posDefinition.charAt(0) == 0) { + try { + return (Integer)a.getClass().getMethod("position").invoke(a); + } catch (NoSuchMethodException ex) { + return Integer.MAX_VALUE; + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + try { + return (Integer)a.getClass().getMethod(posDefinition).invoke(a); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + + private static void searchAnnotations(Set found, boolean canonicalName) { + + try { + Enumeration en = NamedServiceProcessor.class.getClassLoader().getResources(PATH); + while (en.hasMoreElements()) { + URL url = en.nextElement(); + InputStream is = url.openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N + + // XXX consider using ServiceLoaderLine instead + while (true) { + String line = reader.readLine(); + + if (line == null) { + break; + } + line = line.trim(); + if (line.startsWith("#")) { // NOI18N + continue; + } + if (canonicalName) { + line = line.replace('$', '.'); + } + found.add(line); + } + } + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + + private static String substitute(String path, Matcher m, String obj) { + return path.substring(0, m.start(0)) + obj + path.substring(m.end(0)); + } +} diff -r 9e26a4666530 openide.util.lookup/src/org/openide/util/lookup/NamedServiceDefinition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util.lookup/src/org/openide/util/lookup/NamedServiceDefinition.java Tue Mar 20 10:58:38 2012 +0100 @@ -0,0 +1,95 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.openide.util.lookup; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotation to simplify creation and add robustness to usage of + * various named service registration annotations. For example + * the {@code @} + * URLStreamHandlerRegistration annotation uses the {@link NamedServiceDefinition} + * as:
+ * {@code @NamedServiceDefinition(path="URLStreamHandler/@protocol()", serviceType=URLStreamHandler.class)}
+ * 
+ * The above instructs the annotation processor that handles {@link NamedServiceDefinition}s + * to verify the annotated type is subclass of URLStreamHandler and + * if so, register it into URLStreamHandler/@protocol where the + * value of @protocol() is replaced by the value of annotation's + * + * protocol attribute. The registration can later be found by using + * {@link Lookups#forPath(java.lang.String) Lookups.forPath("URLStreamHandler/ftp")} + * (in case the protocol was ftp). + * + * @author Jaroslav Tulach + * @since 8.14 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface NamedServiceDefinition { + /** Type, or array of types that the registered type + * has to implement. + */ + public Class[] serviceType(); + /** Path to register the annotation to, so it can later be found by + * using {@link Lookups#forPath(java.lang.String) Lookups.forPath(theSamePath)}. + * The path may reference attributes of the annotated annotation by prefixing + * them with {@code @}. To reuse attribute named location one + * can for example use "how/to/get/to/@location/please" + * These attributes must be of type String + * or array of Strings. + */ + public String path(); + /** Name of attribute that specifies position. By default the system tries + * to find int position() attribute in the defined annotation + * and use it to specify the order of registrations. In case a different + * attribute should be used to specify position, can be provide its + * name by specifying non-default here. Should the position be ignored, + * specify empty string. + * + * @param name of attribute in the annotated annotation to use for defining + * position of the registration. The attribute should return int value. + */ + public String position() default "\u0000"; +} diff -r 9e26a4666530 openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java Tue Mar 20 10:58:38 2012 +0100 @@ -97,9 +97,13 @@ // OK subclass return; } + if (getClass().getName().equals("org.netbeans.modules.openide.util.NamedServiceProcessor")) { // NOI18N + // OK subclass + return; + } throw new IllegalStateException(); } - + public @Override final boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.errorRaised()) { return false; @@ -135,13 +139,24 @@ * @param supersedes possibly empty list of implementation to supersede * @since 8.8 */ - protected final void register(Element el, Class annotation, - TypeMirror type, String path, int position, String[] supersedes) { + protected final void register( + Element el, Class annotation, + TypeMirror type, String path, int position, String... supersedes + ) { if (el.getKind() != ElementKind.CLASS) { processingEnv.getMessager().printMessage(Kind.ERROR, annotation.getName() + " is not applicable to a " + el.getKind(), el); return; } TypeElement clazz = (TypeElement) el; + String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString(); + String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString(); + if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) { + AnnotationMirror ann = findAnnotationMirror(clazz, annotation); + processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface, + clazz, ann, findAnnotationValue(ann, "service")); + return; + } + String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface; Boolean verify = verifiedClasses.get(clazz); if (verify == null) { verify = verifyServiceProviderSignature(clazz, annotation); @@ -150,19 +165,22 @@ if (!verify) { return; } + registerImpl(clazz, impl, rsrc, position, supersedes); + } + + protected final void register(Element el, String path) { + TypeElement clazz = (TypeElement)el; String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString(); - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString(); - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) { - AnnotationMirror ann = findAnnotationMirror(clazz, annotation); - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface, - clazz, ann, findAnnotationValue(ann, "service")); - return; - } + registerImpl(clazz, impl, path, Integer.MAX_VALUE); + } + + private void registerImpl( + TypeElement clazz, String impl, String rsrc, int position, String... supersedes + ) { /* processingEnv.getMessager().printMessage(Kind.NOTE, impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : "")); */ - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface; Filer filer = processingEnv.getFiler(); { Map> originatingElements = originatingElementsByProcessor.get(filer); diff -r 9e26a4666530 openide.util.lookup/test/unit/src/org/openide/util/lookup/NamedServiceDefinitionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/NamedServiceDefinitionTest.java Tue Mar 20 10:58:38 2012 +0100 @@ -0,0 +1,132 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.openide.util.lookup; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.concurrent.Callable; +import org.netbeans.junit.NbTestCase; +import org.openide.util.Lookup; +import org.openide.util.test.AnnotationProcessorTestUtils; + +/** + * + * @author Jaroslav Tulach + */ +public class NamedServiceDefinitionTest extends NbTestCase { + + public NamedServiceDefinitionTest(String n) { + super(n); + } + + @Override + protected void setUp() throws Exception { + clearWorkDir(); + } + + public void testNamedDefinition() throws Exception { + System.setProperty("executed", "false"); + String content = "import org.openide.util.lookup.NamedServiceDefinitionTest.RunTestReg;\n" + + "@RunTestReg(position=10,when=\"now\")\n" + + "public class Test implements Runnable {\n" + + " public void run() { System.setProperty(\"executed\", \"true\"); }\n" + + "}\n"; + AnnotationProcessorTestUtils.makeSource(getWorkDir(), "x.Test", content); + assertTrue("Compiles OK", + AnnotationProcessorTestUtils.runJavac(getWorkDir(), null, getWorkDir(), null, System.err) + ); + + URLClassLoader l = new URLClassLoader(new URL[] { getWorkDir().toURI().toURL() }, NamedServiceDefinitionTest.class.getClassLoader()); + Lookup lkp = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/now/below/"); + for (Runnable r : lkp.lookupAll(Runnable.class)) { + r.run(); + } + assertEquals("Our runnable was executed", "true", System.getProperty("executed")); + } + + public void testNamedDefinitionWithArray() throws Exception { + System.setProperty("executed", "false"); + String content = "import org.openide.util.lookup.NamedServiceDefinitionTest.RunTestArray;\n" + + "@RunTestArray(position=10,array={\"now\", \"then\" })\n" + + "public class Test implements Runnable {\n" + + " public void run() { System.setProperty(\"executed\", \"true\"); }\n" + + "}\n"; + AnnotationProcessorTestUtils.makeSource(getWorkDir(), "x.Test", content); + assertTrue("Compiles OK", + AnnotationProcessorTestUtils.runJavac(getWorkDir(), null, getWorkDir(), null, System.err) + ); + + URLClassLoader l = new URLClassLoader(new URL[] { getWorkDir().toURI().toURL() }, NamedServiceDefinitionTest.class.getClassLoader()); + Lookup lkp = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/now/"); + for (Runnable r : lkp.lookupAll(Runnable.class)) { + r.run(); + } + assertEquals("Our runnable was executed", "true", System.getProperty("executed")); + System.setProperty("executed", "false"); + Lookup lkp2 = Lookups.metaInfServices(l, "META-INF/namedservices/runtest/then/"); + for (Runnable r : lkp2.lookupAll(Runnable.class)) { + r.run(); + } + assertEquals("Our runnable was executed again", "true", System.getProperty("executed")); + } + + @NamedServiceDefinition( + path="runtest/@when()/below", + serviceType={ Runnable.class, Callable.class } + ) + @Retention(RetentionPolicy.SOURCE) + public static @interface RunTestReg { + public int position(); + public String when(); + } + @NamedServiceDefinition( + path="runtest/@array()", + serviceType={ Runnable.class, Callable.class } + ) + @Retention(RetentionPolicy.SOURCE) + public static @interface RunTestArray { + public int position(); + public String[] array(); + } +} diff -r 9e26a4666530 openide.util/nbproject/project.xml --- a/openide.util/nbproject/project.xml Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util/nbproject/project.xml Tue Mar 20 10:58:38 2012 +0100 @@ -54,7 +54,7 @@ - 8.8 + 8.14 diff -r 9e26a4666530 openide.util/src/org/netbeans/modules/openide/util/ProxyURLStreamHandlerFactory.java --- a/openide.util/src/org/netbeans/modules/openide/util/ProxyURLStreamHandlerFactory.java Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util/src/org/netbeans/modules/openide/util/ProxyURLStreamHandlerFactory.java Tue Mar 20 10:58:38 2012 +0100 @@ -62,7 +62,6 @@ */ @ServiceProvider(service=URLStreamHandlerFactory.class) public final class ProxyURLStreamHandlerFactory implements URLStreamHandlerFactory { - /** prevents GC only */ private final Map> results = new HashMap>(); private final Map handlers = new HashMap(); @@ -74,7 +73,7 @@ return null; } if (!results.containsKey(protocol)) { - final Lookup.Result result = Lookups.forPath(URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX + protocol).lookupResult(URLStreamHandler.class); + final Lookup.Result result = Lookups.forPath("URLStreamHandler/" + protocol).lookupResult(URLStreamHandler.class); LookupListener listener = new LookupListener() { public @Override void resultChanged(LookupEvent ev) { synchronized (ProxyURLStreamHandlerFactory.this) { diff -r 9e26a4666530 openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java --- a/openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java Mon Mar 19 16:35:39 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2010 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.net.URLStreamHandler; -import java.util.Collections; -import java.util.Set; -import javax.annotation.processing.Processor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; -import org.openide.util.URLStreamHandlerRegistration; -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor; - -@ServiceProvider(service=Processor.class) -@SupportedSourceVersion(SourceVersion.RELEASE_6) -public class URLStreamHandlerRegistrationProcessor extends AbstractServiceProviderProcessor { - - public @Override Set getSupportedAnnotationTypes() { - return Collections.singleton(URLStreamHandlerRegistration.class.getCanonicalName()); - } - - public static final String REGISTRATION_PREFIX = "URLStreamHandler/"; // NOI18N - - protected @Override boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { - for (Element el : roundEnv.getElementsAnnotatedWith(URLStreamHandlerRegistration.class)) { - URLStreamHandlerRegistration r = el.getAnnotation(URLStreamHandlerRegistration.class); - TypeMirror type = processingEnv.getTypeUtils().getDeclaredType( - processingEnv.getElementUtils().getTypeElement(URLStreamHandler.class.getName())); - for (String protocol : r.protocol()) { - register(el, URLStreamHandlerRegistration.class, type, - REGISTRATION_PREFIX + protocol, r.position(), new String[0]); - } - } - return true; - } - -} diff -r 9e26a4666530 openide.util/src/org/openide/util/URLStreamHandlerRegistration.java --- a/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java Mon Mar 19 16:35:39 2012 +0100 +++ b/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java Tue Mar 20 10:58:38 2012 +0100 @@ -49,6 +49,7 @@ import java.net.URL; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; +import org.openide.util.lookup.NamedServiceDefinition; /** * Replacement for {@link URLStreamHandlerFactory} within the NetBeans platform. @@ -62,6 +63,7 @@ * from a unit test or otherwise without the module system active. * @since org.openide.util 7.31 */ +@NamedServiceDefinition(path="URLStreamHandler/@protocol()", serviceType=URLStreamHandler.class) @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface URLStreamHandlerRegistration {