KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > TagFileManager


1 /*
2  * TagFileManager.java
3  *
4  * Copyright (C) 1998-2003 Peter Graves
5  * $Id: TagFileManager.java,v 1.3 2003/06/29 00:19:34 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.BufferedWriter JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.io.OutputStreamWriter JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.Comparator JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Vector JavaDoc;
35
36 public final class TagFileManager extends Thread JavaDoc
37 {
38     // Version of tag file format.
39
private static final String JavaDoc VERSION = "1";
40
41     private final File tagFileDir;
42     private final TagFileCatalog catalog;
43
44     private Vector JavaDoc queue = new Vector JavaDoc();
45     private boolean enabled = true;
46
47     private TagFileCache cache;
48
49     public TagFileManager()
50     {
51         super("tag file manager");
52         setPriority(Thread.MIN_PRIORITY);
53         setDaemon(true);
54         tagFileDir =
55             File.getInstance(Directories.getEditorDirectory(), "tagfiles");
56         catalog = new TagFileCatalog(tagFileDir);
57         if (initialize())
58             start();
59     }
60
61     public void run()
62     {
63         while (true) {
64             QueueEntry entry = getEntryFromQueue();
65             refreshTagFile(entry);
66         }
67     }
68
69     private synchronized boolean initialize()
70     {
71         if (!tagFileDir.isDirectory()) {
72             tagFileDir.mkdirs();
73             if (!tagFileDir.isDirectory()) {
74                 Log.error("TagFileManager.run can't make directory ".concat(tagFileDir.canonicalPath()));
75                 queue = null;
76                 return false;
77             }
78         }
79         catalog.load();
80         cleanup();
81         return true;
82     }
83
84     public synchronized void addToQueue(File dir, Mode mode)
85     {
86         if (queue == null)
87             return;
88         if (dir.isRemote())
89             return;
90         QueueEntry entry = new QueueEntry(dir, mode);
91         for (int i = queue.size()-1; i >= 0; i--) {
92             if (entry.equals(queue.get(i)))
93                 return;
94         }
95         queue.add(entry);
96         notify();
97     }
98
99     public synchronized void setEnabled(boolean b)
100     {
101         boolean wasEnabled = enabled;
102         enabled = b;
103         if (enabled && !wasEnabled)
104             notify();
105     }
106
107     private boolean ready()
108     {
109         return enabled && queue.size() > 0;
110     }
111
112     private synchronized QueueEntry getEntryFromQueue()
113     {
114         while (!ready()) {
115             try {
116                 wait();
117             }
118             catch (InterruptedException JavaDoc e) {
119                 Log.error(e);
120             }
121         }
122         return (QueueEntry) queue.remove(0);
123     }
124
125     private final File getTagFile(File dir, Mode mode)
126     {
127         return catalog.getTagFile(dir, mode);
128     }
129
130     public void makeTagFile(File dir, Mode mode)
131     {
132         Debug.assertTrue(mode != null);
133         try {
134             if (dir.isRemote())
135                 return;
136             File oldTagfile = getTagFile(dir, mode);
137             File tagfile = Utilities.getTempFile(tagFileDir);
138             if (tagfile != null) {
139                 String JavaDoc[] files = dir.list();
140                 if (files != null) {
141                     BufferedWriter JavaDoc writer =
142                         new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(
143                             tagfile.getOutputStream()));
144                     writer.write(VERSION);
145                     writer.write('\n');
146                     for (int i = 0; i < files.length; i++) {
147                         File file = File.getInstance(dir, files[i]);
148                         if (mode.accepts(file.getName()) && file.isFile()) {
149                             SystemBuffer buf = new SystemBuffer(file);
150                             buf.load();
151                             Tagger tagger = mode.getTagger(buf);
152                             tagger.run();
153                             tagger.writeTags(writer);
154                             buf._empty();
155                         }
156                     }
157                     writer.flush();
158                     writer.close();
159                     if (tagfile.length() == 0) {
160                         tagfile.delete();
161                     } else {
162                         catalog.addEntry(dir, tagfile, mode);
163                         catalog.save();
164                         if (oldTagfile != null) {
165                             oldTagfile.delete();
166                             if (cache != null)
167                                 cache.remove(oldTagfile);
168                         }
169                     }
170                 }
171             }
172         }
173         catch (Exception JavaDoc e) {
174             Log.error(e);
175         }
176     }
177
178     private boolean isTagFileOutOfDate(QueueEntry entry)
179     {
180         if (entry.directory.isRemote())
181             return false;
182         File tagfile = getTagFile(entry.directory, entry.mode);
183         if (tagfile == null)
184             return true;
185         if (!tagfile.exists())
186             return true;
187         long tagfileLastModified = tagfile.lastModified();
188         String JavaDoc[] files = entry.directory.list();
189         if (files != null) {
190             for (int i = 0; i < files.length; i++) {
191                 File file = File.getInstance(entry.directory, files[i]);
192                 if (!file.isFile())
193                     continue;
194                 if (entry.mode.accepts(file.getName()))
195                     if (file.lastModified() > tagfileLastModified)
196                         return true;
197             }
198         }
199         return false;
200     }
201
202     private void refreshTagFile(QueueEntry queueEntry)
203     {
204         if (isTagFileOutOfDate(queueEntry))
205             makeTagFile(queueEntry.directory, queueEntry.mode);
206     }
207
208     private synchronized void cleanup()
209     {
210         final int days = 5;
211         final long cutoff = System.currentTimeMillis() - 24 * 60 * 60 * 1000 * days;
212         String JavaDoc[] files = tagFileDir.list();
213         for (int i = 0; i < files.length; i++) {
214             String JavaDoc name = files[i];
215             if (name.equals("catalog")) {
216                 // It's the catalog file.
217
continue;
218             }
219             File file = File.getInstance(tagFileDir, name);
220             if (!file.isFile())
221                 continue;
222             if (catalog.containsTagFileName(name) && file.lastModified() > cutoff)
223                 continue;
224             file.delete();
225         }
226         catalog.update();
227     }
228
229     public List JavaDoc getTags(File directory, Mode mode)
230     {
231         File tagFile = getTagFile(directory, mode);
232         if (tagFile == null) {
233             Log.debug("getTags no tag file " + directory + " " + mode);
234             return null;
235         }
236         if (!tagFile.isFile()) {
237             Log.debug("getTags tag file doesn't exist");
238             return null;
239         }
240         List JavaDoc tags = null;
241         // First checked cached tag files.
242
if (cache != null)
243             tags = cache.getTags(tagFile);
244         if (tags == null) {
245             try {
246                 BufferedReader JavaDoc reader =
247                     new BufferedReader JavaDoc(new InputStreamReader JavaDoc(tagFile.getInputStream()));
248                 String JavaDoc s = reader.readLine();
249                 if (s != null && s.equals(VERSION)) {
250                     tags = new ArrayList JavaDoc();
251                     while ((s = reader.readLine()) != null) {
252                         GlobalTag tag = GlobalTag.makeGlobalTag(s);
253                         if (tag != null)
254                             tags.add(tag);
255                     }
256                 } else {
257                     Log.warn("getTags wrong version " + directory + " " +
258                         mode);
259                 }
260                 reader.close();
261             }
262             catch (IOException JavaDoc e) {
263                 Log.error(e);
264             }
265             if (tags != null) {
266                 if (cache == null)
267                     cache = new TagFileCache();
268                 cache.add(directory, mode.toString(), tagFile, tags);
269             } else
270                 tagFile.delete();
271         }
272         return tags;
273     }
274
275     private static class QueueEntry
276     {
277         final File directory;
278         final Mode mode;
279
280         QueueEntry(File directory, Mode mode)
281         {
282             this.directory = directory;
283             this.mode = mode;
284         }
285
286         public boolean equals(Object JavaDoc obj)
287         {
288             if (this == obj)
289                 return true;
290             if (obj instanceof QueueEntry) {
291                 QueueEntry qe = (QueueEntry) obj;
292                 if (!directory.equals(qe.directory))
293                     return false;
294                 // Same directory.
295
if (mode == qe.mode)
296                     return true;
297                 if (mode != null && mode.equals(qe.mode))
298                     return true;
299             }
300             return false;
301         }
302     }
303
304     private static class TagFileCache
305     {
306         private static final int MAX_FILES = 5;
307
308         private ArrayList JavaDoc list = new ArrayList JavaDoc(MAX_FILES);
309
310         TagFileCache() {}
311
312         synchronized List JavaDoc getTags(File tagFile)
313         {
314             Iterator JavaDoc iter = list.iterator();
315             while (iter.hasNext()) {
316                 CacheEntry entry = (CacheEntry) iter.next();
317                 if (entry.tagFile.equals(tagFile)) {
318                     entry.lastAccess = System.currentTimeMillis();
319                     // Move entry to top of list.
320
ArrayList JavaDoc newList = new ArrayList JavaDoc(MAX_FILES);
321                     newList.add(entry);
322                     for (int i = 0; i < list.size(); i++) {
323                         CacheEntry e = (CacheEntry) list.get(i);
324                         if (e != entry)
325                             newList.add(e);
326                     }
327                     Debug.assertTrue(newList.size() == list.size());
328                     list = newList;
329                     checkOrder();
330                     return entry.tags;
331                 }
332             }
333             return null;
334         }
335
336         synchronized void add(File directory, String JavaDoc modeName,
337             File tagFile, List JavaDoc tags)
338         {
339             CacheEntry entry = new CacheEntry(directory, modeName, tagFile, tags);
340             ArrayList JavaDoc newList = new ArrayList JavaDoc(MAX_FILES);
341             newList.add(entry);
342             int count = 1;
343             for (int i = 0; i < list.size() && count < MAX_FILES; i++) {
344                 CacheEntry e = (CacheEntry) list.get(i);
345                 if (!e.tagFile.equals(tagFile)) {
346                     newList.add(e);
347                     ++count;
348                 }
349             }
350             list = newList;
351             checkOrder();
352         }
353
354         synchronized void remove(File tagFile)
355         {
356             Iterator JavaDoc iter = list.iterator();
357             while (iter.hasNext()) {
358                 CacheEntry entry = (CacheEntry) iter.next();
359                 if (entry.tagFile.equals(tagFile)) {
360                     iter.remove();
361                     checkOrder();
362                     Log.debug("cache remove size = " + list.size());
363                     return;
364                 }
365             }
366             // Not found.
367
}
368
369         // Only called from synchronized methods.
370
void checkOrder()
371         {
372             if (Editor.isDebugEnabled()) {
373                 for (int i = 0; i < list.size()-1; i++) {
374                     CacheEntry entry1 = (CacheEntry) list.get(i);
375                     CacheEntry entry2 = (CacheEntry) list.get(i+1);
376                     if (entry1.lastAccess < entry2.lastAccess)
377                         Debug.bug();
378                 }
379 // dump();
380
}
381         }
382
383         // Only called from synchronized methods.
384
// void dump()
385
// {
386
// for (int i = 0; i < list.size(); i++)
387
// Log.debug(String.valueOf(i) + " " + list.get(i).toString());
388
// }
389
}
390
391     private static class CacheEntry
392     {
393         final File directory; // Needed for debugging only!
394
final String JavaDoc modeName; // Needed for debugging only!
395
final File tagFile;
396         List JavaDoc tags;
397         long lastAccess; // Needed for debugging only!
398

399         CacheEntry(File directory, String JavaDoc modeName, File tagFile,
400             List JavaDoc tags)
401         {
402             this.directory = directory;
403             this.modeName = modeName;
404             this.tagFile = tagFile;
405             this.tags = tags;
406             this.lastAccess = System.currentTimeMillis();
407         }
408
409         public String JavaDoc toString()
410         {
411             return directory.canonicalPath() + " " + modeName + " " +
412                 String.valueOf(lastAccess);
413         }
414     }
415 }
416
Popular Tags