1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.apache.harmony.nio.internal; 18 19 import java.io.Closeable; 20 import java.io.FileDescriptor; 21 import java.io.IOException; 22 import java.nio.ByteBuffer; 23 import java.nio.channels.Pipe; 24 import java.nio.channels.spi.SelectorProvider; 25 import libcore.io.IoUtils; 26 import org.apache.harmony.luni.platform.FileDescriptorHandler; 27 28 /* 29 * Implements {@link java.nio.channels.Pipe}. 30 */ 31 final class PipeImpl extends Pipe { 32 private final PipeSinkChannel sink; 33 private final PipeSourceChannel source; 34 35 public PipeImpl() throws IOException { 36 int[] fds = new int[2]; 37 IoUtils.pipe(fds); 38 // Which fd is used for which channel is important. Unix pipes are only guaranteed to be 39 // unidirectional, and indeed are only unidirectional on Linux. See IoUtils.pipe. 40 this.sink = new PipeSinkChannel(fds[1]); 41 this.source = new PipeSourceChannel(fds[0]); 42 } 43 44 @Override public SinkChannel sink() { 45 return sink; 46 } 47 48 @Override public SourceChannel source() { 49 return source; 50 } 51 52 /** 53 * FileChannelImpl doesn't close its fd itself; it calls close on the object it's given. 54 */ 55 private static class FdCloser implements Closeable { 56 private final FileDescriptor fd; 57 private FdCloser(FileDescriptor fd) { 58 this.fd = fd; 59 } 60 public void close() throws IOException { 61 IoUtils.close(fd); 62 } 63 } 64 65 private class PipeSourceChannel extends Pipe.SourceChannel implements FileDescriptorHandler { 66 private final FileDescriptor fd; 67 private final FileChannelImpl channel; 68 69 private PipeSourceChannel(int fd) throws IOException { 70 super(SelectorProvider.provider()); 71 this.fd = IoUtils.newFileDescriptor(fd); 72 this.channel = new ReadOnlyFileChannel(new FdCloser(this.fd), fd); 73 } 74 75 @Override protected void implCloseSelectableChannel() throws IOException { 76 channel.close(); 77 } 78 79 @Override protected void implConfigureBlocking(boolean blocking) throws IOException { 80 IoUtils.setBlocking(getFD(), blocking); 81 } 82 83 public int read(ByteBuffer buffer) throws IOException { 84 return channel.read(buffer); 85 } 86 87 public long read(ByteBuffer[] buffers) throws IOException { 88 return channel.read(buffers); 89 } 90 91 public long read(ByteBuffer[] buffers, int offset, int length) throws IOException { 92 return channel.read(buffers, offset, length); 93 } 94 95 public FileDescriptor getFD() { 96 return fd; 97 } 98 } 99 100 private class PipeSinkChannel extends Pipe.SinkChannel implements FileDescriptorHandler { 101 private final FileDescriptor fd; 102 private final FileChannelImpl channel; 103 104 private PipeSinkChannel(int fd) throws IOException { 105 super(SelectorProvider.provider()); 106 this.fd = IoUtils.newFileDescriptor(fd); 107 this.channel = new WriteOnlyFileChannel(new FdCloser(this.fd), fd); 108 } 109 110 @Override protected void implCloseSelectableChannel() throws IOException { 111 channel.close(); 112 } 113 114 @Override protected void implConfigureBlocking(boolean blocking) throws IOException { 115 IoUtils.setBlocking(getFD(), blocking); 116 } 117 118 public int write(ByteBuffer buffer) throws IOException { 119 return channel.write(buffer); 120 } 121 122 public long write(ByteBuffer[] buffers) throws IOException { 123 return channel.write(buffers); 124 } 125 126 public long write(ByteBuffer[] buffers, int offset, int length) throws IOException { 127 return channel.write(buffers, offset, length); 128 } 129 130 public FileDescriptor getFD() { 131 return fd; 132 } 133 } 134 } 135