KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > headercache > BerkeleyDBHeaderList


1 // The contents of this file are subject to the Mozilla Public License Version
2
// 1.1
3
//(the "License"); you may not use this file except in compliance with the
4
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
5
//
6
//Software distributed under the License is distributed on an "AS IS" basis,
7
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
8
//for the specific language governing rights and
9
//limitations under the License.
10
//
11
//The Original Code is "The Columba Project"
12
//
13
//The Initial Developers of the Original Code are Frederik Dietz and Timo
14
// Stich.
15
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
16
//
17
//All Rights Reserved.
18
package org.columba.mail.folder.headercache;
19
20 import java.io.File JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27
28 import org.columba.mail.config.MailConfig;
29 import org.columba.mail.folder.IHeaderListCorruptedListener;
30 import org.columba.mail.message.ICloseableIterator;
31 import org.columba.mail.message.IColumbaHeader;
32 import org.columba.mail.message.IPersistantHeaderList;
33
34 import com.sleepycat.bind.tuple.IntegerBinding;
35 import com.sleepycat.bind.tuple.StringBinding;
36 import com.sleepycat.bind.tuple.TupleBinding;
37 import com.sleepycat.collections.StoredIterator;
38 import com.sleepycat.collections.StoredKeySet;
39 import com.sleepycat.collections.StoredValueSet;
40 import com.sleepycat.je.BtreeStats;
41 import com.sleepycat.je.Database;
42 import com.sleepycat.je.DatabaseConfig;
43 import com.sleepycat.je.DatabaseEntry;
44 import com.sleepycat.je.DatabaseException;
45 import com.sleepycat.je.Environment;
46 import com.sleepycat.je.EnvironmentConfig;
47 import com.sleepycat.je.LockMode;
48 import com.sleepycat.je.OperationStatus;
49
50 public class BerkeleyDBHeaderList implements IPersistantHeaderList {
51
52     /** JDK 1.4+ logging framework logger, used for logging. */
53     private static final Logger JavaDoc LOG = Logger
54             .getLogger("org.columba.mail.folder.headercache");
55     
56     
57     private String JavaDoc name;
58     private File JavaDoc headercacheDirectory;
59     private Database db;
60     private static Environment environment;
61     private DatabaseConfig databaseConfig;
62     
63     private TupleBinding headerBinding;
64     private TupleBinding integerBinding;
65     private TupleBinding stringBinding;
66     
67     private Class JavaDoc keyType = Integer JavaDoc.class;
68     
69     private List JavaDoc listeners;
70     
71     private static int openDatabases = 0;
72     
73     public BerkeleyDBHeaderList(File JavaDoc headerCacheDirectory, String JavaDoc name){
74         this(headerCacheDirectory, name, new DefaultHeaderBinding());
75     }
76
77     
78     public BerkeleyDBHeaderList(File JavaDoc headerCacheDirectory, String JavaDoc name, TupleBinding headerBinding){
79         super();
80         this.name = name;
81         this.headerBinding = headerBinding;
82         this.headercacheDirectory = headerCacheDirectory;
83         
84         integerBinding = new IntegerBinding();
85         stringBinding = new StringBinding();
86         
87         listeners = new ArrayList JavaDoc();
88     }
89
90     private synchronized void openEnvironment() throws DatabaseException {
91         if( environment != null) return;
92         if( !headercacheDirectory.exists()) headercacheDirectory.mkdir();
93         
94         EnvironmentConfig environmentConfig = new EnvironmentConfig();
95         environmentConfig.setAllowCreate(true);
96         environmentConfig.setCachePercent(80);
97         // perform other environment configurations
98
try {
99             environment = new Environment(headercacheDirectory, environmentConfig);
100         } catch (DatabaseException e) {
101             LOG.severe(e.getMessage());
102             fireHeaderListCorrupted();
103             throw e;
104         }
105         
106         
107     }
108     
109     private synchronized void openDatabase() throws DatabaseException{
110         if( db != null ) return;
111         openEnvironment();
112         try {
113             databaseConfig = new DatabaseConfig();
114             databaseConfig.setAllowCreate(true);
115             // perform other database configurations
116
db = environment.openDatabase(null, name , databaseConfig);
117             
118             openDatabases++;
119         } catch (DatabaseException e) {
120             LOG.severe(e.getMessage());
121             fireHeaderListCorrupted();
122             throw e;
123         }
124     }
125
126     /* (non-Javadoc)
127      * @see org.columba.mail.folder.headercache.HeaderList#add(org.columba.mail.message.IColumbaHeader, java.lang.Object)
128      */

129     public void add(IColumbaHeader header, Object JavaDoc uid) {
130         try {
131             openDatabase();
132             header.getAttributes().put("columba.uid", uid);
133             
134             db.put(null, getDatabaseEntry(uid), getDatabaseEntry(header));
135         } catch (DatabaseException e) {
136             LOG.severe(e.getMessage());
137             fireHeaderListCorrupted();
138         }
139     }
140
141     private DatabaseEntry getDatabaseEntry(Object JavaDoc in) {
142         DatabaseEntry result = new DatabaseEntry();
143
144         if( in instanceof String JavaDoc) {
145             stringBinding.objectToEntry( in, result);
146         } else if( in instanceof Integer JavaDoc) {
147             integerBinding.objectToEntry(in, result);
148         } else if( in instanceof IColumbaHeader) {
149             headerBinding.objectToEntry(in, result);
150         }
151         
152         return result;
153     }
154
155
156     /* (non-Javadoc)
157      * @see org.columba.mail.folder.headercache.HeaderList#clear()
158      */

159     public void clear() {
160         closeDatabase();
161         
162         try {
163             environment.truncateDatabase(null, name, true);
164         } catch (DatabaseException e) {
165             LOG.warning(e.getMessage());
166         }
167     }
168
169     private void closeEnvironment() {
170         if( db != null) closeDatabase();
171         
172         try {
173             if( environment != null ) {
174                 environment.close();
175                 environment = null;
176             }
177         } catch (DatabaseException e) {
178             LOG.warning(e.getMessage());
179         }
180         
181     }
182     
183     private void closeDatabase() {
184         try {
185             if( db != null ) {
186                 openDatabases--;
187                 db.close();
188                 db = null;
189             }
190
191         } catch (DatabaseException e) {
192             LOG.warning(e.getMessage());
193         }
194         
195         if( openDatabases == 0 ) {
196             closeEnvironment();
197         }
198             
199     }
200
201     /* (non-Javadoc)
202      * @see org.columba.mail.folder.headercache.HeaderList#containsValue(java.lang.Object)
203      */

204     public boolean exists(Object JavaDoc uid) {
205         try {
206             openDatabase();
207             return db.get(null, getDatabaseEntry(uid), new DatabaseEntry(), LockMode.DEFAULT).equals(OperationStatus.SUCCESS);
208         } catch (DatabaseException e) {
209             LOG.fine(e.getMessage());
210             return false;
211         }
212     }
213
214     /* (non-Javadoc)
215      * @see org.columba.mail.folder.headercache.HeaderList#count()
216      */

217     public int count() {
218
219         try {
220             openDatabase();
221             return (int) ((BtreeStats)db.getStats(null)).getLeafNodeCount();
222         } catch (DatabaseException e) {
223             LOG.severe(e.getMessage());
224             fireHeaderListCorrupted();
225             
226             return 0;
227         }
228     }
229
230     /* (non-Javadoc)
231      * @see org.columba.mail.folder.headercache.HeaderList#get(java.lang.Object)
232      */

233     public IColumbaHeader get(Object JavaDoc uid) {
234         
235         DatabaseEntry result = new DatabaseEntry();
236         try {
237             openDatabase();
238             OperationStatus status = db.get(null, getDatabaseEntry(uid), result, LockMode.DEFAULT);
239             if( status.equals(OperationStatus.SUCCESS) ) {
240                 return (IColumbaHeader)headerBinding.entryToObject(result);
241             }
242         } catch (DatabaseException e) {
243             LOG.severe(e.getMessage());
244         }
245         return null;
246     }
247
248
249     /* (non-Javadoc)
250      * @see org.columba.mail.folder.headercache.HeaderList#getUids()
251      */

252     public Object JavaDoc[] getUids() {
253         try {
254             openDatabase();
255             return keySet().toArray();
256         } catch (DatabaseException e) {
257             LOG.severe(e.getMessage());
258             return new Object JavaDoc[0];
259         }
260     }
261
262     /* (non-Javadoc)
263      * @see org.columba.mail.folder.headercache.HeaderList#keySet()
264      */

265     public Set JavaDoc keySet() {
266         try {
267             openDatabase();
268         } catch (DatabaseException e) {
269             LOG.severe(e.getMessage());
270             return new HashSet JavaDoc();
271         }
272         
273         if( keyType == Integer JavaDoc.class ) {
274             return new StoredKeySet(db, integerBinding, false);
275         } else if( keyType == String JavaDoc.class) {
276             return new StoredKeySet(db, stringBinding, false);
277         }
278         
279         throw new IllegalArgumentException JavaDoc("keyType not implemented!");
280     }
281
282     /* (non-Javadoc)
283      * @see org.columba.mail.folder.headercache.HeaderList#remove(java.lang.Object)
284      */

285     public IColumbaHeader remove(Object JavaDoc uid) {
286         try {
287             openDatabase();
288             
289             IColumbaHeader header = get(uid);
290             db.delete(null, getDatabaseEntry(uid));
291
292             return header;
293         } catch (DatabaseException e) {
294             LOG.severe(e.getMessage());
295
296             return null;
297         }
298         
299     }
300
301     /* (non-Javadoc)
302      * @see org.columba.mail.folder.headercache.PersistantHeaderList#persist()
303      */

304     public void persist() throws IOException JavaDoc {
305         closeDatabase();
306     }
307
308     /* (non-Javadoc)
309      * @see org.columba.mail.folder.headercache.HeaderList#headerIterator()
310      */

311     public ICloseableIterator headerIterator() {
312         try {
313             openDatabase();
314         } catch (DatabaseException e) {
315             LOG.severe(e.getMessage());
316             throw new RuntimeException JavaDoc(e);
317         }
318         return new BerkeleyDBIterator( (StoredIterator)new StoredValueSet(db,headerBinding, false).iterator());
319     }
320
321     /* (non-Javadoc)
322      * @see org.columba.mail.folder.headercache.HeaderList#keyIterator()
323      */

324     public ICloseableIterator keyIterator() {
325         try {
326             openDatabase();
327         } catch (DatabaseException e) {
328             LOG.severe(e.getMessage());
329             throw new RuntimeException JavaDoc(e);
330         }
331         return new BerkeleyDBIterator( (StoredIterator)new StoredKeySet(db, integerBinding, false).iterator());
332     }
333
334     /* (non-Javadoc)
335      * @see org.columba.mail.folder.headercache.HeaderList#update(java.lang.Object, org.columba.mail.message.IColumbaHeader)
336      */

337     public void update(Object JavaDoc uid, IColumbaHeader header) {
338         try {
339             openDatabase();
340         } catch (DatabaseException e) {
341             LOG.severe(e.getMessage());
342             throw new RuntimeException JavaDoc(e);
343         }
344         DatabaseEntry key = getDatabaseEntry(uid);
345         
346         try {
347             db.delete(null, key);
348             db.put(null, key, getDatabaseEntry(header));
349         } catch (DatabaseException e) {
350             LOG.severe(e.getMessage());
351             fireHeaderListCorrupted();
352         }
353     }
354
355     /**
356      * @param headerBinding The headerBinding to set.
357      */

358     public void setHeaderBinding(TupleBinding headerBinding) {
359         this.headerBinding = headerBinding;
360     }
361
362
363     /**
364      * @return Returns the keyType.
365      */

366     public Class JavaDoc getKeyType() {
367         return keyType;
368     }
369
370
371     /**
372      * @param keyType The keyType to set.
373      */

374     public void setKeyType(Class JavaDoc keyType) {
375         this.keyType = keyType;
376     }
377     
378     private void fireHeaderListCorrupted() {
379         for( int i=0; i<listeners.size(); i++) {
380             ((IHeaderListCorruptedListener)listeners.get(i)).headerListCorrupted(this);
381         }
382     }
383
384
385     public void addHeaderListCorruptedListener(IHeaderListCorruptedListener listener) {
386         listeners.add(listener);
387     }
388     
389     public void removeHeaderListCorruptedListener(IHeaderListCorruptedListener listener) {
390         listeners.remove(listener);
391     }
392 }
393
Popular Tags