1 19 20 package org.netbeans.lib.lexer; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.lang.ref.WeakReference ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.Collections ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.WeakHashMap ; 31 import org.netbeans.api.lexer.InputAttributes; 32 import org.netbeans.api.lexer.Language; 33 import org.netbeans.api.lexer.LanguagePath; 34 import org.netbeans.api.lexer.Token; 35 import org.netbeans.api.lexer.TokenId; 36 import org.netbeans.spi.lexer.LanguageEmbedding; 37 import org.netbeans.spi.lexer.LanguageHierarchy; 38 import org.netbeans.spi.lexer.LanguageProvider; 39 import org.netbeans.spi.lexer.Lexer; 40 import org.netbeans.spi.lexer.LexerRestartInfo; 41 import org.openide.util.Lookup; 42 import org.openide.util.LookupEvent; 43 import org.openide.util.LookupListener; 44 45 49 public final class LanguageManager extends LanguageProvider implements LookupListener, PropertyChangeListener { 50 51 private static final Language<TokenId> NO_LANG = new LanguageHierarchy<TokenId>() { 52 @Override 53 protected Lexer<TokenId> createLexer(LexerRestartInfo<TokenId> info) { 54 return null; 55 } 56 @Override 57 protected Collection <TokenId> createTokenIds() { 58 return Collections.emptyList(); 59 } 60 @Override 61 protected String mimeType() { 62 return "obscure/no-language-marker"; } 64 }.language(); 65 66 private static final LanguageEmbedding<TokenId> NO_LANG_EMBEDDING 67 = LanguageEmbedding.create(NO_LANG, 0, 0); 68 69 private static LanguageManager instance = null; 70 71 public static synchronized LanguageManager getInstance() { 72 if (instance == null) { 73 instance = new LanguageManager(); 74 } 75 return instance; 76 } 77 78 private Lookup.Result<LanguageProvider> lookupResult = null; 79 80 private List <LanguageProvider> providers = Collections.<LanguageProvider>emptyList(); 81 private HashMap <String , WeakReference <Language<? extends TokenId>>> langCache 82 = new HashMap <String , WeakReference <Language<? extends TokenId>>>(); 83 private WeakHashMap <Token, LanguageEmbedding<? extends TokenId>> tokenLangCache 84 = new WeakHashMap <Token, LanguageEmbedding<? extends TokenId>>(); 85 86 private final String LOCK = new String ("LanguageManager.LOCK"); 87 88 89 private LanguageManager() { 90 lookupResult = Lookup.getDefault().lookup(new Lookup.Template<LanguageProvider>(LanguageProvider.class)); 91 lookupResult.addLookupListener(this); 92 refreshProviders(); 93 } 94 95 99 public Language<? extends TokenId> findLanguage(String mimePath) { 100 synchronized(LOCK) { 101 WeakReference <Language<? extends TokenId>> ref = langCache.get(mimePath); 102 Language<? extends TokenId> lang = ref == null ? null : ref.get(); 103 104 if (lang == null) { 105 for(LanguageProvider p : providers) { 106 if (null != (lang = p.findLanguage(mimePath))) { 107 break; 108 } 109 } 110 111 if (lang == null) { 112 lang = NO_LANG; 113 } 114 115 langCache.put(mimePath, new WeakReference <Language<? extends TokenId>>(lang)); 116 } 117 118 return lang == NO_LANG ? null : lang; 119 } 120 } 121 122 public LanguageEmbedding<? extends TokenId> findLanguageEmbedding( 123 Token<? extends TokenId> token, LanguagePath languagePath, InputAttributes inputAttributes) { 124 synchronized(LOCK) { 125 LanguageEmbedding<? extends TokenId> lang = tokenLangCache.get(token); 126 127 if (lang == null) { 128 for(LanguageProvider p : providers) { 129 if (null != (lang = p.findLanguageEmbedding(token, languagePath, inputAttributes))) { 130 break; 131 } 132 } 133 134 if (lang == null) { 135 lang = NO_LANG_EMBEDDING; 136 } 137 138 tokenLangCache.put(token, lang); 139 } 140 141 return lang == NO_LANG_EMBEDDING ? null : lang; 142 } 143 } 144 145 149 public void resultChanged(LookupEvent ev) { 150 refreshProviders(); 151 } 152 153 157 public void propertyChange(PropertyChangeEvent evt) { 158 if (evt.getPropertyName() == null) { 159 synchronized(LOCK) { 160 langCache.clear(); 161 tokenLangCache.clear(); 162 } 163 } else if (LanguageProvider.PROP_LANGUAGE.equals(evt.getPropertyName())) { 164 synchronized(LOCK) { 165 langCache.clear(); 166 } 167 } else if (LanguageProvider.PROP_EMBEDDED_LANGUAGE.equals(evt.getPropertyName())) { 168 synchronized(LOCK) { 169 tokenLangCache.clear(); 170 } 171 } 172 firePropertyChange(evt.getPropertyName()); 174 } 175 176 180 private void refreshProviders() { 181 Collection <? extends LanguageProvider> newProviders = lookupResult.allInstances(); 182 183 synchronized(LOCK) { 184 for(LanguageProvider p : providers) { 185 p.removePropertyChangeListener(this); 186 } 187 188 providers = new ArrayList <LanguageProvider>(newProviders); 189 190 for(LanguageProvider p : providers) { 191 p.addPropertyChangeListener(this); 192 } 193 194 langCache.clear(); 195 tokenLangCache.clear(); 196 } 197 } 198 199 } 200 | Popular Tags |