1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel;
17
18 import io.netty.util.AbstractReferenceCounted;
19 import io.netty.util.IllegalReferenceCountException;
20 import io.netty.util.internal.logging.InternalLogger;
21 import io.netty.util.internal.logging.InternalLoggerFactory;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.RandomAccessFile;
26 import java.nio.channels.FileChannel;
27 import java.nio.channels.WritableByteChannel;
28
29
30
31
32
33
34
35 public class DefaultFileRegion extends AbstractReferenceCounted implements FileRegion {
36
37 private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultFileRegion.class);
38 private final File f;
39 private final long position;
40 private final long count;
41 private long transfered;
42 private FileChannel file;
43
44
45
46
47
48
49
50
51 public DefaultFileRegion(FileChannel file, long position, long count) {
52 if (file == null) {
53 throw new NullPointerException("file");
54 }
55 if (position < 0) {
56 throw new IllegalArgumentException("position must be >= 0 but was " + position);
57 }
58 if (count < 0) {
59 throw new IllegalArgumentException("count must be >= 0 but was " + count);
60 }
61 this.file = file;
62 this.position = position;
63 this.count = count;
64 f = null;
65 }
66
67
68
69
70
71
72
73
74
75 public DefaultFileRegion(File f, long position, long count) {
76 if (f == null) {
77 throw new NullPointerException("f");
78 }
79 if (position < 0) {
80 throw new IllegalArgumentException("position must be >= 0 but was " + position);
81 }
82 if (count < 0) {
83 throw new IllegalArgumentException("count must be >= 0 but was " + count);
84 }
85 this.position = position;
86 this.count = count;
87 this.f = f;
88 }
89
90
91
92
93 public boolean isOpen() {
94 return file != null;
95 }
96
97
98
99
100 public void open() throws IOException {
101 if (!isOpen() && refCnt() > 0) {
102
103 file = new RandomAccessFile(f, "r").getChannel();
104 }
105 }
106
107 @Override
108 public long position() {
109 return position;
110 }
111
112 @Override
113 public long count() {
114 return count;
115 }
116
117 @Override
118 public long transfered() {
119 return transfered;
120 }
121
122 @Override
123 public long transferTo(WritableByteChannel target, long position) throws IOException {
124 long count = this.count - position;
125 if (count < 0 || position < 0) {
126 throw new IllegalArgumentException(
127 "position out of range: " + position +
128 " (expected: 0 - " + (this.count - 1) + ')');
129 }
130 if (count == 0) {
131 return 0L;
132 }
133 if (refCnt() == 0) {
134 throw new IllegalReferenceCountException(0);
135 }
136
137 open();
138
139 long written = file.transferTo(this.position + position, count, target);
140 if (written > 0) {
141 transfered += written;
142 }
143 return written;
144 }
145
146 @Override
147 protected void deallocate() {
148 FileChannel file = this.file;
149
150 if (file == null) {
151 return;
152 }
153 this.file = null;
154
155 try {
156 file.close();
157 } catch (IOException e) {
158 if (logger.isWarnEnabled()) {
159 logger.warn("Failed to close a file.", e);
160 }
161 }
162 }
163 }