Skip to content

Package: WritableSharedFile

WritableSharedFile

nameinstructionbranchcomplexitylinemethod
WritableSharedFile(File)
M: 15 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
close()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
getAppendStream()
M: 17 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getWritableFile()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
updateLength()
M: 11 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package org.eclipse.angus.mail.mbox;
18:
19: import org.eclipse.angus.mail.util.PropUtil;
20: import jakarta.mail.util.SharedFileInputStream;
21:
22: import java.io.*;
23:
24: /**
25: * A temporary file used to cache messages.
26: */
27: class TempFile {
28:
29: private File file;        // the temp file name
30: private WritableSharedFile sf;
31:
32: /**
33: * Create a temp file in the specified directory (if not null).
34: * The file will be deleted when the JVM exits.
35: */
36: public TempFile(File dir) throws IOException {
37:         file = File.createTempFile("mbox.", ".mbox", dir);
38:         // XXX - need JDK 6 to set permissions on the file to owner-only
39:         file.deleteOnExit();
40:         sf = new WritableSharedFile(file);
41: }
42:
43: /**
44: * Return a stream for appending to the temp file.
45: */
46: public AppendStream getAppendStream() throws IOException {
47:         return sf.getAppendStream();
48: }
49:
50: /**
51: * Return a stream for reading from part of the file.
52: */
53: public InputStream newStream(long start, long end) {
54:         return sf.newStream(start, end);
55: }
56:
57: public long length() {
58:         return file.length();
59: }
60:
61: /**
62: * Close and remove this temp file.
63: */
64: public void close() {
65:         try {
66:          sf.close();
67:         } catch (IOException ex) {
68:          // ignore it
69:         }
70:         file.delete();
71: }
72:
73: protected void finalize() throws Throwable {
74:         try {
75:          close();
76:         } finally {
77:          super.finalize();
78:         }
79: }
80: }
81:
82: /**
83: * A subclass of SharedFileInputStream that also allows writing.
84: */
85: class WritableSharedFile extends SharedFileInputStream {
86: private RandomAccessFile raf;
87: private AppendStream af;
88:
89: public WritableSharedFile(File file) throws IOException {
90:         super(file);
91:         try {
92:          raf = new RandomAccessFile(file, "rw");
93:         } catch (IOException ex) {
94:          // if anything goes wrong opening the writable file,
95:          // close the readable file too
96:          super.close();
97:         }
98: }
99:
100: /**
101: * Return the writable version of this file.
102: */
103: public RandomAccessFile getWritableFile() {
104:         return raf;
105: }
106:
107: /**
108: * Close the readable and writable files.
109: */
110: public void close() throws IOException {
111:         try {
112:          super.close();
113:         } finally {
114:          raf.close();
115:         }
116: }
117:
118: /**
119: * Update the size of the readable file after writing
120: * to the file. Updates the length to be the current
121: * size of the file.
122: */
123: synchronized long updateLength() throws IOException {
124:         datalen = in.length();
125:         af = null;
126:         return datalen;
127: }
128:
129: /**
130: * Return a new AppendStream, but only if one isn't in active use.
131: */
132: public synchronized AppendStream getAppendStream() throws IOException {
133:•        if (af != null)
134:          throw new IOException(
135:                 "file cache only supports single threaded access");
136:         af = new AppendStream(this);
137:         return af;
138: }
139: }
140:
141: /**
142: * A stream for writing to the temp file, and when done
143: * can return a stream for reading the data just written.
144: * NOTE: We assume that only one thread is writing to the
145: * file at a time.
146: */
147: class AppendStream extends OutputStream {
148: private final WritableSharedFile tf;
149: private RandomAccessFile raf;
150: private final long start;
151: private long end;
152:
153: public AppendStream(WritableSharedFile tf) throws IOException {
154:         this.tf = tf;
155:         raf = tf.getWritableFile();
156:         start = raf.length();
157:         raf.seek(start);
158: }
159:
160: public void write(int b) throws IOException {
161:         raf.write(b);
162: }
163:
164: public void write(byte[] b) throws IOException {
165:         raf.write(b);
166: }
167:
168: public void write(byte[] b, int off, int len) throws IOException {
169:         raf.write(b, off, len);
170: }
171:
172: public synchronized void close() throws IOException {
173:         end = tf.updateLength();
174:         raf = null;        // no more writing allowed
175: }
176:
177: public synchronized InputStream getInputStream() throws IOException {
178:         return tf.newStream(start, end);
179: }
180: }