~ubuntu-branches/ubuntu/utopic/apache-mime4j/utopic-proposed

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/james/mime4j/storage/TempFileStorageProvider.java

  • Committer: Package Import Robot
  • Author(s): David Paleino
  • Date: 2013-11-03 11:13:27 UTC
  • mfrom: (2.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20131103111327-09huep00ex05z113
Tags: 0.7.2-2
* Upload to unstable
* Fixed Vcs-* fields in debian/control
* Updated debian/watch
* Standards-Version bump to 3.9.5, no changes needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
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   *
9
 
 *                                                              *
10
 
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
11
 
 *                                                              *
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
 
 ****************************************************************/
19
 
 
20
 
package org.apache.james.mime4j.storage;
21
 
 
22
 
import java.io.BufferedInputStream;
23
 
import java.io.File;
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;
31
 
import java.util.Set;
32
 
 
33
 
/**
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>).
37
 
 * <p>
38
 
 * Example usage:
39
 
 *
40
 
 * <pre>
41
 
 * File directory = new File(&quot;/tmp/mime4j&quot;);
42
 
 * StorageProvider provider = new TempFileStorageProvider(directory);
43
 
 * DefaultStorageProvider.setInstance(provider);
44
 
 * </pre>
45
 
 */
46
 
public class TempFileStorageProvider extends AbstractStorageProvider {
47
 
 
48
 
    private static final String DEFAULT_PREFIX = "m4j";
49
 
 
50
 
    private final String prefix;
51
 
    private final String suffix;
52
 
    private final File directory;
53
 
 
54
 
    /**
55
 
     * Equivalent to using constructor
56
 
     * <code>TempFileStorageProvider("m4j", null, null)</code>.
57
 
     */
58
 
    public TempFileStorageProvider() {
59
 
        this(DEFAULT_PREFIX, null, null);
60
 
    }
61
 
 
62
 
    /**
63
 
     * Equivalent to using constructor
64
 
     * <code>TempFileStorageProvider("m4j", null, directory)</code>.
65
 
     */
66
 
    public TempFileStorageProvider(File directory) {
67
 
        this(DEFAULT_PREFIX, null, directory);
68
 
    }
69
 
 
70
 
    /**
71
 
     * Creates a new <code>TempFileStorageProvider</code> using the given
72
 
     * values.
73
 
     *
74
 
     * @param prefix
75
 
     *            prefix for generating the temporary file's name; must be at
76
 
     *            least three characters long.
77
 
     * @param suffix
78
 
     *            suffix for generating the temporary file's name; may be
79
 
     *            <code>null</code> to use the suffix <code>".tmp"</code>.
80
 
     * @param directory
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>).
89
 
     */
90
 
    public TempFileStorageProvider(String prefix, String suffix, File directory) {
91
 
        if (prefix == null || prefix.length() < 3)
92
 
            throw new IllegalArgumentException("invalid prefix");
93
 
 
94
 
        if (directory != null && !directory.isDirectory()
95
 
                && !directory.mkdirs())
96
 
            throw new IllegalArgumentException("invalid directory");
97
 
 
98
 
        this.prefix = prefix;
99
 
        this.suffix = suffix;
100
 
        this.directory = directory;
101
 
    }
102
 
 
103
 
    public StorageOutputStream createStorageOutputStream() throws IOException {
104
 
        File file = File.createTempFile(prefix, suffix, directory);
105
 
        file.deleteOnExit();
106
 
 
107
 
        return new TempFileStorageOutputStream(file);
108
 
    }
109
 
 
110
 
    private static final class TempFileStorageOutputStream extends
111
 
            StorageOutputStream {
112
 
        private File file;
113
 
        private OutputStream out;
114
 
 
115
 
        public TempFileStorageOutputStream(File file) throws IOException {
116
 
            this.file = file;
117
 
            this.out = new FileOutputStream(file);
118
 
        }
119
 
 
120
 
        @Override
121
 
        public void close() throws IOException {
122
 
            super.close();
123
 
            out.close();
124
 
        }
125
 
 
126
 
        @Override
127
 
        protected void write0(byte[] buffer, int offset, int length)
128
 
                throws IOException {
129
 
            out.write(buffer, offset, length);
130
 
        }
131
 
 
132
 
        @Override
133
 
        protected Storage toStorage0() throws IOException {
134
 
            // out has already been closed because toStorage calls close
135
 
            return new TempFileStorage(file);
136
 
        }
137
 
    }
138
 
 
139
 
    private static final class TempFileStorage implements Storage {
140
 
 
141
 
        private File file;
142
 
 
143
 
        private static final Set<File> filesToDelete = new HashSet<File>();
144
 
 
145
 
        public TempFileStorage(File file) {
146
 
            this.file = file;
147
 
        }
148
 
 
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.
154
 
 
155
 
            // a better but more complicated solution would be to start a
156
 
            // separate thread that tries to delete the files periodically.
157
 
 
158
 
            synchronized (filesToDelete) {
159
 
                if (file != null) {
160
 
                    filesToDelete.add(file);
161
 
                    file = null;
162
 
                }
163
 
 
164
 
                for (Iterator<File> iterator = filesToDelete.iterator(); iterator
165
 
                        .hasNext();) {
166
 
                    File file = iterator.next();
167
 
                    if (file.delete()) {
168
 
                        iterator.remove();
169
 
                    }
170
 
                }
171
 
            }
172
 
        }
173
 
 
174
 
        public InputStream getInputStream() throws IOException {
175
 
            if (file == null)
176
 
                throw new IllegalStateException("storage has been deleted");
177
 
 
178
 
            return new BufferedInputStream(new FileInputStream(file));
179
 
        }
180
 
 
181
 
    }
182
 
 
183
 
}