Actually use ServiceLoader in places where we had a hard-coded equivalent.
I've also removed a file that was causing us to use this code unnecessarily
at run-time to explicitly specify the built-in default PreferencesFactory.
I haven't touched Charset, but should come back and fix that too at some
point.
Change-Id: I3a2145041d048078bdb55ae7b8fa4ec9d8726922
diff --git a/libcore/luni/src/main/java/java/util/ServiceLoader.java b/libcore/luni/src/main/java/java/util/ServiceLoader.java
index 2f28dff..335a1db 100644
--- a/libcore/luni/src/main/java/java/util/ServiceLoader.java
+++ b/libcore/luni/src/main/java/java/util/ServiceLoader.java
@@ -62,6 +62,8 @@
*
* <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 @@
}
/**
- * 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 @@
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 @@
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 @@
}
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/libcore/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java b/libcore/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
index 7692f2f..ab898af 100644
--- a/libcore/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
+++ b/libcore/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.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 @@
* 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 @@
* @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/libcore/prefs/src/main/java/java/util/prefs/Preferences.java b/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
index b128858..e79d9eb 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
+++ b/libcore/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.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 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;
+ private static final PreferencesFactory factory = findPreferencesFactory();
- // 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();
+ private static PreferencesFactory findPreferencesFactory() {
+ // Try the system property first...
+ PreferencesFactory result = ServiceLoader.loadFromSystemProperty(PreferencesFactory.class);
+ if (result != null) {
+ return result;
}
- 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$
- }
+ // Then use ServiceLoader for META-INF/services/...
+ for (PreferencesFactory impl : ServiceLoader.load(PreferencesFactory.class, null)) {
+ return impl;
}
-
- if (factoryClassName == null) {
- factoryClassName = "java.util.prefs.FilePreferencesFactoryImpl";
- }
-
- 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$
- }
- // END android-added
+ // Finally return a default...
+ return new FilePreferencesFactoryImpl();
}
/**
diff --git a/libcore/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory b/libcore/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory
deleted file mode 100644
index ebb514c..0000000
--- a/libcore/prefs/src/main/resources/META-INF/services/java.util.prefs.PreferencesFactory
+++ /dev/null
@@ -1 +0,0 @@
-java.util.prefs.FilePreferencesFactoryImpl