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 }