# HG changeset patch # User Jesse Glick # Date 1256334403 14400 Issue #20838: declarative registration of URLStreamHandler instances by protocol. diff --git a/core.startup/src/org/netbeans/core/startup/NbURLStreamHandlerFactory.java b/core.startup/src/org/netbeans/core/startup/NbResourceStreamHandler.java rename from core.startup/src/org/netbeans/core/startup/NbURLStreamHandlerFactory.java rename to core.startup/src/org/netbeans/core/startup/NbResourceStreamHandler.java --- a/core.startup/src/org/netbeans/core/startup/NbURLStreamHandlerFactory.java +++ b/core.startup/src/org/netbeans/core/startup/NbResourceStreamHandler.java @@ -47,47 +47,18 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; -import org.openide.filesystems.FileUtil; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.URLStreamHandlerRegistration; -/** - * Proxying stream handler factory. Currently searches Lookup for registered - * factories and delegates to them. But #20838 suggests using JNDI instead, - * in which case registering them via Lookup would be deprecated. - * @author Jesse Glick - */ -@org.openide.util.lookup.ServiceProvider(service=java.net.URLStreamHandlerFactory.class) -public final class NbURLStreamHandlerFactory implements URLStreamHandlerFactory { - - /** public for lookup */ - public NbURLStreamHandlerFactory() {} - - public URLStreamHandler createURLStreamHandler(String protocol) { - if (protocol.equals("nbfs")) { // NOI18N - return FileUtil.nbfsURLStreamHandler(); - } - - if (protocol.equals(NbResourceStreamHandler.PROTOCOL_SYSTEM_RESOURCE) || - protocol.equals(NbResourceStreamHandler.PROTOCOL_LOCALIZED_SYSTEM_RESOURCE)) { - return new NbResourceStreamHandler(); - } - - return null; - } - /** Stream handler for internal resource-based URLs. - * Copied with modifications from org.openide.execution - that version is now - * deprecated and handles only deprecated protocols. * @author Jesse Glick */ - private static final class NbResourceStreamHandler extends URLStreamHandler { - - public NbResourceStreamHandler() {} + @URLStreamHandlerRegistration(protocol={NbResourceStreamHandler.PROTOCOL_SYSTEM_RESOURCE, NbResourceStreamHandler.PROTOCOL_LOCALIZED_SYSTEM_RESOURCE}) + public final class NbResourceStreamHandler extends URLStreamHandler { public static final String PROTOCOL_SYSTEM_RESOURCE = "nbres"; // NOI18N public static final String PROTOCOL_LOCALIZED_SYSTEM_RESOURCE = "nbresloc"; // NOI18N @@ -133,7 +104,7 @@ if (resource.length() > 0 && resource.charAt(0) == '/') { // NOI18N resource = resource.substring(1); } else { - Logger.getLogger(NbURLStreamHandlerFactory.class.getName()).log(Level.WARNING, "URL path should begin with a slash: " + url); + Logger.getLogger(NbResourceStreamHandler.class.getName()).log(Level.WARNING, "URL path should begin with a slash: " + url); } ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class); URL target; @@ -166,7 +137,7 @@ target = t1; } if (target == null) { - throw new IOException(NbBundle.getMessage(NbURLStreamHandlerFactory.class, "EXC_nbres_cannot_connect", url)); + throw new IOException(NbBundle.getMessage(NbResourceStreamHandler.class, "EXC_nbres_cannot_connect", url)); } real = target.openConnection(); real.connect(); @@ -267,5 +238,3 @@ } } - -} diff --git a/core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandlerFactory.java b/core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandler.java rename from core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandlerFactory.java rename to core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandler.java --- a/core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandlerFactory.java +++ b/core.startup/src/org/netbeans/core/startup/layers/NbinstURLStreamHandler.java @@ -47,43 +47,19 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; import java.net.UnknownServiceException; import org.openide.filesystems.FileObject; import org.openide.util.Exceptions; +import org.openide.util.URLStreamHandlerRegistration; /** - * StreamHandlerFactory for nbinst protocol + * URLStreamHandler for nbinst protocol */ -@org.openide.util.lookup.ServiceProvider(service=java.net.URLStreamHandlerFactory.class) -public class NbinstURLStreamHandlerFactory implements URLStreamHandlerFactory { +@URLStreamHandlerRegistration(protocol=NbinstURLMapper.PROTOCOL) +public class NbinstURLStreamHandler extends URLStreamHandler { - /** - * Creates URLStreamHandler for nbinst protocol - * @param protocol - * @return NbinstURLStreamHandler if the protocol is nbinst otherwise null - */ - public URLStreamHandler createURLStreamHandler(String protocol) { - if (NbinstURLMapper.PROTOCOL.equals(protocol)) { - return new NbinstURLStreamHandler (); - } - return null; - } - - /** - * URLStreamHandler for nbinst protocol - */ - private static class NbinstURLStreamHandler extends URLStreamHandler { - - /** - * Creates URLConnection for URL with nbinst protocol. - * @param u URL for which the URLConnection should be created - * @return URLConnection - * @throws IOException - */ - protected URLConnection openConnection(URL u) throws IOException { - return new NbinstURLConnection (u); - } + protected URLConnection openConnection(URL u) throws IOException { + return new NbinstURLConnection(u); } /** URLConnection for URL with nbinst protocol. diff --git a/core.startup/test/unit/src/org/netbeans/core/startup/layers/NbinstURLMapperTest.java b/core.startup/test/unit/src/org/netbeans/core/startup/layers/NbinstURLMapperTest.java --- a/core.startup/test/unit/src/org/netbeans/core/startup/layers/NbinstURLMapperTest.java +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/NbinstURLMapperTest.java @@ -77,7 +77,6 @@ MockServices.setServices( TestInstalledFileLocator.class, - NbinstURLStreamHandlerFactory.class, NbinstURLMapper.class); org.netbeans.core.startup.Main.initializeURLFactory (); diff --git a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandlerFactory.java b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandler.java rename from ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandlerFactory.java rename to ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandler.java --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandlerFactory.java +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FoDURLStreamHandler.java @@ -46,24 +46,16 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; +import org.openide.util.URLStreamHandlerRegistration; /** * * @author Jaroslav Tulach */ -@ServiceProvider(service=URLStreamHandlerFactory.class, position=99999) -public class FoDURLStreamHandlerFactory implements URLStreamHandlerFactory { +@URLStreamHandlerRegistration(protocol="ergoloc") +public class FoDURLStreamHandler extends URLStreamHandler { - public URLStreamHandler createURLStreamHandler(String protocol) { - if (protocol.equals("ergoloc")) { - return new FoDSH(); - } - return null; - } - private static final class FoDSH extends URLStreamHandler { @Override protected URLConnection openConnection(URL u) throws IOException { URL orig = new URL("nbresloc", u.getHost(), u.getPort(), u.getFile()); // NOI18N @@ -79,7 +71,7 @@ throw new IOException(); } String head = new String(arr, 0, len, "UTF-8"); // NOI18N - String newHead = head.replaceFirst("<[bB][oO][dD][yY]>", NbBundle.getMessage(FoDSH.class, "MSG_NotEnabled")); // NOI18N + String newHead = head.replaceFirst("<[bB][oO][dD][yY]>", NbBundle.getMessage(FoDURLStreamHandler.class, "MSG_NotEnabled")); // NOI18N ByteArrayInputStream headIS = new ByteArrayInputStream(newHead.getBytes("UTF-8")); // NOI18N final SequenceInputStream seq = new SequenceInputStream(headIS, is); @@ -97,5 +89,4 @@ }; } - } } diff --git a/javahelp/src/org/netbeans/modules/javahelp/NbDocsStreamHandler.java b/javahelp/src/org/netbeans/modules/javahelp/NbDocsStreamHandler.java --- a/javahelp/src/org/netbeans/modules/javahelp/NbDocsStreamHandler.java +++ b/javahelp/src/org/netbeans/modules/javahelp/NbDocsStreamHandler.java @@ -50,22 +50,13 @@ import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.URLStreamHandlerRegistration; /** Handler & connection cribbed from NbResourceStreamHandler. * @author Jesse Glick */ -final class NbDocsStreamHandler extends URLStreamHandler { - - @org.openide.util.lookup.ServiceProvider(service=java.net.URLStreamHandlerFactory.class) - public static final class Factory implements URLStreamHandlerFactory { - public URLStreamHandler createURLStreamHandler(String protocol) { - if (protocol.equals("nbdocs")) { // NOI18N - return new NbDocsStreamHandler(); - } else { - return null; - } - } - } +@URLStreamHandlerRegistration(protocol="nbdocs") +public final class NbDocsStreamHandler extends URLStreamHandler { /** Make a URLConnection for nbdocs: URLs. * @param u the URL diff --git a/o.n.bootstrap/src/org/netbeans/ProxyURLStreamHandlerFactory.java b/o.n.bootstrap/src/org/netbeans/ProxyURLStreamHandlerFactory.java --- a/o.n.bootstrap/src/org/netbeans/ProxyURLStreamHandlerFactory.java +++ b/o.n.bootstrap/src/org/netbeans/ProxyURLStreamHandlerFactory.java @@ -53,6 +53,7 @@ import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; +import org.openide.util.URLStreamHandlerRegistration; import org.openide.util.Utilities; /** @@ -154,7 +155,8 @@ public void resultChanged(LookupEvent ev) { Collection c = r.allInstances(); synchronized (this) { - handlers = c.toArray(new URLStreamHandlerFactory[0]); + handlers = c.toArray(new URLStreamHandlerFactory[c.size() + 1]); + handlers[c.size()] = new URLStreamHandlerRegistration.ProxyURLStreamHandlerFactory(); } } diff --git a/openide.filesystems/src/org/netbeans/modules/openide/filesystems/RecognizeInstanceFiles.java b/openide.filesystems/src/org/netbeans/modules/openide/filesystems/RecognizeInstanceFiles.java --- a/openide.filesystems/src/org/netbeans/modules/openide/filesystems/RecognizeInstanceFiles.java +++ b/openide.filesystems/src/org/netbeans/modules/openide/filesystems/RecognizeInstanceFiles.java @@ -69,6 +69,17 @@ public Lookup create(String path) { + if (path.equals("URLStreamHandler/nbres/")) { // NOI18N + // Need to avoid a stack overflow during initialization. + ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); + if (l == null) { + l = Thread.currentThread().getContextClassLoader(); + if (l == null) { + l = RecognizeInstanceFiles.class.getClassLoader(); + } + } + return Lookups.metaInfServices(l, "META-INF/namedservices/URLStreamHandler/nbres/"); // NOI18N + } return new OverFiles(path); } diff --git a/openide.filesystems/src/org/openide/filesystems/FileURL.java b/openide.filesystems/src/org/openide/filesystems/FileURL.java --- a/openide.filesystems/src/org/openide/filesystems/FileURL.java +++ b/openide.filesystems/src/org/openide/filesystems/FileURL.java @@ -54,6 +54,7 @@ import java.net.URLStreamHandler; import java.net.UnknownServiceException; import java.security.Permission; +import org.openide.util.URLStreamHandlerRegistration; /** Special URL connection directly accessing an internal file object. * @@ -65,20 +66,15 @@ /** Default implemenatation of handler for this type of URL. */ - static URLStreamHandler HANDLER = new URLStreamHandler() { - /** - * @param u - URL to open connection to. - * @return new URLConnection. - */ - public URLConnection openConnection(URL u) - throws IOException { - return new FileURL(u); - } - - protected synchronized InetAddress getHostAddress(URL u) { - return null; - } - }; + @URLStreamHandlerRegistration(protocol=PROTOCOL) + public static class Handler extends URLStreamHandler { + public URLConnection openConnection(URL u) throws IOException { + return new FileURL(u); + } + protected @Override synchronized InetAddress getHostAddress(URL u) { + return null; + } + } /** 1 URLConnection == 1 InputSteam*/ InputStream iStream = null; diff --git a/openide.filesystems/src/org/openide/filesystems/FileUtil.java b/openide.filesystems/src/org/openide/filesystems/FileUtil.java --- a/openide.filesystems/src/org/openide/filesystems/FileUtil.java +++ b/openide.filesystems/src/org/openide/filesystems/FileUtil.java @@ -1492,16 +1492,11 @@ } /** - * Construct a stream handler that handles the nbfs URL protocol - * used for accessing file objects directly. - * This method is not intended for module use; only the core - * should need to call it. - * Modules probably need only use {@link URLMapper} to create and decode such - * URLs. - * @since 3.17 + * @deprecated No longer used. */ + @Deprecated public static URLStreamHandler nbfsURLStreamHandler() { - return FileURL.HANDLER; + return new FileURL.Handler(); } /** Recursively checks whether the file is underneath the folder. It checks whether diff --git a/openide.filesystems/src/org/openide/filesystems/NbfsUtil.java b/openide.filesystems/src/org/openide/filesystems/NbfsUtil.java --- a/openide.filesystems/src/org/openide/filesystems/NbfsUtil.java +++ b/openide.filesystems/src/org/openide/filesystems/NbfsUtil.java @@ -80,7 +80,7 @@ new PrivilegedExceptionAction() { public URL run() throws Exception { // #30397: the fsPart name cannot be null - return new URL(FileURL.PROTOCOL, host, -1, file, FileURL.HANDLER); // NOI18N + return new URL(FileURL.PROTOCOL, host, -1, file, new FileURL.Handler()); } } ); diff --git a/openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java b/openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java --- a/openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java +++ b/openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java @@ -48,6 +48,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.annotation.Annotation; +import java.net.URLStreamHandler; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -75,13 +76,20 @@ import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.StandardLocation; +import org.openide.util.URLStreamHandlerRegistration; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; @SupportedSourceVersion(SourceVersion.RELEASE_6) -@SupportedAnnotationTypes({"org.openide.util.lookup.ServiceProvider", "org.openide.util.lookup.ServiceProviders"}) +@SupportedAnnotationTypes({ + "org.openide.util.lookup.ServiceProvider", + "org.openide.util.lookup.ServiceProviders", + "org.openide.util.URLStreamHandlerRegistration" +}) public class ServiceProviderProcessor extends AbstractProcessor { + public static final String URL_STREAM_HANDLER_REGISTRATION_PREFIX = "URLStreamHandler/"; // NOI18N + /** public for ServiceLoader */ public ServiceProviderProcessor() {} @@ -115,19 +123,33 @@ register(clazz, sp); } } + for (Element el : roundEnv.getElementsAnnotatedWith(URLStreamHandlerRegistration.class)) { + TypeElement clazz = (TypeElement) el; + if (!verifyServiceProviderSignature(clazz)) { + continue; + } + URLStreamHandlerRegistration r = clazz.getAnnotation(URLStreamHandlerRegistration.class); + TypeMirror type = processingEnv.getTypeUtils().getDeclaredType( + processingEnv.getElementUtils().getTypeElement(URLStreamHandler.class.getName())); + for (String protocol : r.protocol()) { + register(clazz, type, URL_STREAM_HANDLER_REGISTRATION_PREFIX + protocol, r.position(), new String[0]); + } + } return true; } } private void register(TypeElement clazz, ServiceProvider svc) { - TypeMirror type; try { svc.service(); assert false; return; } catch (MirroredTypeException e) { - type = e.getTypeMirror(); + register(clazz, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes()); } + } + + private void register(TypeElement clazz, TypeMirror type, String path, int position, String[] supersedes) { 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)) { @@ -136,8 +158,9 @@ clazz, ann, findAnnotationValue(ann, "service")); return; } - processingEnv.getMessager().printMessage(Kind.NOTE, impl + " to be registered as a " + xface); - String rsrc = (svc.path().length() > 0 ? "META-INF/namedservices/" + svc.path() + "/" : "META-INF/services/") + xface; + 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; { List origEls = originatingElements.get(rsrc); if (origEls == null) { @@ -188,10 +211,10 @@ } } lines.add(impl); - if (svc.position() != Integer.MAX_VALUE) { - lines.add("#position=" + svc.position()); + if (position != Integer.MAX_VALUE) { + lines.add("#position=" + position); } - for (String exclude : svc.supersedes()) { + for (String exclude : supersedes) { lines.add("#-" + exclude); } } diff --git a/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java b/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java new file mode 100644 --- /dev/null +++ b/openide.util/src/org/openide/util/URLStreamHandlerRegistration.java @@ -0,0 +1,114 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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.openide.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.netbeans.modules.openide.util.ServiceProviderProcessor; +import org.openide.util.lookup.Lookups; + +/** + * Replacement for {@link URLStreamHandlerFactory} within the NetBeans platform. + * (The JVM only permits one factory, whereas various independent modules may wish to register handlers.) + * May be placed on a {@link URLStreamHandler} implementation to register it. + * @since XXX + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface URLStreamHandlerRegistration { + + /** + * URL protocol(s) which are handled. + * {@link URLStreamHandler#openConnection} will be called with a matching {@link URL#getProtocol}. + */ + String[] protocol(); + + /** + * An optional position in which to register this handler relative to others. + * The lowest-numbered handler is used in favor of any others, including unnumbered handlers. + */ + int position() default Integer.MAX_VALUE; + + // cannot be a constant: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6857918 + /** + * Factory which uses these registrations. + * This factory is active whenever the module system is loaded. + * You may also wish to call {@link URL#setURLStreamHandlerFactory} + * from a unit test or otherwise without the module system active. + */ + class ProxyURLStreamHandlerFactory implements URLStreamHandlerFactory { + + /** prevents GC only */ + private final Map> results = new HashMap>(); + private final Map handlers = new HashMap(); + + /** Create a new proxy factory. */ + public ProxyURLStreamHandlerFactory() {} + + public synchronized URLStreamHandler createURLStreamHandler(final String protocol) { + if (!results.containsKey(protocol)) { + final Lookup.Result result = Lookups.forPath( + ServiceProviderProcessor.URL_STREAM_HANDLER_REGISTRATION_PREFIX + protocol).lookupResult(URLStreamHandler.class); + LookupListener listener = new LookupListener() { + public void resultChanged(LookupEvent ev) { + synchronized (ProxyURLStreamHandlerFactory.this) { + Collection instances = result.allInstances(); + handlers.put(protocol, instances.isEmpty() ? null : instances.iterator().next()); + } + } + }; + result.addLookupListener(listener); + listener.resultChanged(null); + results.put(protocol, result); + } + return handlers.get(protocol); + } + + } + +} diff --git a/openide.util/test/unit/src/org/openide/util/URLStreamHandlerRegistrationTest.java b/openide.util/test/unit/src/org/openide/util/URLStreamHandlerRegistrationTest.java new file mode 100644 --- /dev/null +++ b/openide.util/test/unit/src/org/openide/util/URLStreamHandlerRegistrationTest.java @@ -0,0 +1,69 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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.openide.util; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import org.netbeans.junit.NbTestCase; + +public class URLStreamHandlerRegistrationTest extends NbTestCase { + + public URLStreamHandlerRegistrationTest(String n) { + super(n); + } + + public void testURLStreamHandlerRegistration() throws Exception { + URLStreamHandlerFactory factory = new URLStreamHandlerRegistration.ProxyURLStreamHandlerFactory(); + assertEquals(MyHandler.class, factory.createURLStreamHandler("stuff").getClass()); + assertEquals(MyHandler.class, factory.createURLStreamHandler("stuff").getClass()); + assertNull(factory.createURLStreamHandler("whatever")); + } + + @URLStreamHandlerRegistration(protocol="stuff") + public static class MyHandler extends URLStreamHandler { + protected URLConnection openConnection(URL u) throws IOException { + throw new IOException("unsupported"); + } + } + +}