| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.internal.ui.text.spelling; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultSpellChecker; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary; |
| import org.eclipse.jdt.internal.ui.text.spelling.engine.PersistentSpellDictionary; |
| |
| /** |
| * Spell check engine for Java source spell checking. |
| * |
| * @since 3.0 |
| */ |
| public class SpellCheckEngine implements ISpellCheckEngine, IPropertyChangeListener { |
| |
| /** The dictionary location */ |
| public static final String DICTIONARY_LOCATION= "dictionaries/"; //$NON-NLS-1$ |
| |
| /** The singleton engine instance */ |
| private static ISpellCheckEngine fgEngine= null; |
| |
| /** |
| * Returns the available locales for this spell check engine. |
| * |
| * @return The available locales for this engine |
| */ |
| public static Set getAvailableLocales() { |
| |
| URL url= null; |
| Locale locale= null; |
| InputStream stream= null; |
| |
| final Set result= new HashSet(); |
| try { |
| |
| final URL location= getDictionaryLocation(); |
| |
| if (location == null) |
| return Collections.EMPTY_SET; |
| |
| final Locale[] locales= Locale.getAvailableLocales(); |
| |
| for (int index= 0; index < locales.length; index++) { |
| |
| locale= locales[index]; |
| url= new URL(location, locale.toString().toLowerCase() + ".dictionary"); //$NON-NLS-1$ |
| |
| try { |
| stream= url.openStream(); |
| if (stream != null) { |
| try { |
| result.add(locale); |
| } finally { |
| stream.close(); |
| } |
| } |
| } catch (IOException exception) { |
| // Do nothing |
| } |
| } |
| } catch (MalformedURLException exception) { |
| // Do nothing |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Returns the default locale for this engine. |
| * |
| * @return The default locale |
| */ |
| public static Locale getDefaultLocale() { |
| return Locale.getDefault(); |
| } |
| |
| /** |
| * Returns the dictionary location. |
| * |
| * @throws MalformedURLException |
| * if the URL could not be created |
| * @return The dictionary location, or <code>null</code> iff the location |
| * is not known |
| */ |
| public static URL getDictionaryLocation() throws MalformedURLException { |
| |
| final JavaPlugin plugin= JavaPlugin.getDefault(); |
| if (plugin != null) |
| return plugin.getBundle().getEntry("/" + DICTIONARY_LOCATION); //$NON-NLS-1$ |
| |
| return null; |
| } |
| |
| /** |
| * Returns the singleton instance of the spell check engine. |
| * |
| * @return The singleton instance of the spell check engine |
| */ |
| public static final synchronized ISpellCheckEngine getInstance() { |
| |
| if (fgEngine == null) |
| fgEngine= new SpellCheckEngine(); |
| |
| return fgEngine; |
| } |
| |
| /** The registered locale insenitive dictionaries */ |
| private final Set fGlobalDictionaries= new HashSet(); |
| |
| /** The current locale */ |
| private Locale fLocale= null; |
| |
| /** The spell checker for fLocale */ |
| private ISpellChecker fChecker= null; |
| |
| /** The registered locale sensitive dictionaries */ |
| private final Map fLocaleDictionaries= new HashMap(); |
| |
| /** The preference store where to listen */ |
| private IPreferenceStore fPreferences= null; |
| |
| /** The user dictionary */ |
| private ISpellDictionary fUserDictionary= null; |
| |
| /** |
| * Creates a new spell check manager. |
| */ |
| private SpellCheckEngine() { |
| |
| fGlobalDictionaries.add(new TaskTagDictionary()); |
| fGlobalDictionaries.add(new HtmlTagDictionary()); |
| fGlobalDictionaries.add(new JavaDocTagDictionary()); |
| |
| try { |
| |
| Locale locale= null; |
| final URL location= getDictionaryLocation(); |
| |
| for (final Iterator iterator= getAvailableLocales().iterator(); iterator.hasNext();) { |
| |
| locale= (Locale)iterator.next(); |
| fLocaleDictionaries.put(locale, new SpellReconcileDictionary(locale, location)); |
| } |
| |
| } catch (MalformedURLException exception) { |
| // Do nothing |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#createSpellChecker(java.util.Locale,org.eclipse.jface.preference.IPreferenceStore) |
| */ |
| public final synchronized ISpellChecker createSpellChecker(final Locale locale, final IPreferenceStore store) { |
| |
| if (fLocale != null && fLocale.equals(locale)) |
| return fChecker; |
| |
| if (fChecker == null) { |
| |
| fChecker= new DefaultSpellChecker(store); |
| store.addPropertyChangeListener(this); |
| |
| fPreferences= store; |
| |
| ISpellDictionary dictionary= null; |
| for (Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { |
| |
| dictionary= (ISpellDictionary)iterator.next(); |
| fChecker.addDictionary(dictionary); |
| } |
| } |
| |
| ISpellDictionary dictionary= null; |
| if (fLocale != null) { |
| |
| dictionary= (ISpellDictionary)fLocaleDictionaries.get(fLocale); |
| if (dictionary != null) { |
| |
| fChecker.removeDictionary(dictionary); |
| dictionary.unload(); |
| } |
| } |
| fLocale= locale; |
| |
| dictionary= (ISpellDictionary)fLocaleDictionaries.get(locale); |
| if (dictionary == null) { |
| |
| if (!getDefaultLocale().equals(locale)) { |
| |
| if (fPreferences != null) |
| fPreferences.removePropertyChangeListener(this); |
| |
| fChecker= null; |
| fLocale= null; |
| } |
| |
| } else |
| fChecker.addDictionary(dictionary); |
| |
| if (fPreferences != null) |
| propertyChange(new PropertyChangeEvent(this, ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY, null, fPreferences.getString(ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY))); |
| |
| return fChecker; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale() |
| */ |
| public final Locale getLocale() { |
| return fLocale; |
| } |
| |
| /* |
| * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) |
| */ |
| public final void propertyChange(final PropertyChangeEvent event) { |
| |
| if (fChecker != null && event.getProperty().equals(ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY)) { |
| |
| if (fUserDictionary != null) { |
| |
| fChecker.removeDictionary(fUserDictionary); |
| fUserDictionary= null; |
| } |
| |
| final String file= (String)event.getNewValue(); |
| if (file.length() > 0) { |
| |
| try { |
| |
| final URL url= new URL("file", null, file); //$NON-NLS-1$ |
| InputStream stream= url.openStream(); |
| if (stream != null) { |
| try { |
| fUserDictionary= new PersistentSpellDictionary(url); |
| fChecker.addDictionary(fUserDictionary); |
| } finally { |
| stream.close(); |
| } |
| } |
| } catch (MalformedURLException exception) { |
| // Do nothing |
| } catch (IOException exception) { |
| // Do nothing |
| } |
| } |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary) |
| */ |
| public synchronized final void registerDictionary(final ISpellDictionary dictionary) { |
| |
| fGlobalDictionaries.add(dictionary); |
| |
| if (fChecker != null) |
| fChecker.addDictionary(dictionary); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale,org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary) |
| */ |
| public synchronized final void registerDictionary(final Locale locale, final ISpellDictionary dictionary) { |
| |
| fLocaleDictionaries.put(locale, dictionary); |
| |
| if (fChecker != null && fLocale != null && fLocale.equals(locale)) |
| fChecker.addDictionary(dictionary); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#unload() |
| */ |
| public synchronized final void unload() { |
| |
| ISpellDictionary dictionary= null; |
| for (final Iterator iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) { |
| |
| dictionary= (ISpellDictionary)iterator.next(); |
| dictionary.unload(); |
| } |
| |
| for (final Iterator iterator= fLocaleDictionaries.values().iterator(); iterator.hasNext();) { |
| |
| dictionary= (ISpellDictionary)iterator.next(); |
| dictionary.unload(); |
| } |
| |
| if (fPreferences != null) |
| fPreferences.removePropertyChangeListener(this); |
| |
| fUserDictionary= null; |
| fChecker= null; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary) |
| */ |
| public synchronized final void unregisterDictionary(final ISpellDictionary dictionary) { |
| |
| fGlobalDictionaries.remove(dictionary); |
| fLocaleDictionaries.values().remove(dictionary); |
| |
| if (fChecker != null) |
| fChecker.removeDictionary(dictionary); |
| |
| dictionary.unload(); |
| } |
| } |