001: package org.bouncycastle.mail.smime.util;
002:
003: import javax.mail.MessagingException;
004: import javax.mail.internet.InternetHeaders;
005: import javax.mail.internet.MimeBodyPart;
006: import java.io.File;
007: import java.io.FileOutputStream;
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.io.OutputStream;
011: import java.util.Enumeration;
012:
013: public class FileBackedMimeBodyPart extends MimeBodyPart {
014: private static final int BUF_SIZE = 32760;
015:
016: private final File _file;
017:
018: /**
019: * Create a MimeBodyPart backed by the data in file.
020: *
021: * @param file file containing the body part.
022: * @throws MessagingException an exception occurs parsing file.
023: * @throws IOException an exception occurs accessing file.
024: */
025: public FileBackedMimeBodyPart(File file) throws MessagingException,
026: IOException {
027: super (new SharedFileInputStream(file));
028:
029: _file = file;
030: }
031:
032: /**
033: * Create a MimeBodyPart backed by file based on the headers and
034: * content data in content.
035: *
036: * @param content an inputstream containing the body part.
037: * @param file a handle to the backing file to use for storage.
038: * @throws MessagingException an exception occurs parsing the resulting body part in file.
039: * @throws IOException an exception occurs accessing file or content.
040: */
041: public FileBackedMimeBodyPart(InputStream content, File file)
042: throws MessagingException, IOException {
043: this (saveStreamToFile(content, file));
044: }
045:
046: /**
047: * Create a MimeBodyPart backed by file, with the headers
048: * given in headers and body content taken from the stream body.
049: *
050: * @param headers headers for the body part.
051: * @param body internal content for the body part.
052: * @param file backing file to use.
053: *
054: * @throws MessagingException if the body part can't be produced.
055: * @throws IOException if there is an issue reading stream or writing to file.
056: */
057: public FileBackedMimeBodyPart(InternetHeaders headers,
058: InputStream body, File file) throws MessagingException,
059: IOException {
060: this (saveStreamToFile(headers, body, file));
061: }
062:
063: public void writeTo(OutputStream out) throws IOException,
064: MessagingException {
065: if (!_file.exists()) {
066: throw new IOException("file " + _file.getCanonicalPath()
067: + " no longer exists.");
068: }
069:
070: super .writeTo(out);
071: }
072:
073: /**
074: * Close off the underlying shared streams and remove the backing file.
075: *
076: * @throws IOException if streams cannot be closed or the file cannot be deleted.
077: */
078: public void dispose() throws IOException {
079: ((SharedFileInputStream) contentStream).getRoot().dispose();
080:
081: if (!_file.delete()) {
082: throw new IOException("deletion of underlying file <"
083: + _file.getCanonicalPath() + "> failed.");
084: }
085: }
086:
087: private static File saveStreamToFile(InputStream content,
088: File tempFile) throws IOException {
089: saveContentToStream(new FileOutputStream(tempFile), content);
090:
091: return tempFile;
092: }
093:
094: private static File saveStreamToFile(InternetHeaders headers,
095: InputStream content, File tempFile) throws IOException {
096: OutputStream out = new FileOutputStream(tempFile);
097: Enumeration en = headers.getAllHeaderLines();
098:
099: while (en.hasMoreElements()) {
100: writeHeader(out, (String) en.nextElement());
101: }
102:
103: writeSeperator(out);
104:
105: saveContentToStream(out, content);
106:
107: return tempFile;
108: }
109:
110: private static void writeHeader(OutputStream out, String header)
111: throws IOException {
112: for (int i = 0; i != header.length(); i++) {
113: out.write(header.charAt(i));
114: }
115:
116: writeSeperator(out);
117: }
118:
119: private static void writeSeperator(OutputStream out)
120: throws IOException {
121: out.write('\r');
122: out.write('\n');
123: }
124:
125: private static void saveContentToStream(OutputStream out,
126: InputStream content) throws IOException {
127: byte[] buf = new byte[BUF_SIZE];
128: int len;
129:
130: while ((len = content.read(buf, 0, buf.length)) > 0) {
131: out.write(buf, 0, len);
132: }
133:
134: out.close();
135: content.close();
136: }
137: }
|