KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > mailrepository > MimeMessageJDBCSource


1 /***********************************************************************
2  * Copyright (c) 2000-2004 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.mailrepository;
19
20 import org.apache.avalon.cornerstone.services.store.StreamRepository;
21 import org.apache.james.core.MimeMessageSource;
22 import org.apache.james.util.JDBCUtil;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.SequenceInputStream JavaDoc;
28 import java.sql.Blob JavaDoc;
29 import java.sql.Connection JavaDoc;
30 import java.sql.PreparedStatement JavaDoc;
31 import java.sql.ResultSet JavaDoc;
32 import java.sql.SQLException JavaDoc;
33 import java.sql.Statement JavaDoc;
34
35 /**
36  * This class points to a specific message in a repository. This will return an
37  * InputStream to the JDBC field/record, possibly sequenced with the file stream.
38  */

39 public class MimeMessageJDBCSource extends MimeMessageSource {
40
41     /**
42      * Whether 'deep debugging' is turned on.
43      */

44     private static final boolean DEEP_DEBUG = false;
45
46     //Define how to get to the data
47
JDBCMailRepository repository = null;
48     String JavaDoc key = null;
49     StreamRepository sr = null;
50
51     private long size = -1;
52
53     /**
54      * SQL used to retrieve the message body
55      */

56     String JavaDoc retrieveMessageBodySQL = null;
57
58     /**
59      * SQL used to retrieve the size of the message body
60      */

61     String JavaDoc retrieveMessageBodySizeSQL = null;
62
63     /**
64      * The JDBCUtil helper class
65      */

66     private static final JDBCUtil theJDBCUtil =
67             new JDBCUtil() {
68                 protected void delegatedLog(String JavaDoc logString) {
69                     // No logging available at this point in the code.
70
// Therefore this is a noop method.
71
}
72             };
73
74     /**
75      * Construct a MimeMessageSource based on a JDBC repository, a key, and a
76      * stream repository (where we might store the message body)
77      */

78     public MimeMessageJDBCSource(JDBCMailRepository repository,
79             String JavaDoc key, StreamRepository sr) throws IOException JavaDoc {
80         if (repository == null) {
81             throw new IOException JavaDoc("Repository is null");
82         }
83         if (key == null) {
84             throw new IOException JavaDoc("Message name (key) was not defined");
85         }
86         this.repository = repository;
87         this.key = key;
88         this.sr = sr;
89
90         retrieveMessageBodySQL =
91             repository.sqlQueries.getSqlString("retrieveMessageBodySQL", true);
92         // this is optional
93
retrieveMessageBodySizeSQL =
94             repository.sqlQueries.getSqlString("retrieveMessageBodySizeSQL");
95     }
96
97     /**
98      * Returns a unique String ID that represents the location from where
99      * this source is loaded. This will be used to identify where the data
100      * is, primarily to avoid situations where this data would get overwritten.
101      *
102      * @return the String ID
103      */

104     public String JavaDoc getSourceId() {
105         StringBuffer JavaDoc sourceIdBuffer =
106             new StringBuffer JavaDoc(128)
107                     .append(repository.repositoryName)
108                     .append("/")
109                     .append(key);
110         return sourceIdBuffer.toString();
111     }
112
113     /**
114      * Return the input stream to the database field and then the file stream. This should
115      * be smart enough to work even if the file does not exist. This is to support
116      * a repository with the entire message in the database, which is how James 1.2 worked.
117      */

118     public synchronized InputStream JavaDoc getInputStream() throws IOException JavaDoc {
119         Connection JavaDoc conn = null;
120         PreparedStatement JavaDoc retrieveMessageStream = null;
121         ResultSet JavaDoc rsRetrieveMessageStream = null;
122         try {
123             conn = repository.getConnection();
124
125             byte[] headers = null;
126
127             long start = 0;
128             if (DEEP_DEBUG) {
129                 start = System.currentTimeMillis();
130                 System.out.println("starting");
131             }
132             retrieveMessageStream = conn.prepareStatement(retrieveMessageBodySQL);
133             retrieveMessageStream.setString(1, key);
134             retrieveMessageStream.setString(2, repository.repositoryName);
135             rsRetrieveMessageStream = retrieveMessageStream.executeQuery();
136
137             if (!rsRetrieveMessageStream.next()) {
138                 throw new IOException JavaDoc("Could not find message");
139             }
140
141             String JavaDoc getBodyOption = repository.sqlQueries.getDbOption("getBody");
142             if (getBodyOption != null && getBodyOption.equalsIgnoreCase("useBlob")) {
143                 Blob JavaDoc b = rsRetrieveMessageStream.getBlob(1);
144                 headers = b.getBytes(1, (int)b.length());
145             } else {
146                 headers = rsRetrieveMessageStream.getBytes(1);
147             }
148             if (DEEP_DEBUG) {
149                 System.err.println("stopping");
150                 System.err.println(System.currentTimeMillis() - start);
151             }
152
153             InputStream JavaDoc in = new ByteArrayInputStream JavaDoc(headers);
154             try {
155                 if (sr != null) {
156                     in = new SequenceInputStream JavaDoc(in, sr.get(key));
157                 }
158             } catch (Exception JavaDoc e) {
159                 //ignore this... either sr is null, or the file does not exist
160
// or something else
161
}
162             return in;
163         } catch (SQLException JavaDoc sqle) {
164             throw new IOException JavaDoc(sqle.toString());
165         } finally {
166             theJDBCUtil.closeJDBCResultSet(rsRetrieveMessageStream);
167             theJDBCUtil.closeJDBCStatement(retrieveMessageStream);
168             theJDBCUtil.closeJDBCConnection(conn);
169         }
170     }
171
172     /**
173      * Runs a custom SQL statement to check the size of the message body
174      */

175     public synchronized long getMessageSize() throws IOException JavaDoc {
176         if (size != -1) return size;
177         if (retrieveMessageBodySizeSQL == null) {
178             //There was no SQL statement for this repository... figure it out the hard way
179
System.err.println("no SQL statement to find size");
180             return size = super.getMessageSize();
181         }
182         Connection JavaDoc conn = null;
183         PreparedStatement JavaDoc retrieveMessageSize = null;
184         ResultSet JavaDoc rsRetrieveMessageSize = null;
185         try {
186             conn = repository.getConnection();
187
188             retrieveMessageSize = conn.prepareStatement(retrieveMessageBodySizeSQL);
189             retrieveMessageSize.setString(1, key);
190             retrieveMessageSize.setString(2, repository.repositoryName);
191             rsRetrieveMessageSize = retrieveMessageSize.executeQuery();
192
193             if (!rsRetrieveMessageSize.next()) {
194                 throw new IOException JavaDoc("Could not find message");
195             }
196
197             size = rsRetrieveMessageSize.getLong(1);
198
199             InputStream JavaDoc in = null;
200             try {
201                 if (sr != null) {
202                     if (sr instanceof org.apache.james.mailrepository.filepair.File_Persistent_Stream_Repository) {
203                         size += ((org.apache.james.mailrepository.filepair.File_Persistent_Stream_Repository) sr).getSize(key);
204                     } else {
205                         in = sr.get(key);
206                         int len = 0;
207                         byte[] block = new byte[1024];
208                         while ((len = in.read(block)) > -1) {
209                             size += len;
210                         }
211                     }
212                 }
213             } catch (Exception JavaDoc e) {
214                 //ignore this... either sr is null, or the file does not exist
215
// or something else
216
} finally {
217                 try {
218                     if (in != null) {
219                         in.close();
220                     }
221                 } catch (IOException JavaDoc ioe) {
222                     // Ignored - no access to logger at this point in the code
223
}
224             }
225             
226             return size;
227         } catch (SQLException JavaDoc sqle) {
228             throw new IOException JavaDoc(sqle.toString());
229         } finally {
230             theJDBCUtil.closeJDBCResultSet(rsRetrieveMessageSize);
231             theJDBCUtil.closeJDBCStatement(retrieveMessageSize);
232             theJDBCUtil.closeJDBCConnection(conn);
233         }
234     }
235
236     /**
237      * Check to see whether this is the same repository and the same key
238      */

239     public boolean equals(Object JavaDoc obj) {
240         if (obj instanceof MimeMessageJDBCSource) {
241             // TODO: Figure out whether other instance variables should be part of
242
// the equals equation
243
MimeMessageJDBCSource source = (MimeMessageJDBCSource)obj;
244             return ((source.key == key) || ((source.key != null) && source.key.equals(key))) &&
245                    ((source.repository == repository) || ((source.repository != null) && source.repository.equals(repository)));
246         }
247         return false;
248     }
249
250     /**
251      * Provide a hash code that is consistent with equals for this class
252      *
253      * @return the hash code
254      */

255      public int hashCode() {
256         int result = 17;
257         if (key != null) {
258             result = 37 * key.hashCode();
259         }
260         if (repository != null) {
261             result = 37 * repository.hashCode();
262         }
263         return result;
264      }
265 }
266
Popular Tags