View Javadoc

1   /************************************************************************
2    * Copyright (c) 2000-2006 The Apache Software Foundation.             *
3    * All rights reserved.                                                *
4    * ------------------------------------------------------------------- *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you *
6    * may not use this file except in compliance with the License. You    *
7    * may obtain a copy of the License at:                                *
8    *                                                                     *
9    *     http://www.apache.org/licenses/LICENSE-2.0                      *
10   *                                                                     *
11   * Unless required by applicable law or agreed to in writing, software *
12   * distributed under the License is distributed on an "AS IS" BASIS,   *
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
14   * implied.  See the License for the specific language governing       *
15   * permissions and limitations under the License.                      *
16   ***********************************************************************/
17  
18  package org.apache.james.core;
19  
20  import javax.mail.MessagingException;
21  import javax.mail.util.SharedFileInputStream;
22  
23  import java.io.BufferedOutputStream;
24  import java.io.File;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.OutputStream;
29  
30  import org.apache.avalon.framework.activity.Disposable;
31  
32  /***
33   * Takes an input stream and creates a repeatable input stream source
34   * for a MimeMessageWrapper.  It does this by completely reading the
35   * input stream and saving that to a temporary file that should delete on exit,
36   * or when this object is GC'd.
37   *
38   * @see MimeMessageWrapper
39   *
40   *
41   */
42  public class MimeMessageInputStreamSource
43      extends MimeMessageSource
44      implements Disposable {
45  
46      /***
47       * A temporary file used to hold the message stream
48       */
49      File file;
50  
51      /***
52       * The full path of the temporary file
53       */
54      String sourceId;
55  
56      /***
57       * Construct a new MimeMessageInputStreamSource from an
58       * <code>InputStream</code> that contains the bytes of a
59       * MimeMessage.
60       *
61       * @param key the prefix for the name of the temp file
62       * @param in the stream containing the MimeMessage
63       *
64       * @throws MessagingException if an error occurs while trying to store
65       *                            the stream
66       */
67      public MimeMessageInputStreamSource(String key, InputStream in)
68              throws MessagingException {
69          //We want to immediately read this into a temporary file
70          //Create a temp file and channel the input stream into it
71          OutputStream fout = null;
72          try {
73              file = File.createTempFile(key, ".m64");
74              fout = new BufferedOutputStream(new FileOutputStream(file));
75              int b = -1;
76              while ((b = in.read()) != -1) {
77                  fout.write(b);
78              }
79              fout.flush();
80  
81              sourceId = file.getCanonicalPath();
82          } catch (IOException ioe) {
83              // We had an IOException preparing the temporary file, so
84              // don't just leave it around to garbage collect later.
85              // It isn't as if we are going to use it after we throw
86              // the MessagingException.
87              if (fout != null) try {
88                  fout.close();
89                  fout = null;
90              } catch (IOException _) {
91                  // Ignored - logging unavailable to log this error.
92              }
93  
94              if (file != null) {
95                  file.delete();
96                  file = null;
97              }
98  
99              throw new MessagingException("Unable to retrieve the data: " + ioe.getMessage(), ioe);
100         } finally {
101             try {
102                 if (fout != null) {
103                     fout.close();
104                 }
105             } catch (IOException ioe) {
106                 // Ignored - logging unavailable to log this non-fatal error.
107             }
108 
109             try {
110                 if (in != null) {
111                     in.close();
112                 }
113             } catch (IOException ioe) {
114                 // Ignored - logging unavailable to log this non-fatal error.
115             }
116         }
117     }
118 
119     /***
120      * Returns the unique identifier of this input stream source
121      *
122      * @return the unique identifier for this MimeMessageInputStreamSource
123      */
124     public String getSourceId() {
125         return sourceId;
126     }
127 
128     /***
129      * Get an input stream to retrieve the data stored in the temporary file
130      *
131      * @return a <code>BufferedInputStream</code> containing the data
132      */
133     public synchronized InputStream getInputStream() throws IOException {
134         return new SharedFileInputStream(file);
135     }
136 
137     /***
138      * Get the size of the temp file
139      *
140      * @return the size of the temp file
141      *
142      * @throws IOException if an error is encoutered while computing the size of the message
143      */
144     public long getMessageSize() throws IOException {
145         return file.length();
146     }
147 
148     /***
149      * @see org.apache.avalon.framework.activity.Disposable#dispose()
150      */
151     public void dispose() {
152         try {
153             if (file != null && file.exists()) {
154                 file.delete();
155             }
156         } catch (Exception e) {
157             //ignore
158         }
159         file = null;
160     }
161 
162     /***
163      * <p>Finalizer that closes and deletes the temp file.  Very bad.</p>
164      * We're leaving this in temporarily, while also establishing a more
165      * formal mechanism for cleanup through use of the dispose() method.
166      * @throws Throwable 
167      *
168     public void finalize() throws Throwable {
169         dispose();
170         super.finalize();
171     }
172      */
173 }