1 /*
  2  * Copyright (c) 2022, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /* @test
 25  * @enablePreview
 26  * @bug 8281412
 27  * @summary Test FileChannel::map to MemorySegment with custom file channel
 28  * @run testng/othervm MapToMemorySegmentTest
 29  */
 30 
 31 import java.io.File;
 32 import java.io.IOException;
 33 import java.lang.foreign.Arena;
 34 import java.lang.foreign.MemorySegment;
 35 import java.nio.ByteBuffer;
 36 import java.nio.MappedByteBuffer;
 37 import java.nio.channels.FileChannel;
 38 import java.nio.channels.FileLock;
 39 import java.nio.channels.ReadableByteChannel;
 40 import java.nio.channels.WritableByteChannel;
 41 import java.nio.file.Path;
 42 import java.nio.file.StandardOpenOption;
 43 import org.testng.annotations.Test;
 44 
 45 import static org.testng.Assert.assertTrue;
 46 import static org.testng.Assert.fail;
 47 
 48 public class MapToMemorySegmentTest {
 49 
 50     static Path tempPath;
 51 
 52     static {
 53         try {
 54             File file = File.createTempFile("foo", "txt");
 55             file.deleteOnExit();
 56             tempPath = file.toPath();
 57         } catch (IOException ex) {
 58             throw new ExceptionInInitializerError(ex);
 59         }
 60     }
 61 
 62     @Test(expectedExceptions = UnsupportedOperationException.class)
 63     public void testCustomFileChannel() throws IOException {
 64         var arena = Arena.ofConfined();
 65         var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ);
 66         var fileChannel = new CustomFileChannel(fc);
 67         try (arena; fileChannel){
 68             fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena);
 69         }
 70     }
 71 
 72     @Test
 73     public void testCustomFileChannelOverride() throws IOException {
 74         var arena = Arena.ofConfined();
 75         var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ);
 76         var fileChannel = new CustomFileChannelOverride(fc);
 77         try (arena; fileChannel){
 78             fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena);
 79         }
 80     }
 81 
 82     static class CustomFileChannel extends FileChannel {
 83         FileChannel fc;
 84 
 85         public CustomFileChannel(FileChannel fc) {
 86             this.fc = fc;
 87         }
 88 
 89         public int read(ByteBuffer dst) throws IOException {
 90             return fc.read(dst);
 91         }
 92 
 93         public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
 94             return fc.read(dsts, offset, length);
 95         }
 96 
 97         public int write(ByteBuffer src) throws IOException {
 98             return fc.write(src);
 99         }
100 
101         public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
102             return fc.write(srcs, offset, length);
103         }
104 
105         public long position() throws IOException {
106             return fc.position();
107         }
108 
109         public FileChannel position(long newPosition) throws IOException {
110             return fc.position(newPosition);
111         }
112 
113         public long size() throws IOException {
114             return fc.size();
115         }
116 
117         public FileChannel truncate(long size) throws IOException {
118             return fc.truncate(size);
119         }
120 
121         public void force(boolean metaData) throws IOException {
122             this.fc.force(metaData);
123         }
124 
125         public long transferTo(long position, long count, WritableByteChannel target) throws IOException {
126             return fc.transferTo(position, count, target);
127         }
128 
129         public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException {
130             return fc.transferFrom(src, position, count);
131         }
132 
133         public int read(ByteBuffer dst, long position) throws IOException {
134             return fc.read(dst, position);
135         }
136 
137         public int write(ByteBuffer src, long position) throws IOException {
138             return fc.write(src, position);
139         }
140 
141         public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
142             return fc.map(mode, position, size);
143         }
144 
145         public FileLock lock(long position, long size, boolean shared) throws IOException {
146             return fc.lock(position, size, shared);
147         }
148 
149         public FileLock tryLock(long position, long size, boolean shared) throws IOException {
150             return fc.tryLock(position , size, shared);
151         }
152 
153         protected void implCloseChannel() throws IOException {
154             fc.close();
155         }
156     }
157 
158     static class CustomFileChannelOverride extends CustomFileChannel {
159 
160         public CustomFileChannelOverride(FileChannel fc) { super(fc); }
161 
162         @Override
163         public MemorySegment map(MapMode mode, long offset, long size, Arena arena)
164                 throws IOException, UnsupportedOperationException
165         {
166             return fc.map(mode, offset, size, arena);
167         }
168     }
169 }