KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > impl > KitsTracker


1 /*
2  * KitsTracker.java
3  *
4  * Created on February 21, 2007, 1:26 PM
5  *
6  * To change this template, choose Tools | Template Manager
7  * and open the template in the editor.
8  */

9
10 package org.netbeans.modules.editor.impl;
11
12 import java.util.ArrayList JavaDoc;
13 import java.util.Collections JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.logging.Level JavaDoc;
20 import java.util.logging.Logger JavaDoc;
21 import javax.swing.text.EditorKit JavaDoc;
22 import org.netbeans.api.editor.mimelookup.MimeLookup;
23 import org.netbeans.api.editor.mimelookup.MimePath;
24 import org.openide.filesystems.FileChangeAdapter;
25 import org.openide.filesystems.FileChangeListener;
26 import org.openide.filesystems.FileEvent;
27 import org.openide.filesystems.FileObject;
28 import org.openide.filesystems.FileRenameEvent;
29 import org.openide.filesystems.Repository;
30
31 /**
32  *
33  * @author vita
34  */

35 public final class KitsTracker {
36         
37     private static final Logger JavaDoc LOG = Logger.getLogger(KitsTracker.class.getName());
38     private static final Set JavaDoc ALREADY_LOGGED = Collections.synchronizedSet(new HashSet JavaDoc(10));
39     
40     private static KitsTracker instance = null;
41     
42     /**
43      * Gets the <code>KitsTracker</code> singleton instance.
44      * @return The <code>KitsTracker</code> instance.
45      */

46     public static synchronized KitsTracker getInstance() {
47         if (instance == null) {
48             instance = new KitsTracker();
49         }
50         return instance;
51     }
52     
53     /**
54      * Gets the list of mime types (<code>String</code>s) that use the given
55      * class as an editor kit implementation.
56      *
57      * @param kitClass The editor kit class to get mime types for.
58      * @return The <code>List&lt;String&gt;</code> of mime types.
59      */

60     public List JavaDoc/*<String>*/ getMimeTypesForKitClass(Class JavaDoc kitClass) {
61         synchronized (mimeType2kitClass) {
62             if (needsReloading) {
63                 reload();
64             }
65
66             ArrayList JavaDoc list = new ArrayList JavaDoc();
67             for(Iterator JavaDoc i = mimeType2kitClass.keySet().iterator(); i.hasNext(); ) {
68                 String JavaDoc mimeType = (String JavaDoc) i.next();
69                 Class JavaDoc clazz = (Class JavaDoc) mimeType2kitClass.get(mimeType);
70                 if (kitClass == clazz) {
71                     list.add(mimeType);
72                 }
73             }
74
75             return list;
76         }
77     }
78
79     /**
80      * Find mime type for a given editor kit implementation class.
81      *
82      * @param kitClass The editor kit class to get the mime type for.
83      * @return The mime type or <code>null</code> if the mime type can't be
84      * resolved for the given kit class.
85      */

86     public String JavaDoc findMimeType(Class JavaDoc kitClass) {
87         List JavaDoc mimeTypes = getMimeTypesForKitClass(kitClass);
88         if (mimeTypes.size() == 0) {
89             if (LOG.isLoggable(Level.WARNING)) {
90                 logOnce(Level.WARNING, "No mime type uses editor kit implementation class: " + kitClass); //NOI18N
91
}
92             return null;
93         } else if (mimeTypes.size() == 1) {
94             return (String JavaDoc) mimeTypes.get(0);
95         } else {
96             if (LOG.isLoggable(Level.WARNING)) {
97 // Throwable t = new Throwable("Stacktrace"); //NOI18N
98
// LOG.log(Level.WARNING, "Ambiguous mime types for editor kit implementation class: " + kitClass + "; mime types: " + mimeTypes, t); //NOI18N
99
logOnce(Level.WARNING, "Ambiguous mime types for editor kit implementation class: " + kitClass + "; mime types: " + mimeTypes); //NOI18N
100
}
101             return null;
102         }
103     }
104     
105     // ------------------------------------------------------------------
106
// private implementation
107
// ------------------------------------------------------------------
108

109     // The map of mime type -> kit class
110
private final HashMap JavaDoc/*<String, Class>*/ mimeType2kitClass = new HashMap JavaDoc();
111     private final ArrayList JavaDoc/*<FileObject>*/ eventSources = new ArrayList JavaDoc();
112     private boolean needsReloading = true;
113
114     private final FileChangeListener fcl = new FileChangeAdapter() {
115         public void fileFolderCreated(FileEvent fe) {
116             invalidateCache();
117         }
118
119         public void fileDeleted(FileEvent fe) {
120             if (fe.getFile().isFolder()) {
121                 invalidateCache();
122             }
123         }
124
125         public void fileRenamed(FileRenameEvent fe) {
126             if (fe.getFile().isFolder()) {
127                 invalidateCache();
128             }
129         }
130     };
131     
132     private KitsTracker() {
133
134     }
135
136     private void reload() {
137         // Stop listening
138
for(Iterator JavaDoc i = eventSources.iterator(); i.hasNext(); ) {
139             FileObject fo = (FileObject) i.next();
140             fo.removeFileChangeListener(fcl);
141         }
142
143         // Clear the cache
144
mimeType2kitClass.clear();
145
146         // Get the root of the MimeLookup registry
147
FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource("Editors"); //NOI18N
148

149         // Generally may not exist (e.g. in tests)
150
if (fo != null) {
151             // Go through mime type types
152
FileObject [] types = fo.getChildren();
153             for(int i = 0; i < types.length; i++) {
154                 if (!types[i].isFolder()) {
155                     continue;
156                 }
157
158                 // Go through mime type subtypes
159
FileObject [] subTypes = types[i].getChildren();
160                 for(int j = 0; j < subTypes.length; j++) {
161                     if (!subTypes[j].isFolder()) {
162                         continue;
163                     }
164
165                     String JavaDoc mimeType = types[i].getNameExt() + "/" + subTypes[j].getNameExt(); //NOI18N
166
MimePath mimePath = MimePath.parse(mimeType);
167                     EditorKit JavaDoc kit = (EditorKit JavaDoc) MimeLookup.getLookup(mimePath).lookup(EditorKit JavaDoc.class);
168
169                     if (kit != null) {
170                         String JavaDoc genericMimeType;
171                         if (!kit.getContentType().equals(mimeType) &&
172                             !(null != (genericMimeType = getGenericPartOfCompoundMimeType(mimeType)) && genericMimeType.equals(kit.getContentType())))
173                         {
174                             LOG.warning("Inconsistent mime type declaration for the kit: " + kit + //NOI18N
175
"; mimeType from the kit is '" + kit.getContentType() + //NOI18N
176
", but the kit is registered for '" + mimeType + "'"); //NOI18N
177
}
178                         mimeType2kitClass.put(mimeType, kit.getClass());
179                     } else {
180                         if (LOG.isLoggable(Level.FINE)) {
181                             LOG.fine("No kit for '" + mimeType + "'");
182                         }
183                     }
184                 }
185
186                 types[i].addFileChangeListener(fcl);
187                 eventSources.add(types[i]);
188             }
189
190             fo.addFileChangeListener(fcl);
191             eventSources.add(fo);
192         }
193
194         needsReloading = false;
195     }
196
197     private void invalidateCache() {
198         synchronized (mimeType2kitClass) {
199             needsReloading = true;
200         }
201     }
202
203     private static String JavaDoc getGenericPartOfCompoundMimeType(String JavaDoc mimeType) {
204         int plusIdx = mimeType.lastIndexOf('+'); //NOI18N
205
if (plusIdx != -1 && plusIdx < mimeType.length() - 1) {
206             int slashIdx = mimeType.indexOf('/'); //NOI18N
207
String JavaDoc prefix = mimeType.substring(0, slashIdx + 1);
208             String JavaDoc suffix = mimeType.substring(plusIdx + 1);
209
210             // fix for #61245
211
if (suffix.equals("xml")) { //NOI18N
212
prefix = "text/"; //NOI18N
213
}
214
215             return prefix + suffix;
216         } else {
217             return null;
218         }
219     }
220     
221     private static void logOnce(Level JavaDoc level, String JavaDoc msg) {
222         if (!ALREADY_LOGGED.contains(msg)) {
223             LOG.log(level, msg);
224             ALREADY_LOGGED.add(msg);
225         }
226     }
227 }
228
Popular Tags