1/*
2 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.nio.channels.spi;
27
28import java.nio.channels.*;
29import java.io.IOException;
30import java.util.Iterator;
31import java.util.ServiceLoader;
32import java.util.ServiceConfigurationError;
33import java.util.concurrent.*;
34import java.security.AccessController;
35import java.security.PrivilegedAction;
36
37/**
38 * Service-provider class for asynchronous channels.
39 *
40 * <p> An asynchronous channel provider is a concrete subclass of this class that
41 * has a zero-argument constructor and implements the abstract methods specified
42 * below.  A given invocation of the Java virtual machine maintains a single
43 * system-wide default provider instance, which is returned by the {@link
44 * #provider() provider} method.  The first invocation of that method will locate
45 * the default provider as specified below.
46 *
47 * <p> All of the methods in this class are safe for use by multiple concurrent
48 * threads.  </p>
49 *
50 * @since 1.7
51 */
52
53public abstract class AsynchronousChannelProvider {
54    private static Void checkPermission() {
55        SecurityManager sm = System.getSecurityManager();
56        if (sm != null)
57            sm.checkPermission(new RuntimePermission("asynchronousChannelProvider"));
58        return null;
59    }
60    private AsynchronousChannelProvider(Void ignore) { }
61
62    /**
63     * Initializes a new instance of this class.
64     *
65     * @throws  SecurityException
66     *          If a security manager has been installed and it denies
67     *          {@link RuntimePermission}{@code ("asynchronousChannelProvider")}
68     */
69    protected AsynchronousChannelProvider() {
70        this(checkPermission());
71    }
72
73    // lazy initialization of default provider
74    private static class ProviderHolder {
75        static final AsynchronousChannelProvider provider = load();
76
77        private static AsynchronousChannelProvider load() {
78            return AccessController
79                .doPrivileged(new PrivilegedAction<>() {
80                    public AsynchronousChannelProvider run() {
81                        AsynchronousChannelProvider p;
82                        p = loadProviderFromProperty();
83                        if (p != null)
84                            return p;
85                        p = loadProviderAsService();
86                        if (p != null)
87                            return p;
88                        return sun.nio.ch.DefaultAsynchronousChannelProvider.create();
89                    }});
90        }
91
92        private static AsynchronousChannelProvider loadProviderFromProperty() {
93            String cn = System.getProperty("java.nio.channels.spi.AsynchronousChannelProvider");
94            if (cn == null)
95                return null;
96            try {
97                @SuppressWarnings("deprecation")
98                Object tmp = Class.forName(cn, true,
99                                           ClassLoader.getSystemClassLoader()).newInstance();
100                return (AsynchronousChannelProvider)tmp;
101            } catch (ClassNotFoundException x) {
102                throw new ServiceConfigurationError(null, x);
103            } catch (IllegalAccessException x) {
104                throw new ServiceConfigurationError(null, x);
105            } catch (InstantiationException x) {
106                throw new ServiceConfigurationError(null, x);
107            } catch (SecurityException x) {
108                throw new ServiceConfigurationError(null, x);
109            }
110        }
111
112        private static AsynchronousChannelProvider loadProviderAsService() {
113            ServiceLoader<AsynchronousChannelProvider> sl =
114                ServiceLoader.load(AsynchronousChannelProvider.class,
115                                   ClassLoader.getSystemClassLoader());
116            Iterator<AsynchronousChannelProvider> i = sl.iterator();
117            for (;;) {
118                try {
119                    return (i.hasNext()) ? i.next() : null;
120                } catch (ServiceConfigurationError sce) {
121                    if (sce.getCause() instanceof SecurityException) {
122                        // Ignore the security exception, try the next provider
123                        continue;
124                    }
125                    throw sce;
126                }
127            }
128        }
129    }
130
131    /**
132     * Returns the system-wide default asynchronous channel provider for this
133     * invocation of the Java virtual machine.
134     *
135     * <p> The first invocation of this method locates the default provider
136     * object as follows: </p>
137     *
138     * <ol>
139     *
140     *   <li><p> If the system property
141     *   {@code java.nio.channels.spi.AsynchronousChannelProvider} is defined
142     *   then it is taken to be the fully-qualified name of a concrete provider class.
143     *   The class is loaded and instantiated; if this process fails then an
144     *   unspecified error is thrown.  </p></li>
145     *
146     *   <li><p> If a provider class has been installed in a jar file that is
147     *   visible to the system class loader, and that jar file contains a
148     *   provider-configuration file named
149     *   {@code java.nio.channels.spi.AsynchronousChannelProvider} in the resource
150     *   directory {@code META-INF/services}, then the first class name
151     *   specified in that file is taken.  The class is loaded and
152     *   instantiated; if this process fails then an unspecified error is
153     *   thrown.  </p></li>
154     *
155     *   <li><p> Finally, if no provider has been specified by any of the above
156     *   means then the system-default provider class is instantiated and the
157     *   result is returned.  </p></li>
158     *
159     * </ol>
160     *
161     * <p> Subsequent invocations of this method return the provider that was
162     * returned by the first invocation.  </p>
163     *
164     * @return  The system-wide default AsynchronousChannel provider
165     */
166    public static AsynchronousChannelProvider provider() {
167        return ProviderHolder.provider;
168    }
169
170    /**
171     * Constructs a new asynchronous channel group with a fixed thread pool.
172     *
173     * @param   nThreads
174     *          The number of threads in the pool
175     * @param   threadFactory
176     *          The factory to use when creating new threads
177     *
178     * @return  A new asynchronous channel group
179     *
180     * @throws  IllegalArgumentException
181     *          If {@code nThreads <= 0}
182     * @throws  IOException
183     *          If an I/O error occurs
184     *
185     * @see AsynchronousChannelGroup#withFixedThreadPool
186     */
187    public abstract AsynchronousChannelGroup
188        openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) throws IOException;
189
190    /**
191     * Constructs a new asynchronous channel group with the given thread pool.
192     *
193     * @param   executor
194     *          The thread pool
195     * @param   initialSize
196     *          A value {@code >=0} or a negative value for implementation
197     *          specific default
198     *
199     * @return  A new asynchronous channel group
200     *
201     * @throws  IOException
202     *          If an I/O error occurs
203     *
204     * @see AsynchronousChannelGroup#withCachedThreadPool
205     */
206    public abstract AsynchronousChannelGroup
207        openAsynchronousChannelGroup(ExecutorService executor, int initialSize) throws IOException;
208
209    /**
210     * Opens an asynchronous server-socket channel.
211     *
212     * @param   group
213     *          The group to which the channel is bound, or {@code null} to
214     *          bind to the default group
215     *
216     * @return  The new channel
217     *
218     * @throws  IllegalChannelGroupException
219     *          If the provider that created the group differs from this provider
220     * @throws  ShutdownChannelGroupException
221     *          The group is shutdown
222     * @throws  IOException
223     *          If an I/O error occurs
224     */
225    public abstract AsynchronousServerSocketChannel openAsynchronousServerSocketChannel
226        (AsynchronousChannelGroup group) throws IOException;
227
228    /**
229     * Opens an asynchronous socket channel.
230     *
231     * @param   group
232     *          The group to which the channel is bound, or {@code null} to
233     *          bind to the default group
234     *
235     * @return  The new channel
236     *
237     * @throws  IllegalChannelGroupException
238     *          If the provider that created the group differs from this provider
239     * @throws  ShutdownChannelGroupException
240     *          The group is shutdown
241     * @throws  IOException
242     *          If an I/O error occurs
243     */
244    public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
245        (AsynchronousChannelGroup group) throws IOException;
246}
247