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 }