View Javadoc

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  
21  
22  package org.apache.james.core;
23  
24  import javax.mail.MessagingException;
25  import javax.mail.util.SharedFileInputStream;
26  
27  import java.io.BufferedOutputStream;
28  import java.io.File;
29  import java.io.FileOutputStream;
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.io.OutputStream;
33  
34  import org.apache.avalon.framework.activity.Disposable;
35  
36  /**
37   * Takes an input stream and creates a repeatable input stream source
38   * for a MimeMessageWrapper.  It does this by completely reading the
39   * input stream and saving that to a temporary file that should delete on exit,
40   * or when this object is GC'd.
41   *
42   * @see MimeMessageWrapper
43   *
44   *
45   */
46  public class MimeMessageInputStreamSource
47      extends MimeMessageSource
48      implements Disposable {
49  
50      /**
51       * A temporary file used to hold the message stream
52       */
53      File file;
54  
55      /**
56       * The full path of the temporary file
57       */
58      String sourceId;
59  
60      /**
61       * Construct a new MimeMessageInputStreamSource from an
62       * <code>InputStream</code> that contains the bytes of a
63       * MimeMessage.
64       *
65       * @param key the prefix for the name of the temp file
66       * @param in the stream containing the MimeMessage
67       *
68       * @throws MessagingException if an error occurs while trying to store
69       *                            the stream
70       */
71      public MimeMessageInputStreamSource(String key, InputStream in)
72              throws MessagingException {
73          //We want to immediately read this into a temporary file
74          //Create a temp file and channel the input stream into it
75          OutputStream fout = null;
76          try {
77              file = File.createTempFile(key, ".m64");
78              fout = new BufferedOutputStream(new FileOutputStream(file));
79              int b = -1;
80              while ((b = in.read()) != -1) {
81                  fout.write(b);
82              }
83              fout.flush();
84  
85              sourceId = file.getCanonicalPath();
86          } catch (IOException ioe) {
87              throw new MessagingException("Unable to retrieve the data: " + ioe.getMessage(), ioe);
88          } finally {
89              try {
90                  if (fout != null) {
91                      fout.close();
92                  }
93              } catch (IOException ioe) {
94                  // Ignored - logging unavailable to log this non-fatal error.
95              }
96  
97              try {
98                  if (in != null) {
99                      in.close();
100                 }
101             } catch (IOException ioe) {
102                 // Ignored - logging unavailable to log this non-fatal error.
103             }
104             
105             // if sourceId is null while file is not null then we had
106             // an IOxception and we have to clean the file.
107             if (sourceId == null && file != null) {
108                 file.delete();
109             }
110         }
111     }
112 
113     /**
114      * Returns the unique identifier of this input stream source
115      *
116      * @return the unique identifier for this MimeMessageInputStreamSource
117      */
118     public String getSourceId() {
119         return sourceId;
120     }
121 
122     /**
123      * Get an input stream to retrieve the data stored in the temporary file
124      *
125      * @return a <code>BufferedInputStream</code> containing the data
126      */
127     public synchronized InputStream getInputStream() throws IOException {
128         return new SharedFileInputStream(file);
129     }
130 
131     /**
132      * Get the size of the temp file
133      *
134      * @return the size of the temp file
135      *
136      * @throws IOException if an error is encoutered while computing the size of the message
137      */
138     public long getMessageSize() throws IOException {
139         return file.length();
140     }
141 
142     /**
143      * @see org.apache.avalon.framework.activity.Disposable#dispose()
144      */
145     public void dispose() {
146         try {
147             if (file != null && file.exists()) {
148                 file.delete();
149             }
150         } catch (Exception e) {
151             //ignore
152         }
153         file = null;
154     }
155 
156 }