View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.io.channels;
19  
20  import java.io.IOException;
21  import java.nio.ByteBuffer;
22  import java.nio.MappedByteBuffer;
23  import java.nio.channels.Channel;
24  import java.nio.channels.FileChannel;
25  import java.nio.channels.FileLock;
26  import java.nio.channels.ReadableByteChannel;
27  import java.nio.channels.WritableByteChannel;
28  import java.util.Objects;
29  
30  import org.apache.commons.io.build.AbstractStreamBuilder;
31  
32  /**
33   * Filters a {@link FileChannel}.
34   * <p>
35   * 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
36   * additional functionality. The class {@code FilterFileChannel} itself simply overrides methods of {@code FileChannel} with versions that pass all requests to
37   * the wrapped channel. Subclasses of {@code FilterFileChannel} may of course override any methods declared or inherited by {@code FilterFileChannel}, and may
38   * also provide additional fields and methods.
39   * </p>
40   * <p>
41   * You construct s simple instance with the {@link FilterFileChannel#FilterFileChannel(FileChannel) channel constructor} and more advanced instances through the
42   * {@link Builder}.
43   * </p>
44   *
45   * @since 2.22.0
46   */
47  public class FilterFileChannel extends FileChannel {
48  
49      /**
50       * Builds instances of {@link FilterFileChannel} for subclasses.
51       *
52       * @param <F> The {@link FilterFileChannel} type.
53       * @param <C> The {@link Channel} type wrapped by the FilterChannel.
54       * @param <B> The builder type.
55       */
56      public abstract static class AbstractBuilder<F extends FilterFileChannel, C extends FileChannel, B extends AbstractBuilder<F, C, B>>
57              extends AbstractStreamBuilder<F, AbstractBuilder<F, C, B>> {
58  
59          /**
60           * Constructs instance for subclasses.
61           */
62          protected AbstractBuilder() {
63              // empty
64          }
65      }
66  
67      /**
68       * Builds instances of {@link FilterFileChannel}.
69       */
70      public static class Builder extends AbstractBuilder<FilterFileChannel, FileChannel, Builder> {
71  
72          /**
73           * Builds instances of {@link FilterChannel}.
74           */
75          protected Builder() {
76              // empty
77          }
78  
79          @Override
80          public FilterFileChannel get() throws IOException {
81              return new FilterFileChannel(this);
82          }
83      }
84  
85      /**
86       * Creates a new {@link Builder}.
87       *
88       * @return a new {@link Builder}.
89       */
90      public static Builder forFilterFileChannel() {
91          return new Builder();
92      }
93  
94      final FileChannel fileChannel;
95  
96      private FilterFileChannel(final Builder builder) throws IOException {
97          this.fileChannel = builder.getChannel(FileChannel.class);
98      }
99  
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 }