diff options
4 files changed, 63 insertions, 235 deletions
diff --git a/luni/src/main/java/java/util/ServiceLoader.java b/luni/src/main/java/java/util/ServiceLoader.java index 2f28dff..335a1db 100644 --- a/luni/src/main/java/java/util/ServiceLoader.java +++ b/luni/src/main/java/java/util/ServiceLoader.java @@ -62,6 +62,8 @@ import java.net.URL; * * <p>Note that each iteration creates new instances of the various service implementations, so * any heavily-used code will likely want to cache the known implementations itself and reuse them. + * Note also that the candidate classes are instantiated lazily as you call {@code next} on the + * iterator: construction of the iterator itself does not instantiate any of the providers. * * @param <S> the service class or interface * @since 1.6 @@ -106,13 +108,17 @@ public final class ServiceLoader<S> implements Iterable<S> { } /** - * Constructs a service loader. + * Constructs a service loader. If {@code classLoader} is null, the system class loader + * is used. * * @param service the service class or interface - * @param loader the class loader + * @param classLoader the class loader * @return a new ServiceLoader */ public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader classLoader) { + if (classLoader == null) { + classLoader = ClassLoader.getSystemClassLoader(); + } return new ServiceLoader<S>(service, classLoader); } @@ -120,16 +126,12 @@ public final class ServiceLoader<S> implements Iterable<S> { services.clear(); try { String name = "META-INF/services/" + service.getName(); - services.addAll(Collections.list(classLoader().getResources(name))); + services.addAll(Collections.list(classLoader.getResources(name))); } catch (IOException e) { return; } } - private ClassLoader classLoader() { - return (classLoader != null) ? classLoader : ClassLoader.getSystemClassLoader(); - } - /** * Constructs a service loader, using the current thread's context class loader. * @@ -156,6 +158,29 @@ public final class ServiceLoader<S> implements Iterable<S> { return ServiceLoader.load(service, cl); } + /** + * Internal API to support built-in SPIs that check a system property first. + * Returns an instance specified by a property with the class' binary name, or null if + * no such property is set. + * @hide + */ + public static <S> S loadFromSystemProperty(final Class<S> service) { + return AccessController.doPrivileged(new PrivilegedAction<S>() { + public S run() { + try { + final String className = System.getProperty(service.getName()); + if (className != null) { + Class<?> c = ClassLoader.getSystemClassLoader().loadClass(className); + return (S) c.newInstance(); + } + return null; + } catch (Exception e) { + throw new Error(e); + } + } + }); + } + @Override public String toString() { return "ServiceLoader for " + service.getName(); @@ -190,11 +215,7 @@ public final class ServiceLoader<S> implements Iterable<S> { } String className = queue.remove(); try { - if (classLoader == null) { - return service.cast(Class.forName(className).newInstance()); - } else { - return service.cast(classLoader.loadClass(className).newInstance()); - } + return service.cast(classLoader.loadClass(className).newInstance()); } catch (Exception e) { throw new ServiceConfigurationError("Couldn't instantiate class " + className, e); } diff --git a/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java index 7692f2f..ab898af 100644 --- a/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java +++ b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java @@ -17,10 +17,7 @@ package java.nio.channels.spi; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; import java.nio.channels.Channel; import java.nio.channels.DatagramChannel; import java.nio.channels.Pipe; @@ -28,8 +25,7 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Enumeration; - +import java.util.ServiceLoader; import org.apache.harmony.luni.platform.Platform; import org.apache.harmony.nio.internal.SelectorProviderImpl; @@ -38,19 +34,12 @@ import org.apache.harmony.nio.internal.SelectorProviderImpl; * providing instances of {@link DatagramChannel}, {@link Pipe}, * {@link java.nio.channels.Selector} , {@link ServerSocketChannel}, and * {@link SocketChannel}. All the methods of this class are thread-safe. - * <p> - * A provider instance can be retrieved through a system property or the - * configuration file in a jar file; if no provide is available that way then + * + * <p>A provider instance can be retrieved through a system property or the + * configuration file in a jar file; if no provider is available that way then * the system default provider is returned. */ -public abstract class SelectorProvider extends Object { - - private static final String SYMBOL_COMMENT = "#"; //$NON-NLS-1$ - - private static final String PROVIDER_IN_SYSTEM_PROPERTY = "java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$ - - private static final String PROVIDER_IN_JAR_RESOURCE = "META-INF/services/java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$ - +public abstract class SelectorProvider { private static SelectorProvider provider = null; private static Channel inheritedChannel; @@ -87,103 +76,29 @@ public abstract class SelectorProvider extends Object { * @return the provider. */ synchronized public static SelectorProvider provider() { - if (null == provider) { - provider = loadProviderByProperty(); - if (null == provider) { + if (provider == null) { + provider = ServiceLoader.loadFromSystemProperty(SelectorProvider.class); + if (provider == null) { provider = loadProviderByJar(); } - if (null == provider) { - provider = AccessController - .doPrivileged(new PrivilegedAction<SelectorProvider>() { - public SelectorProvider run() { - return new SelectorProviderImpl(); - } - }); + if (provider == null) { + provider = AccessController.doPrivileged(new PrivilegedAction<SelectorProvider>() { + public SelectorProvider run() { + return new SelectorProviderImpl(); + } + }); } } return provider; } - /* - * load the provider in the jar file of class path. - */ - static SelectorProvider loadProviderByJar() { - Enumeration<URL> enumeration = null; - - ClassLoader classLoader = AccessController - .doPrivileged(new PrivilegedAction<ClassLoader>() { - public ClassLoader run() { - return ClassLoader.getSystemClassLoader(); - } - }); - try { - enumeration = classLoader.getResources(PROVIDER_IN_JAR_RESOURCE); - } catch (IOException e) { - throw new Error(e); - } - if (null == enumeration) { - return null; - } - // for every jar, read until we find the provider name. - while (enumeration.hasMoreElements()) { - BufferedReader br = null; - String className = null; - try { - br = new BufferedReader( - new InputStreamReader(enumeration.nextElement().openStream())); - } catch (Exception e) { - continue; - } - try { - // only the first class is loaded ,as spec says, not the same as - // we do before. - while ((className = br.readLine()) != null) { - className = className.trim(); - int siteComment = className.indexOf(SYMBOL_COMMENT); - className = (-1 == siteComment) ? className : className - .substring(0, siteComment); - if (0 < className.length()) { - return (SelectorProvider) classLoader.loadClass( - className).newInstance(); - } - } - } catch (Exception e) { - throw new Error(e); - } finally { - try { - br.close(); - } catch (IOException ioe) { - // Ignore - } - } + private static SelectorProvider loadProviderByJar() { + for (SelectorProvider provider : ServiceLoader.load(SelectorProvider.class, null)) { + return provider; } return null; } - /* - * Load by system property. - */ - static SelectorProvider loadProviderByProperty() { - return AccessController - .doPrivileged(new PrivilegedAction<SelectorProvider>() { - public SelectorProvider run() { - try { - final String className = System - .getProperty(PROVIDER_IN_SYSTEM_PROPERTY); - if (null != className) { - Class<?> spClass = ClassLoader - .getSystemClassLoader().loadClass( - className); - return (SelectorProvider) spClass.newInstance(); - } - return null; - } catch (Exception e) { - throw new Error(e); - } - } - }); - } - /** * Creates a new open {@code DatagramChannel}. * diff --git a/prefs/src/main/java/java/util/prefs/Preferences.java b/prefs/src/main/java/java/util/prefs/Preferences.java index b128858..e79d9eb 100644 --- a/prefs/src/main/java/java/util/prefs/Preferences.java +++ b/prefs/src/main/java/java/util/prefs/Preferences.java @@ -16,14 +16,6 @@ package java.util.prefs; -// BEGIN android-added -import java.io.BufferedReader; -import java.io.File; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.Enumeration; -// END android-added - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -31,7 +23,7 @@ import java.net.MalformedURLException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Locale; - +import java.util.ServiceLoader; import org.apache.harmony.prefs.internal.nls.Messages; /** @@ -110,123 +102,24 @@ public abstract class Preferences { */ public static final int MAX_VALUE_LENGTH = 8192; - // BEGIN android-added - /** - * The name of the configuration file where preferences factory class names - * can be specified. - */ - private static final String FACTORY_CONFIGURATION_FILE_NAME = "META-INF/services/java.util.prefs.PreferencesFactory"; //$NON-NLS-1$ - - /** - * The encoding of configuration files - */ - private static final String CONFIGURATION_FILE_ENCODING = "UTF-8"; //$NON-NLS-1$ - - /** - * The comment string used in configuration files - */ - private static final String CONFIGURATION_FILE_COMMENT = "#"; //$NON-NLS-1$ - - // END android-added - //permission - private static final RuntimePermission PREFS_PERM = new RuntimePermission("preferences"); //$NON-NLS-1$ + private static final RuntimePermission PREFS_PERM = new RuntimePermission("preferences"); //factory used to get user/system prefs root - private static final PreferencesFactory factory; - - // BEGIN android-removed - // // default provider factory name for Windows - // private static final String DEFAULT_FACTORY_NAME_WIN = "java.util.prefs.RegistryPreferencesFactoryImpl"; //$NON-NLS-1$ - // - // // default provider factory name for Unix - // private static final String DEFAULT_FACTORY_NAME_UNIX = "java.util.prefs.FilePreferencesFactoryImpl"; //$NON-NLS-1$ - // END android-removed - - static { - String factoryClassName = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty("java.util.prefs.PreferencesFactory"); //$NON-NLS-1$ - } - }); - // BEGIN android-removed - // // set default provider - // if (factoryClassName == null) { - // String osName = AccessController.doPrivileged(new PrivilegedAction<String>() { - // public String run() { - // return System.getProperty("os.name"); //$NON-NLS-1$ - // } - // }); - // - // // only comparing ASCII, so assume english locale - // osName = (osName == null ? null : osName.toLowerCase(Locale.ENGLISH)); - // - // if (osName != null && osName.startsWith("windows")) { - // factoryClassName = DEFAULT_FACTORY_NAME_WIN; - // } else { - // factoryClassName = DEFAULT_FACTORY_NAME_UNIX; - // } - // } - // try { - // ClassLoader loader = Thread.currentThread().getContextClassLoader(); - // if(loader == null){ - // loader = ClassLoader.getSystemClassLoader(); - // } - // Class<?> factoryClass = loader.loadClass(factoryClassName); - // factory = (PreferencesFactory) factoryClass.newInstance(); - // } catch (Exception e) { - // // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by {1} - // throw new InternalError(Messages.getString("prefs.10", factoryClassName, e)); //$NON-NLS-1$ - // } - // BEGIN android-added - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - if (factoryClassName == null) { - Enumeration<URL> en = null; - try { - en = loader.getResources(FACTORY_CONFIGURATION_FILE_NAME); - BufferedReader reader = null; - int commentIndex = 0; - while (en.hasMoreElements()) { - try { - InputStream is = en.nextElement().openStream(); - // Read each line for charset provider class names - reader = new BufferedReader(new InputStreamReader(is, - CONFIGURATION_FILE_ENCODING)); - factoryClassName = reader.readLine(); - commentIndex = factoryClassName.indexOf(CONFIGURATION_FILE_COMMENT); - if (commentIndex > 0) { - factoryClassName = factoryClassName.substring(0, commentIndex).trim(); - } - if (factoryClassName.length() > 0) { - break; - } - } catch (IOException ex) { - // ignore if a resource couldn't be read - } - } - } catch (Exception e) { - // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by - // {1} - throw new InternalError(Messages.getString("prefs.10", - FACTORY_CONFIGURATION_FILE_NAME, e)); //$NON-NLS-1$ - } - } + private static final PreferencesFactory factory = findPreferencesFactory(); - if (factoryClassName == null) { - factoryClassName = "java.util.prefs.FilePreferencesFactoryImpl"; + private static PreferencesFactory findPreferencesFactory() { + // Try the system property first... + PreferencesFactory result = ServiceLoader.loadFromSystemProperty(PreferencesFactory.class); + if (result != null) { + return result; } - - try { - Class<?> c = loader.loadClass(factoryClassName); - factory = (PreferencesFactory)c.newInstance(); - } catch (Exception e) { - // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by {1} - throw new InternalError(Messages.getString("prefs.10", factoryClassName, e)); //$NON-NLS-1$ + // Then use ServiceLoader for META-INF/services/... + for (PreferencesFactory impl : ServiceLoader.load(PreferencesFactory.class, null)) { + return impl; } - // END android-added + // Finally return a default... + return new FilePreferencesFactoryImpl(); } /** diff --git a/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory b/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory deleted file mode 100644 index ebb514c..0000000 --- a/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory +++ /dev/null @@ -1 +0,0 @@ -java.util.prefs.FilePreferencesFactoryImpl |