/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.nio.channels.spi;
import java.nio.channels.*;
import java.io.
IOException;
import java.util.
Iterator;
import java.util.
ServiceLoader;
import java.util.
ServiceConfigurationError;
import java.util.concurrent.*;
import java.security.
AccessController;
import java.security.
PrivilegedAction;
/**
* Service-provider class for asynchronous channels.
*
* <p> An asynchronous channel provider is a concrete subclass of this class that
* has a zero-argument constructor and implements the abstract methods specified
* below. A given invocation of the Java virtual machine maintains a single
* system-wide default provider instance, which is returned by the {@link
* #provider() provider} method. The first invocation of that method will locate
* the default provider as specified below.
*
* <p> All of the methods in this class are safe for use by multiple concurrent
* threads. </p>
*
* @since 1.7
*/
public abstract class
AsynchronousChannelProvider {
private static
Void checkPermission() {
SecurityManager sm =
System.
getSecurityManager();
if (
sm != null)
sm.
checkPermission(new
RuntimePermission("asynchronousChannelProvider"));
return null;
}
private
AsynchronousChannelProvider(
Void ignore) { }
/**
* Initializes a new instance of this class.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link RuntimePermission}<tt>("asynchronousChannelProvider")</tt>
*/
protected
AsynchronousChannelProvider() {
this(
checkPermission());
}
// lazy initialization of default provider
private static class
ProviderHolder {
static final
AsynchronousChannelProvider provider =
load();
private static
AsynchronousChannelProvider load() {
return
AccessController
.
doPrivileged(new
PrivilegedAction<
AsynchronousChannelProvider>() {
public
AsynchronousChannelProvider run() {
AsynchronousChannelProvider p;
p =
loadProviderFromProperty();
if (
p != null)
return
p;
p =
loadProviderAsService();
if (
p != null)
return
p;
return sun.nio.ch.
DefaultAsynchronousChannelProvider.
create();
}});
}
private static
AsynchronousChannelProvider loadProviderFromProperty() {
String cn =
System.
getProperty("java.nio.channels.spi.AsynchronousChannelProvider");
if (
cn == null)
return null;
try {
Class<?>
c =
Class.
forName(
cn, true,
ClassLoader.
getSystemClassLoader());
return (
AsynchronousChannelProvider)
c.
newInstance();
} catch (
ClassNotFoundException x) {
throw new
ServiceConfigurationError(null,
x);
} catch (
IllegalAccessException x) {
throw new
ServiceConfigurationError(null,
x);
} catch (
InstantiationException x) {
throw new
ServiceConfigurationError(null,
x);
} catch (
SecurityException x) {
throw new
ServiceConfigurationError(null,
x);
}
}
private static
AsynchronousChannelProvider loadProviderAsService() {
ServiceLoader<
AsynchronousChannelProvider>
sl =
ServiceLoader.
load(
AsynchronousChannelProvider.class,
ClassLoader.
getSystemClassLoader());
Iterator<
AsynchronousChannelProvider>
i =
sl.
iterator();
for (;;) {
try {
return (
i.
hasNext()) ?
i.
next() : null;
} catch (
ServiceConfigurationError sce) {
if (
sce.
getCause() instanceof
SecurityException) {
// Ignore the security exception, try the next provider
continue;
}
throw
sce;
}
}
}
}
/**
* Returns the system-wide default asynchronous channel provider for this
* invocation of the Java virtual machine.
*
* <p> The first invocation of this method locates the default provider
* object as follows: </p>
*
* <ol>
*
* <li><p> If the system property
* <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> is defined
* then it is taken to be the fully-qualified name of a concrete provider class.
* The class is loaded and instantiated; if this process fails then an
* unspecified error is thrown. </p></li>
*
* <li><p> If a provider class has been installed in a jar file that is
* visible to the system class loader, and that jar file contains a
* provider-configuration file named
* <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> in the resource
* directory <tt>META-INF/services</tt>, then the first class name
* specified in that file is taken. The class is loaded and
* instantiated; if this process fails then an unspecified error is
* thrown. </p></li>
*
* <li><p> Finally, if no provider has been specified by any of the above
* means then the system-default provider class is instantiated and the
* result is returned. </p></li>
*
* </ol>
*
* <p> Subsequent invocations of this method return the provider that was
* returned by the first invocation. </p>
*
* @return The system-wide default AsynchronousChannel provider
*/
public static
AsynchronousChannelProvider provider() {
return
ProviderHolder.
provider;
}
/**
* Constructs a new asynchronous channel group with a fixed thread pool.
*
* @param nThreads
* The number of threads in the pool
* @param threadFactory
* The factory to use when creating new threads
*
* @return A new asynchronous channel group
*
* @throws IllegalArgumentException
* If {@code nThreads <= 0}
* @throws IOException
* If an I/O error occurs
*
* @see AsynchronousChannelGroup#withFixedThreadPool
*/
public abstract
AsynchronousChannelGroup
openAsynchronousChannelGroup(int
nThreads,
ThreadFactory threadFactory) throws
IOException;
/**
* Constructs a new asynchronous channel group with the given thread pool.
*
* @param executor
* The thread pool
* @param initialSize
* A value {@code >=0} or a negative value for implementation
* specific default
*
* @return A new asynchronous channel group
*
* @throws IOException
* If an I/O error occurs
*
* @see AsynchronousChannelGroup#withCachedThreadPool
*/
public abstract
AsynchronousChannelGroup
openAsynchronousChannelGroup(
ExecutorService executor, int
initialSize) throws
IOException;
/**
* Opens an asynchronous server-socket channel.
*
* @param group
* The group to which the channel is bound, or {@code null} to
* bind to the default group
*
* @return The new channel
*
* @throws IllegalChannelGroupException
* If the provider that created the group differs from this provider
* @throws ShutdownChannelGroupException
* The group is shutdown
* @throws IOException
* If an I/O error occurs
*/
public abstract
AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
(
AsynchronousChannelGroup group) throws
IOException;
/**
* Opens an asynchronous socket channel.
*
* @param group
* The group to which the channel is bound, or {@code null} to
* bind to the default group
*
* @return The new channel
*
* @throws IllegalChannelGroupException
* If the provider that created the group differs from this provider
* @throws ShutdownChannelGroupException
* The group is shutdown
* @throws IOException
* If an I/O error occurs
*/
public abstract
AsynchronousSocketChannel openAsynchronousSocketChannel
(
AsynchronousChannelGroup group) throws
IOException;
}