src/jdk.net/share/classes/jdk/nio/Channels.java
changeset 50739 4bedc9338137
equal deleted inserted replaced
50738:6cc2dc161c64 50739:4bedc9338137
       
     1 /*
       
     2  * Copyright (c) 2018, 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 
       
    26 package jdk.nio;
       
    27 
       
    28 import java.io.FileDescriptor;
       
    29 import java.io.IOException;
       
    30 import java.nio.channels.SelectableChannel;
       
    31 import java.nio.channels.SelectionKey;
       
    32 import java.nio.channels.spi.AbstractSelectableChannel;
       
    33 import java.nio.channels.spi.SelectorProvider;
       
    34 import java.util.Objects;
       
    35 
       
    36 import sun.nio.ch.IOUtil;
       
    37 import sun.nio.ch.Net;
       
    38 import sun.nio.ch.SelChImpl;
       
    39 import sun.nio.ch.SelectionKeyImpl;
       
    40 import sun.nio.ch.SelectorProviderImpl;
       
    41 
       
    42 /**
       
    43  * Defines static methods to create {@link java.nio.channels.Channel channels}.
       
    44  *
       
    45  * <p> Unless otherwise specified, passing a {@code null} argument to any of the
       
    46  * methods defined here will cause a {@code NullPointerException} to be thrown.
       
    47  *
       
    48  * @since 11
       
    49  */
       
    50 
       
    51 public final class Channels {
       
    52     private Channels() { }
       
    53 
       
    54     /**
       
    55      * An object used to coordinate the closing of a selectable channel created
       
    56      * by {@link Channels#readWriteSelectableChannel readWriteSelectableChannel}.
       
    57      *
       
    58      * @since 11
       
    59      */
       
    60     public interface SelectableChannelCloser {
       
    61 
       
    62         /**
       
    63          * Closes a selectable channel.
       
    64          *
       
    65          * <p> This method is invoked by the channel's close method in order to
       
    66          * perform the actual work of closing the channel. This method is only
       
    67          * invoked if the channel has not yet been closed, and it is never
       
    68          * invoked more than once by the channel's close implementation.
       
    69          *
       
    70          * <p> An implementation of this method must arrange for any other
       
    71          * thread that is blocked in an I/O operation upon the channel to return
       
    72          * immediately, either by throwing an exception or by returning normally.
       
    73          * If the channel is {@link SelectableChannel#isRegistered registered}
       
    74          * with one or more {@link java.nio.channels.Selector Selector}s then
       
    75          * the file descriptor should not be released until the {@link
       
    76          * #implReleaseChannel implReleaseChannel} method is invoked. </p>
       
    77          *
       
    78          * @param  sc
       
    79          *         The selectable channel
       
    80          *
       
    81          * @throws IOException
       
    82          *         If an I/O error occurs while closing the file descriptor
       
    83          *
       
    84          * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel
       
    85          */
       
    86         void implCloseChannel(SelectableChannel sc) throws IOException;
       
    87 
       
    88         /**
       
    89          * Release the file descriptor and any resources for a selectable
       
    90          * channel that closed while registered with one or more {@link
       
    91          * java.nio.channels.Selector Selector}s.
       
    92          *
       
    93          * <p> This method is for cases where a channel is closed when
       
    94          * {@link java.nio.channels.SelectableChannel#isRegistered registered}
       
    95          * with one or more {@code Selector}s. A channel may remain registered
       
    96          * for some time after it is closed. This method is invoked when the
       
    97          * channel is eventually deregistered from the last {@code Selector}
       
    98          * that it was registered with. It is invoked at most once.
       
    99          *
       
   100          * @apiNote This method is invoked while synchronized on the selector
       
   101          * and its selected-key set. Great care must be taken to avoid deadlocks
       
   102          * with other threads that also synchronize on these objects.
       
   103          *
       
   104          * @param  sc
       
   105          *         The closed selectable channel
       
   106          *
       
   107          * @throws IOException
       
   108          *         If an I/O error occurs
       
   109          *
       
   110          * @see java.nio.channels.spi.AbstractSelector#deregister
       
   111          */
       
   112         void implReleaseChannel(SelectableChannel sc) throws IOException;
       
   113     }
       
   114 
       
   115     /**
       
   116      * Creates a selectable channel to a file descriptor that supports an
       
   117      * {@link SelectableChannel#validOps() operation-set} of
       
   118      * {@link SelectionKey#OP_READ OP_READ} and
       
   119      * {@link SelectionKey#OP_WRITE OP_WRITE}. The selectable channel will be
       
   120      * created by the default {@link SelectorProvider}.
       
   121      *
       
   122      * <p> The given file descriptor is a socket or resource that can be
       
   123      * multiplexed by a {@link java.nio.channels.Selector} for read and write
       
   124      * readiness. Great care is required to coordinate direct use of the file
       
   125      * descriptor with the use of the selectable channel. In particular,
       
   126      * changing the blocking mode or closing the file descriptor without careful
       
   127      * coordination will result in unspecified and unsafe side effects. The
       
   128      * given {@link SelectableChannelCloser SelectableChannelCloser} is invoked to
       
   129      * close the file descriptor and to coordinate the closing when the channel
       
   130      * is registered with a {@code Selector}. </p>
       
   131      *
       
   132      * <p> If there is a security manager set then its
       
   133      * {@link SecurityManager#checkRead(FileDescriptor) checkRead} and
       
   134      * {@link SecurityManager#checkWrite(FileDescriptor) checkWrite} methods
       
   135      * are invoked to check that the caller has permission to both read from and
       
   136      * write to the file descriptor. </p>
       
   137      *
       
   138      * @implNote This method throws {@code UnsupportedOperationException} if
       
   139      * the default {@code SelectorProvider} is not the JDK built-in implementation.
       
   140      *
       
   141      * @param  fd
       
   142      *         The file descriptor
       
   143      * @param  closer
       
   144      *         The object to close the channel
       
   145      *
       
   146      * @return The selectable channel
       
   147      *
       
   148      * @throws IllegalArgumentException
       
   149      *         If the file descriptor is not {@link FileDescriptor#valid() valid}
       
   150      * @throws SecurityException
       
   151      *         If denied by the security manager
       
   152      */
       
   153     public static SelectableChannel readWriteSelectableChannel(FileDescriptor fd,
       
   154                                                                SelectableChannelCloser closer) {
       
   155         Objects.requireNonNull(closer);
       
   156         if (!fd.valid())
       
   157             throw new IllegalArgumentException("file descriptor is not valid");
       
   158 
       
   159         SecurityManager sm = System.getSecurityManager();
       
   160         if (sm != null) {
       
   161             sm.checkRead(fd);
       
   162             sm.checkWrite(fd);
       
   163         }
       
   164 
       
   165         SelectorProvider provider = SelectorProvider.provider();
       
   166         if (!(provider instanceof SelectorProviderImpl))
       
   167             throw new UnsupportedOperationException("custom SelectorProvider");
       
   168 
       
   169         return new ReadWriteChannelImpl((SelectorProviderImpl)provider, fd, closer);
       
   170     }
       
   171 
       
   172     private static final class ReadWriteChannelImpl
       
   173         extends AbstractSelectableChannel implements SelChImpl
       
   174     {
       
   175         private final FileDescriptor fd;
       
   176         private final int fdVal;
       
   177         private final SelectableChannelCloser closer;
       
   178 
       
   179         ReadWriteChannelImpl(SelectorProviderImpl provider,
       
   180                              FileDescriptor fd,
       
   181                              SelectableChannelCloser closer) {
       
   182             super(provider);
       
   183             this.fd = fd;
       
   184             this.fdVal = IOUtil.fdVal(fd);
       
   185             this.closer = closer;
       
   186         }
       
   187 
       
   188         @Override
       
   189         public FileDescriptor getFD() {
       
   190             return fd;
       
   191         }
       
   192 
       
   193         @Override
       
   194         public int getFDVal() {
       
   195             return fdVal;
       
   196         }
       
   197 
       
   198         @Override
       
   199         public int validOps() {
       
   200             return (SelectionKey.OP_READ | SelectionKey.OP_WRITE);
       
   201         }
       
   202 
       
   203         private boolean translateReadyOps(int ops,
       
   204                                           int initialOps,
       
   205                                           SelectionKeyImpl ski) {
       
   206             int intOps = ski.nioInterestOps();
       
   207             int oldOps = ski.nioReadyOps();
       
   208             int newOps = initialOps;
       
   209 
       
   210             if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
       
   211                 newOps = intOps;
       
   212                 ski.nioReadyOps(newOps);
       
   213                 return (newOps & ~oldOps) != 0;
       
   214             }
       
   215 
       
   216             if (((ops & Net.POLLIN) != 0) &&
       
   217                     ((intOps & SelectionKey.OP_READ) != 0))
       
   218                 newOps |= SelectionKey.OP_READ;
       
   219 
       
   220             if (((ops & Net.POLLOUT) != 0) &&
       
   221                     ((intOps & SelectionKey.OP_WRITE) != 0))
       
   222                 newOps |= SelectionKey.OP_WRITE;
       
   223 
       
   224             ski.nioReadyOps(newOps);
       
   225             return (newOps & ~oldOps) != 0;
       
   226         }
       
   227 
       
   228         @Override
       
   229         public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
       
   230             return translateReadyOps(ops, ski.nioReadyOps(), ski);
       
   231         }
       
   232 
       
   233         @Override
       
   234         public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
       
   235             return translateReadyOps(ops, 0, ski);
       
   236         }
       
   237 
       
   238         @Override
       
   239         public int translateInterestOps(int ops) {
       
   240             int newOps = 0;
       
   241             if ((ops & SelectionKey.OP_READ) != 0)
       
   242                 newOps |= Net.POLLIN;
       
   243             if ((ops & SelectionKey.OP_WRITE) != 0)
       
   244                 newOps |= Net.POLLOUT;
       
   245             return newOps;
       
   246         }
       
   247 
       
   248         @Override
       
   249         protected void implConfigureBlocking(boolean block) throws IOException {
       
   250             IOUtil.configureBlocking(fd, block);
       
   251         }
       
   252 
       
   253         @Override
       
   254         protected void implCloseSelectableChannel() throws IOException {
       
   255             closer.implCloseChannel(this);
       
   256         }
       
   257 
       
   258         @Override
       
   259         public void kill() throws IOException {
       
   260             closer.implReleaseChannel(this);
       
   261         }
       
   262     }
       
   263 }