package org.skife.url; import net.sf.cglib.core.NamingPolicy; import net.sf.cglib.core.Predicate; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.NoOp; import java.net.URL; import java.net.URLStreamHandler; import java.util.Set; import java.util.concurrent.ConcurrentSkipListSet; /** * */ public class UrlSchemeRegistry { public static String KEY = "java.protocol.handler.pkgs"; private final static Set<String> registeredPackages = new ConcurrentSkipListSet<String>(); private final static Set<String> registeredSchemes = new ConcurrentSkipListSet<String>(); static void registerPackage(String pkg) { if (!registeredPackages.add(pkg)) { // short circuit package re-registration return; } synchronized (System.getProperties()) { if (System.getProperties().contains(KEY)) { String current = System.getProperty(KEY); if (!current.contains(pkg)) { System.setProperty(KEY, current + "|" + pkg); } } else { System.setProperty(KEY, pkg); } } } /** * Used to register a handler for a scheme. The actual handler used will in fact be a runtime generated * subclass of handlerType in order to abide by the naming rules for URL scheme handlers. * * @param scheme scheme name to associate handlerType with * @param handlerType non-final class with a no-arg public constructor which will create handlers * for scheme */ public static void register(final String scheme, Class<? extends URLStreamHandler> handlerType) { if (!registeredSchemes.add(scheme)) { throw new IllegalStateException("a scheme has already been registered for " + scheme); } registerPackage("org.skife.url.generated"); Enhancer e = new Enhancer(); e.setNamingPolicy(new NamingPolicy() { @Override public String getClassName(String prefix, String source, Object key, Predicate names) { return "org.skife.url.generated." + scheme + ".Handler"; } }); e.setSuperclass(handlerType); e.setCallbackType(NoOp.class); e.createClass(); } }