1
/****************************************************************
2
* Licensed to the Apache Software Foundation (ASF) under one *
3
* or more contributor license agreements. See the NOTICE file *
4
* distributed with this work for additional information *
5
* regarding copyright ownership. The ASF licenses this file *
6
* to you under the Apache License, Version 2.0 (the *
7
* "License"); you may not use this file except in compliance *
8
* with the License. You may obtain a copy of the License at *
10
* http://www.apache.org/licenses/LICENSE-2.0 *
12
* Unless required by applicable law or agreed to in writing, *
13
* software distributed under the License is distributed on an *
14
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15
* KIND, either express or implied. See the License for the *
16
* specific language governing permissions and limitations *
17
* under the License. *
18
****************************************************************/
20
package org.apache.james.mime4j.storage;
22
import java.io.BufferedInputStream;
24
import java.io.FileInputStream;
25
import java.io.FileOutputStream;
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.OutputStream;
29
import java.util.HashSet;
30
import java.util.Iterator;
34
* A {@link StorageProvider} that stores the data in temporary files. The files
35
* are stored either in a user-specified directory or the default temporary-file
36
* directory (specified by system property <code>java.io.tmpdir</code>).
41
* File directory = new File("/tmp/mime4j");
42
* StorageProvider provider = new TempFileStorageProvider(directory);
43
* DefaultStorageProvider.setInstance(provider);
46
public class TempFileStorageProvider extends AbstractStorageProvider {
48
private static final String DEFAULT_PREFIX = "m4j";
50
private final String prefix;
51
private final String suffix;
52
private final File directory;
55
* Equivalent to using constructor
56
* <code>TempFileStorageProvider("m4j", null, null)</code>.
58
public TempFileStorageProvider() {
59
this(DEFAULT_PREFIX, null, null);
63
* Equivalent to using constructor
64
* <code>TempFileStorageProvider("m4j", null, directory)</code>.
66
public TempFileStorageProvider(File directory) {
67
this(DEFAULT_PREFIX, null, directory);
71
* Creates a new <code>TempFileStorageProvider</code> using the given
75
* prefix for generating the temporary file's name; must be at
76
* least three characters long.
78
* suffix for generating the temporary file's name; may be
79
* <code>null</code> to use the suffix <code>".tmp"</code>.
81
* the directory in which the file is to be created, or
82
* <code>null</code> if the default temporary-file directory is
83
* to be used (specified by the system property
84
* <code>java.io.tmpdir</code>).
85
* @throws IllegalArgumentException
86
* if the given prefix is less than three characters long or the
87
* given directory does not exist and cannot be created (if it
88
* is not <code>null</code>).
90
public TempFileStorageProvider(String prefix, String suffix, File directory) {
91
if (prefix == null || prefix.length() < 3)
92
throw new IllegalArgumentException("invalid prefix");
94
if (directory != null && !directory.isDirectory()
95
&& !directory.mkdirs())
96
throw new IllegalArgumentException("invalid directory");
100
this.directory = directory;
103
public StorageOutputStream createStorageOutputStream() throws IOException {
104
File file = File.createTempFile(prefix, suffix, directory);
107
return new TempFileStorageOutputStream(file);
110
private static final class TempFileStorageOutputStream extends
111
StorageOutputStream {
113
private OutputStream out;
115
public TempFileStorageOutputStream(File file) throws IOException {
117
this.out = new FileOutputStream(file);
121
public void close() throws IOException {
127
protected void write0(byte[] buffer, int offset, int length)
129
out.write(buffer, offset, length);
133
protected Storage toStorage0() throws IOException {
134
// out has already been closed because toStorage calls close
135
return new TempFileStorage(file);
139
private static final class TempFileStorage implements Storage {
143
private static final Set<File> filesToDelete = new HashSet<File>();
145
public TempFileStorage(File file) {
149
public void delete() {
150
// deleting a file might not immediately succeed if there are still
151
// streams left open (especially under Windows). so we keep track of
152
// the files that have to be deleted and try to delete all these
153
// files each time this method gets invoked.
155
// a better but more complicated solution would be to start a
156
// separate thread that tries to delete the files periodically.
158
synchronized (filesToDelete) {
160
filesToDelete.add(file);
164
for (Iterator<File> iterator = filesToDelete.iterator(); iterator
166
File file = iterator.next();
174
public InputStream getInputStream() throws IOException {
176
throw new IllegalStateException("storage has been deleted");
178
return new BufferedInputStream(new FileInputStream(file));