001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.io.channels; 019 020import java.io.IOException; 021import java.nio.ByteBuffer; 022import java.nio.MappedByteBuffer; 023import java.nio.channels.Channel; 024import java.nio.channels.FileChannel; 025import java.nio.channels.FileLock; 026import java.nio.channels.ReadableByteChannel; 027import java.nio.channels.WritableByteChannel; 028import java.util.Objects; 029 030import org.apache.commons.io.build.AbstractStreamBuilder; 031 032/** 033 * Filters a {@link FileChannel}. 034 * <p> 035 * A {@code FilterFileChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing 036 * additional functionality. The class {@code FilterFileChannel} itself simply overrides methods of {@code FileChannel} with versions that pass all requests to 037 * the wrapped channel. Subclasses of {@code FilterFileChannel} may of course override any methods declared or inherited by {@code FilterFileChannel}, and may 038 * also provide additional fields and methods. 039 * </p> 040 * <p> 041 * You construct s simple instance with the {@link FilterFileChannel#FilterFileChannel(FileChannel) channel constructor} and more advanced instances through the 042 * {@link Builder}. 043 * </p> 044 * 045 * @since 2.22.0 046 */ 047public class FilterFileChannel extends FileChannel { 048 049 /** 050 * Builds instances of {@link FilterFileChannel} for subclasses. 051 * 052 * @param <F> The {@link FilterFileChannel} type. 053 * @param <C> The {@link Channel} type wrapped by the FilterChannel. 054 * @param <B> The builder type. 055 */ 056 public abstract static class AbstractBuilder<F extends FilterFileChannel, C extends FileChannel, B extends AbstractBuilder<F, C, B>> 057 extends AbstractStreamBuilder<F, AbstractBuilder<F, C, B>> { 058 059 /** 060 * Constructs instance for subclasses. 061 */ 062 protected AbstractBuilder() { 063 // empty 064 } 065 } 066 067 /** 068 * Builds instances of {@link FilterFileChannel}. 069 */ 070 public static class Builder extends AbstractBuilder<FilterFileChannel, FileChannel, Builder> { 071 072 /** 073 * Builds instances of {@link FilterChannel}. 074 */ 075 protected Builder() { 076 // empty 077 } 078 079 @Override 080 public FilterFileChannel get() throws IOException { 081 return new FilterFileChannel(this); 082 } 083 } 084 085 /** 086 * Creates a new {@link Builder}. 087 * 088 * @return a new {@link Builder}. 089 */ 090 public static Builder forFilterFileChannel() { 091 return new Builder(); 092 } 093 094 final FileChannel fileChannel; 095 096 private FilterFileChannel(final Builder builder) throws IOException { 097 this.fileChannel = builder.getChannel(FileChannel.class); 098 } 099 100 /** 101 * Constructs a new instance. 102 * 103 * @param fileChannel the file channel to wrap. 104 */ 105 public FilterFileChannel(final FileChannel fileChannel) { 106 this.fileChannel = Objects.requireNonNull(fileChannel, "fileChannel"); 107 } 108 109 @Override 110 public boolean equals(final Object o) { 111 return fileChannel.equals(o); 112 } 113 114 @Override 115 public void force(final boolean metaData) throws IOException { 116 fileChannel.force(metaData); 117 } 118 119 @Override 120 public int hashCode() { 121 return fileChannel.hashCode(); 122 } 123 124 @Override 125 protected void implCloseChannel() throws IOException { 126 fileChannel.close(); 127 } 128 129 @Override 130 public FileLock lock(final long position, final long size, final boolean shared) throws IOException { 131 return fileChannel.lock(position, size, shared); 132 } 133 134 @Override 135 public MappedByteBuffer map(final MapMode mode, final long position, final long size) throws IOException { 136 return fileChannel.map(mode, position, size); 137 } 138 139 @Override 140 public long position() throws IOException { 141 return fileChannel.position(); 142 } 143 144 @Override 145 public FileChannel position(final long newPosition) throws IOException { 146 return fileChannel.position(newPosition); 147 } 148 149 @Override 150 public int read(final ByteBuffer dst) throws IOException { 151 return fileChannel.read(dst); 152 } 153 154 @Override 155 public int read(final ByteBuffer dst, final long position) throws IOException { 156 return fileChannel.read(dst, position); 157 } 158 159 @Override 160 public long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException { 161 return fileChannel.read(dsts, offset, length); 162 } 163 164 @Override 165 public long size() throws IOException { 166 return fileChannel.size(); 167 } 168 169 @Override 170 public String toString() { 171 return fileChannel.toString(); 172 } 173 174 @Override 175 public long transferFrom(final ReadableByteChannel src, final long position, final long count) throws IOException { 176 return fileChannel.transferFrom(src, position, count); 177 } 178 179 @Override 180 public long transferTo(final long position, final long count, final WritableByteChannel target) throws IOException { 181 return fileChannel.transferTo(position, count, target); 182 } 183 184 @Override 185 public FileChannel truncate(final long size) throws IOException { 186 return fileChannel.truncate(size); 187 } 188 189 @Override 190 public FileLock tryLock(final long position, final long size, final boolean shared) throws IOException { 191 return fileChannel.tryLock(position, size, shared); 192 } 193 194 /** 195 * Unwraps this instance by returning the underlying {@link FileChannel}. 196 * <p> 197 * Use with caution. 198 * </p> 199 * 200 * @return the underlying {@link FileChannel}. 201 */ 202 public FileChannel unwrap() { 203 return fileChannel; 204 } 205 206 @Override 207 public int write(final ByteBuffer src) throws IOException { 208 return fileChannel.write(src); 209 } 210 211 @Override 212 public int write(final ByteBuffer src, final long position) throws IOException { 213 return fileChannel.write(src, position); 214 } 215 216 @Override 217 public long write(final ByteBuffer[] srcs, final int offset, final int length) throws IOException { 218 return fileChannel.write(srcs, offset, length); 219 } 220}