file i/o buffering
[mir.git] / source / mir / generator / tal / CachingFileLoader.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mir.generator.tal;
31
32 import java.io.BufferedInputStream;
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.FileNotFoundException;
36 import java.io.InputStream;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Vector;
41
42 public class CachingFileLoader {
43   private Map cachedObjects;
44   private List history;
45   private int capacity;
46   private CachedFileObjectFactory factory;
47
48   public CachingFileLoader(int aCapacity, CachedFileObjectFactory aFactory) {
49     capacity = aCapacity;
50     cachedObjects = new HashMap();
51     history = new Vector();
52     factory = aFactory;
53   }
54
55   private void cacheObject(String aFilename, long aLastModified, Object anObject) {
56     synchronized (this) {
57       history.remove(aFilename);
58       history.add(aFilename);
59       while (history.size()>capacity && history.size()>0) {
60         history.remove(0);
61       }
62       cachedObjects.put(aFilename, new CachedObject(aFilename, aLastModified, anObject));
63     }
64   }
65
66   private Object constructObject(String aFilename) throws FileNotFoundException {
67     File file = new File(aFilename);
68     BufferedInputStream inputStream = new BufferedInputStream(
69       new FileInputStream(file), 8192);
70     try {
71       Object result = factory.constructObject(inputStream);
72       cacheObject(aFilename, file.lastModified(), result);
73
74       return result;
75     }
76     finally {
77       try {
78         inputStream.close();
79       }
80       catch (Throwable t) {
81       }
82     }
83   }
84
85   private void revatilize(String aFilename) {
86     synchronized (this) {
87       history.remove(aFilename);
88       history.add(aFilename);
89     }
90   }
91
92   private class CachedObject {
93     private String filename;
94     private long lastModified;
95     private Object object;
96
97     public CachedObject(String aFilename, long aLastModified, Object anObject) {
98       filename = aFilename;
99       lastModified = aLastModified;
100       object = anObject;
101     }
102
103     public Object getObject() {
104       return object;
105     }
106
107     public String getFilename() {
108       return filename;
109     }
110
111     public long getLastModified() {
112       return lastModified;
113     }
114   }
115
116   public Object retrieveFile(String aFilename) throws FileNotFoundException {
117     synchronized (this) {
118       if (!cachedObjects.containsKey(aFilename)) {
119         return constructObject(aFilename);
120       }
121
122       CachedObject cachedObject = (CachedObject) cachedObjects.get(aFilename);
123       File file = new File(aFilename);
124       if (file.lastModified() != cachedObject.getLastModified()) {
125         return constructObject(aFilename);
126       }
127
128       revatilize(aFilename);
129
130       return cachedObject.getObject();
131     }
132   }
133
134   public interface CachedFileObjectFactory {
135     Object constructObject(InputStream aStream);
136   }
137 }