1 9 10 package org.netbeans.modules.editor.impl; 11 12 import java.util.ArrayList ; 13 import java.util.Collections ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Set ; 19 import java.util.logging.Level ; 20 import java.util.logging.Logger ; 21 import javax.swing.text.EditorKit ; 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 35 public final class KitsTracker { 36 37 private static final Logger LOG = Logger.getLogger(KitsTracker.class.getName()); 38 private static final Set ALREADY_LOGGED = Collections.synchronizedSet(new HashSet (10)); 39 40 private static KitsTracker instance = null; 41 42 46 public static synchronized KitsTracker getInstance() { 47 if (instance == null) { 48 instance = new KitsTracker(); 49 } 50 return instance; 51 } 52 53 60 public List getMimeTypesForKitClass(Class kitClass) { 61 synchronized (mimeType2kitClass) { 62 if (needsReloading) { 63 reload(); 64 } 65 66 ArrayList list = new ArrayList (); 67 for(Iterator i = mimeType2kitClass.keySet().iterator(); i.hasNext(); ) { 68 String mimeType = (String ) i.next(); 69 Class clazz = (Class ) mimeType2kitClass.get(mimeType); 70 if (kitClass == clazz) { 71 list.add(mimeType); 72 } 73 } 74 75 return list; 76 } 77 } 78 79 86 public String findMimeType(Class kitClass) { 87 List 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); } 92 return null; 93 } else if (mimeTypes.size() == 1) { 94 return (String ) mimeTypes.get(0); 95 } else { 96 if (LOG.isLoggable(Level.WARNING)) { 97 logOnce(Level.WARNING, "Ambiguous mime types for editor kit implementation class: " + kitClass + "; mime types: " + mimeTypes); } 101 return null; 102 } 103 } 104 105 109 private final HashMap mimeType2kitClass = new HashMap (); 111 private final ArrayList eventSources = new ArrayList (); 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 for(Iterator i = eventSources.iterator(); i.hasNext(); ) { 139 FileObject fo = (FileObject) i.next(); 140 fo.removeFileChangeListener(fcl); 141 } 142 143 mimeType2kitClass.clear(); 145 146 FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource("Editors"); 149 if (fo != null) { 151 FileObject [] types = fo.getChildren(); 153 for(int i = 0; i < types.length; i++) { 154 if (!types[i].isFolder()) { 155 continue; 156 } 157 158 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 mimeType = types[i].getNameExt() + "/" + subTypes[j].getNameExt(); MimePath mimePath = MimePath.parse(mimeType); 167 EditorKit kit = (EditorKit ) MimeLookup.getLookup(mimePath).lookup(EditorKit .class); 168 169 if (kit != null) { 170 String 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 + "; mimeType from the kit is '" + kit.getContentType() + ", but the kit is registered for '" + mimeType + "'"); } 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 getGenericPartOfCompoundMimeType(String mimeType) { 204 int plusIdx = mimeType.lastIndexOf('+'); if (plusIdx != -1 && plusIdx < mimeType.length() - 1) { 206 int slashIdx = mimeType.indexOf('/'); String prefix = mimeType.substring(0, slashIdx + 1); 208 String suffix = mimeType.substring(plusIdx + 1); 209 210 if (suffix.equals("xml")) { prefix = "text/"; } 214 215 return prefix + suffix; 216 } else { 217 return null; 218 } 219 } 220 221 private static void logOnce(Level level, String msg) { 222 if (!ALREADY_LOGGED.contains(msg)) { 223 LOG.log(level, msg); 224 ALREADY_LOGGED.add(msg); 225 } 226 } 227 } 228 | Popular Tags |