summaryrefslogtreecommitdiff
path: root/gnu/classpath
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2007-01-01 20:27:36 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2007-01-01 20:27:36 +0000
commitdcba527c112e564771f554731f71c3d7c1c11533 (patch)
tree7eea75af633d8bb76f2ac4c3c8d0f0ecd80fd6fc /gnu/classpath
parenteeecdc6f3fd6990889b204abe0d60f6061ca8bfb (diff)
downloadclasspath-dcba527c112e564771f554731f71c3d7c1c11533.tar.gz
2007-01-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
* ChangeLog-2006: New file. * gnu/classpath/ServiceFactory.java: Add option of throwing a ServiceConfigurationError. (lookupProviders(Class,ClassLoader,boolean)): Implemented. * java/util/ServiceConfigurationError.java: New file. * java/util/ServiceLoader.java: Likewise.
Diffstat (limited to 'gnu/classpath')
-rw-r--r--gnu/classpath/ServiceFactory.java83
1 files changed, 79 insertions, 4 deletions
diff --git a/gnu/classpath/ServiceFactory.java b/gnu/classpath/ServiceFactory.java
index 122a79c96..daf996c23 100644
--- a/gnu/classpath/ServiceFactory.java
+++ b/gnu/classpath/ServiceFactory.java
@@ -49,6 +49,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.ServiceConfigurationError;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
@@ -176,7 +177,6 @@ public final class ServiceFactory
*/
private static final Logger LOGGER = Logger.getLogger("gnu.classpath");
-
/**
* Declared private in order to prevent constructing instances of
* this utility class.
@@ -225,6 +225,51 @@ public final class ServiceFactory
public static Iterator lookupProviders(Class spi,
ClassLoader loader)
{
+ return lookupProviders(spi, loader, false);
+ }
+
+ /**
+ * Finds service providers that are implementing the specified
+ * Service Provider Interface.
+ *
+ * <p><b>On-demand loading:</b> Loading and initializing service
+ * providers is delayed as much as possible. The rationale is that
+ * typical clients will iterate through the set of installed service
+ * providers until one is found that matches some criteria (like
+ * supported formats, or quality of service). In such scenarios, it
+ * might make sense to install only the frequently needed service
+ * providers on the local machine. More exotic providers can be put
+ * onto a server; the server will only be contacted when no suitable
+ * service could be found locally.
+ *
+ * <p><b>Security considerations:</b> Any loaded service providers
+ * are loaded through the specified ClassLoader, or the system
+ * ClassLoader if <code>classLoader</code> is
+ * <code>null</code>. When <code>lookupProviders</code> is called,
+ * the current {@link AccessControlContext} gets recorded. This
+ * captured security context will determine the permissions when
+ * services get loaded via the <code>next()</code> method of the
+ * returned <code>Iterator</code>.
+ *
+ * @param spi the service provider interface which must be
+ * implemented by any loaded service providers.
+ *
+ * @param loader the class loader that will be used to load the
+ * service providers, or <code>null</code> for the system class
+ * loader. For using the context class loader, see {@link
+ * #lookupProviders(Class)}.
+ * @param error true if a {@link ServiceConfigurationError}
+ * should be thrown when an error occurs, rather
+ * than it merely being logged.
+ * @return an iterator over instances of <code>spi</code>.
+ *
+ * @throws IllegalArgumentException if <code>spi</code> is
+ * <code>null</code>.
+ */
+ public static Iterator lookupProviders(Class spi,
+ ClassLoader loader,
+ boolean error)
+ {
String resourceName;
Enumeration urls;
@@ -246,10 +291,14 @@ public final class ServiceFactory
* does not return anything (no providers installed).
*/
log(Level.WARNING, "cannot access {0}", resourceName, ioex);
- return Collections.EMPTY_LIST.iterator();
+ if (error)
+ throw new ServiceConfigurationError("Failed to access + " +
+ resourceName, ioex);
+ else
+ return Collections.EMPTY_LIST.iterator();
}
- return new ServiceIterator(spi, urls, loader,
+ return new ServiceIterator(spi, urls, loader, error,
AccessController.getContext());
}
@@ -342,6 +391,11 @@ public final class ServiceFactory
*/
private Object nextProvider;
+ /**
+ * True if a {@link ServiceConfigurationError} should be thrown
+ * when an error occurs, instead of it merely being logged.
+ */
+ private boolean error;
/**
* Constructs an Iterator that loads and initializes services on
@@ -359,16 +413,21 @@ public final class ServiceFactory
* @param loader the ClassLoader that gets used for loading
* service providers.
*
+ * @param error true if a {@link ServiceConfigurationError}
+ * should be thrown when an error occurs, rather
+ * than it merely being logged.
+ *
* @param securityContext the security context to use when loading
* and initializing service providers.
*/
ServiceIterator(Class spi, Enumeration urls, ClassLoader loader,
- AccessControlContext securityContext)
+ boolean error, AccessControlContext securityContext)
{
this.spi = spi;
this.urls = urls;
this.loader = loader;
this.securityContext = securityContext;
+ this.error = error;
this.nextProvider = loadNextServiceProvider();
}
@@ -426,6 +485,9 @@ public final class ServiceFactory
log(Level.WARNING, "IOException upon reading {0}", currentURL,
readProblem);
line = null;
+ if (error)
+ throw new ServiceConfigurationError("Error reading " +
+ currentURL, readProblem);
}
/* When we are at the end of one list of services,
@@ -477,6 +539,13 @@ public final class ServiceFactory
log(Level.WARNING, msg,
new Object[] { line, spi.getName(), currentURL },
ex);
+ if (error)
+ throw new ServiceConfigurationError("Cannot load service "+
+ "provider class " +
+ line + " specified by "+
+ "\"META-INF/services/"+
+ spi.getName() + "\" in "+
+ currentURL, ex);
continue;
}
}
@@ -497,6 +566,9 @@ public final class ServiceFactory
catch (Exception ex)
{
log(Level.WARNING, "cannot close {0}", currentURL, ex);
+ if (error)
+ throw new ServiceConfigurationError("Cannot close " +
+ currentURL, ex);
}
reader = null;
currentURL = null;
@@ -515,6 +587,9 @@ public final class ServiceFactory
catch (Exception ex)
{
log(Level.WARNING, "cannot open {0}", currentURL, ex);
+ if (error)
+ throw new ServiceConfigurationError("Cannot open " +
+ currentURL, ex);
}
}
while (reader == null);