1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.nio.channels.spi;
19
20import java.io.IOException;
21import java.nio.SelectorProviderImpl;
22import java.nio.channels.Channel;
23import java.nio.channels.DatagramChannel;
24import java.nio.channels.Pipe;
25import java.nio.channels.ServerSocketChannel;
26import java.nio.channels.SocketChannel;
27import java.util.ServiceLoader;
28
29/**
30 * {@code SelectorProvider} is an abstract base class that declares methods for
31 * providing instances of {@link DatagramChannel}, {@link Pipe},
32 * {@link java.nio.channels.Selector} , {@link ServerSocketChannel}, and
33 * {@link SocketChannel}. All the methods of this class are thread-safe.
34 *
35 * <p>A provider instance can be retrieved through a system property or the
36 * configuration file in a jar file; if no provider is available that way then
37 * the system default provider is returned.
38 */
39public abstract class SelectorProvider {
40
41    private static SelectorProvider provider = null;
42
43    /**
44     * Constructs a new {@code SelectorProvider}.
45     */
46    protected SelectorProvider() {
47    }
48
49    /**
50     * Gets a provider instance by executing the following steps when called for
51     * the first time:
52     * <ul>
53     * <li> if the system property "java.nio.channels.spi.SelectorProvider" is
54     * set, the value of this property is the class name of the provider
55     * returned; </li>
56     * <li>if there is a provider-configuration file named
57     * "java.nio.channels.spi.SelectorProvider" in META-INF/services of a jar
58     * file valid in the system class loader, the first class name is the
59     * provider's class name; </li>
60     * <li> otherwise, a system default provider will be returned.</li>
61     * </ul>
62     *
63     * @return the provider.
64     */
65    synchronized public static SelectorProvider provider() {
66        if (provider == null) {
67            provider = ServiceLoader.loadFromSystemProperty(SelectorProvider.class);
68            if (provider == null) {
69                provider = loadProviderByJar();
70            }
71            if (provider == null) {
72                provider = new SelectorProviderImpl();
73            }
74        }
75        return provider;
76    }
77
78    private static SelectorProvider loadProviderByJar() {
79        for (SelectorProvider provider : ServiceLoader.load(SelectorProvider.class)) {
80            return provider;
81        }
82        return null;
83    }
84
85    /**
86     * Creates a new open {@code DatagramChannel}.
87     *
88     * @return the new channel.
89     * @throws IOException
90     *             if an I/O error occurs.
91     */
92    public abstract DatagramChannel openDatagramChannel() throws IOException;
93
94    /**
95     * Creates a new {@code Pipe}.
96     *
97     * @return the new pipe.
98     * @throws IOException
99     *             if an I/O error occurs.
100     */
101    public abstract Pipe openPipe() throws IOException;
102
103    /**
104     * Creates a new selector.
105     *
106     * @return the new selector.
107     * @throws IOException
108     *             if an I/O error occurs.
109     */
110    public abstract AbstractSelector openSelector() throws IOException;
111
112    /**
113     * Creates a new open {@code ServerSocketChannel}.
114     *
115     * @return the new channel.
116     * @throws IOException
117     *             if an I/O error occurs.
118     */
119    public abstract ServerSocketChannel openServerSocketChannel()
120            throws IOException;
121
122    /**
123     * Create a new open {@code SocketChannel}.
124     *
125     * @return the new channel.
126     * @throws IOException
127     *             if an I/O error occurs.
128     */
129    public abstract SocketChannel openSocketChannel() throws IOException;
130
131    /**
132     * Returns the channel inherited from the process that created this VM.
133     * On Android, this method always returns null because stdin and stdout are
134     * never connected to a socket.
135     *
136     * @return the channel.
137     * @throws IOException
138     *             if an I/O error occurs.
139     */
140    public Channel inheritedChannel() throws IOException {
141        // Android never has stdin/stdout connected to a socket.
142        return null;
143    }
144}
145