/**
* This file Copyright (c) 2005-2008 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.editors.unified;
import java.io.File;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.activities.IActivityManager;
import org.eclipse.ui.activities.IIdentifier;
import org.eclipse.ui.activities.IIdentifierListener;
import org.eclipse.ui.activities.IdentifierEvent;
import com.aptana.ide.core.IdeLog;
import com.aptana.ide.core.StringUtils;
import com.aptana.ide.editors.UnifiedEditorsPlugin;
import com.aptana.ide.editors.unified.colorizer.ColorizerReader;
import com.aptana.ide.editors.unified.colorizer.LanguageColorizer;
import com.aptana.ide.editors.unified.colorizer.Messages;
import com.aptana.ide.lexer.TokenList;
import com.aptana.ide.parsing.IParser;
import com.aptana.ide.parsing.eclipse.ParsingRegistry;
/**
* Maintains registry of token lists, colorizers, pair finders, and parsers by language MIME type
*
* @author Kevin Sawicki (ksawicki@aptana.com)
* @author Kevin Lindsey
*/
public final class LanguageRegistry
{
private static final String PAIRFINDER_ID = "com.aptana.ide.editors.pairfinder"; //$NON-NLS-1$
private static final String FORMATTER_ID = "com.aptana.ide.editors.formatter"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
private static final String ATTR_LANGUAGE = "language"; //$NON-NLS-1$
private static final String TAG_PAIR_FINDER = "pairFinder"; //$NON-NLS-1$
private static final String TAG_FORMATTER = "formatter"; //$NON-NLS-1$
private static Map<String, LanguageColorizer> languageColorizers = new HashMap<String, LanguageColorizer>();
private static Map<String, InstanceCreator> pairFinders = new HashMap<String, InstanceCreator>();
private static Map<String, InstanceCreator> formatters = new HashMap<String, InstanceCreator>();
private static ColorizerReader colorizerReader;
private static final IActivityManager activityManager = PlatformUI.getWorkbench().getActivitySupport()
.getActivityManager();
private static IIdentifierListener identifierListener = new IIdentifierListener()
{
public void identifierChanged(IdentifierEvent identifierEvent)
{
if (identifierEvent.hasEnabledChanged())
{
IIdentifier identifier = identifierEvent.getIdentifier();
if (identifier.isEnabled())
{
LanguageRegistry.reloadAll();
// identifier.removeIdentifierListener(this);
}
}
}
};
/**
* static constructor
*/
static
{
loadAll();
}
/**
* LanguageRegistry
*/
private LanguageRegistry()
{
// Does nothing
}
public static void clearAll()
{
languageColorizers.clear();
pairFinders.clear();
formatters.clear();
}
public static void loadAll()
{
loadColorizations();
loadPairFinders();
loadCodeFormatters();
}
public static void reloadAll()
{
clearAll();
loadAll();
}
/**
* Get the colorizer for the specified language
*
* @param language
* @return LanguageColorizer or null
*/
public static LanguageColorizer getLanguageColorizer(String language)
{
LanguageColorizer original = null;
if (languageColorizers.containsKey(language))
{
original = languageColorizers.get(language);
}
else if (colorizerReader.getInstanceCreator(language) != null)
{
InstanceCreator creator = colorizerReader.getInstanceCreator(language);
// This method call will also register the colorizer which is done
// in ColorizerReader
original = (LanguageColorizer) creator.getCachedInstance();
}
else
{
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), StringUtils.format(
Messages.LanguageRegistry_NO_COLORIZER, language));
}
return original;
}
/**
* Get the colorizer for the specified language
*
* @param language
* @param reader
* - reader to use if needed.
* @return LanguageColorizer or null
*/
public static LanguageColorizer getLanguageColorizer(String language, ColorizerReader reader)
{
LanguageColorizer original = null;
if (languageColorizers.containsKey(language))
{
original = languageColorizers.get(language);
}
else if (reader.getInstanceCreator(language) != null)
{
InstanceCreator creator = reader.getInstanceCreator(language);
// This method call will also register the colorizer which is done
// in ColorizerReader
original = (LanguageColorizer) creator.getCachedInstance();
}
else
{
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), StringUtils.format(
Messages.LanguageRegistry_NO_COLORIZER, language));
}
return original;
}
/**
* Gets a list of all the registered language colorizers
*
* @return - list of LanguageColorzier objects
*/
public static List<LanguageColorizer> getLanguageColorizers()
{
return new ArrayList<LanguageColorizer>(languageColorizers.values());
}
/**
* @param language
* @return preference id for this language type
*/
public static String getPreferenceId(String language)
{
return colorizerReader.getPreferenceId(language);
}
/**
* Creates the parser for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
* @deprecated use {@link ParsingRegistry#getParser(String)}
*/
public static IParser getParser(String language)
{
return ParsingRegistry.getParser(language);
}
/**
* Creates the parser for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
* @deprecated use {@link ParsingRegistry#getScanner(String)}
*/
public static IParser getScanner(String language)
{
return ParsingRegistry.getScanner(language);
}
/**
* Creates the pair finder for a language mime type
*
* @param language
* - language mime type
* @return IPairFinder
*/
public static IPairFinder getPairFinder(String language)
{
IPairFinder result = null;
if (pairFinders.containsKey(language))
{
InstanceCreator creator = pairFinders.get(language);
result = (IPairFinder) creator.getCachedInstance();
}
else
{
String message = MessageFormat.format(Messages.LanguageRegistry_No_Associated_Finder,
new Object[] { language });
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), message);
}
return result;
}
/**
* Creates the Code Formatter for a language mime type
*
* @param language
* - language mime type
* @return ICodeFormatter
*/
public static ICodeFormatter getCodeFormatter(String language)
{
ICodeFormatter result = null;
if (formatters.containsKey(language))
{
InstanceCreator creator = formatters.get(language);
result = (ICodeFormatter) creator.getCachedInstance();
}
else
{
String message = MessageFormat.format(Messages.LanguageRegistry_No_Associated_Formatter,
new Object[] { language });
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), message);
}
return result;
}
/**
* Creates the token list for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
* @deprecated use {@link ParsingRegistry#getTokenList(String)}
*/
public static TokenList getTokenList(String language)
{
return ParsingRegistry.getTokenList(language);
}
/**
* getTokenListByExtension
*
* @param extension
* @return - token list
* @deprecated use {@link ParsingRegistry#getTokenListByExtension(String)}
*/
public static TokenList getTokenListByExtension(String extension)
{
return ParsingRegistry.getTokenListByExtension(extension);
}
/**
* createParse
*
* @param language
* @return IParser
* @deprecated use {@link ParsingRegistry#createParser(String)}
*/
public static IParser createParser(String language)
{
return ParsingRegistry.createParser(language);
}
/**
* createScanner
*
* @param language
* @return IParser
* @deprecated use {@link ParsingRegistry#createScanner(String)}
*/
public static IParser createScanner(String language)
{
return ParsingRegistry.createScanner(language);
}
/**
* createTokenList
*
* @param input
* @return TokenList or null
* @deprecated use {@link ParsingRegistry#createTokenList(InputStream)}
*/
public static TokenList createTokenList(InputStream input)
{
try
{
return ParsingRegistry.createTokenList(input);
}
catch (Exception e)
{
IdeLog.logError(UnifiedEditorsPlugin.getDefault(), Messages.LanguageRegistry_Cannot_Create_Token_List, e);
}
return null;
}
/**
* createTokenList
*
* @param language
* @return TokenList
* @deprecated use {@link ParsingRegistry#createTokenList(String)}
*/
public static TokenList createTokenList(String language)
{
return ParsingRegistry.createTokenList(language);
}
/**
* Checks if a colorizer exists for a language
*
* @param language
* @return - true if colorizer exists for the language
*/
public static boolean hasLanguageColorizer(String language)
{
return languageColorizers.containsKey(language);
}
/**
* hasParser
*
* @param language
* @return boolean
* @deprecated use {@link ParsingRegistry#hasParser(String)}
*/
public static boolean hasParser(String language)
{
return ParsingRegistry.hasParser(language);
}
/**
* hasScanner
*
* @param language
* @return boolean
* @deprecated use {@link ParsingRegistry#hasScanner(String)}
*/
public static boolean hasScanner(String language)
{
return ParsingRegistry.hasScanner(language);
}
/**
* hasTokenList
*
* @param language
* @return boolean
* @deprecated use {@link ParsingRegistry#hasTokenList(String)}
*/
public static boolean hasTokenList(String language)
{
return ParsingRegistry.hasTokenList(language);
}
/**
* Imports a colorization
*
* @param file
* - colorization file
* @param language
* - mime type
*/
public static void importColorization(File file, String language)
{
colorizerReader.importColorization(file, language);
}
/**
* loadColorizations
*/
private static void loadColorizations()
{
colorizerReader = new ColorizerReader();
colorizerReader.loadExtensionPointColorizers();
}
public static final boolean isActivityEnabled(IConfigurationElement element)
{
String extensionId = element.getAttribute("id"); //$NON-NLS-1$
String extensionPluginId = element.getNamespaceIdentifier();
String extensionString = null;
if (extensionPluginId != null && extensionId != null && extensionPluginId.length() > 0
&& extensionId.length() > 0)
{
extensionString = extensionPluginId + "/" + extensionId; //$NON-NLS-1$
}
else if (extensionPluginId != null && extensionPluginId.length() > 0)
{
extensionString = extensionPluginId + "/.*"; //$NON-NLS-1$
}
if (extensionString != null)
{
final IIdentifier id = activityManager.getIdentifier(extensionString);
if (id != null)
{
boolean enabled = id.isEnabled();
if (!id.isEnabled())
{
id.addIdentifierListener(identifierListener);
}
return enabled;
}
}
return true;
}
/**
* loadPairFinders
*/
private static void loadPairFinders()
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint(PAIRFINDER_ID);
if (ep != null)
{
IExtension[] extensions = ep.getExtensions();
for (int i = 0; i < extensions.length; i++)
{
IExtension extension = extensions[i];
IConfigurationElement[] elements = extension.getConfigurationElements();
for (int j = 0; j < elements.length; j++)
{
IConfigurationElement element = elements[j];
String elementName = element.getName();
if (!isActivityEnabled(element))
{
// Do nothing because this extension should not work.
continue;
}
else if (elementName.equals(TAG_PAIR_FINDER))
{
String finderClass = element.getAttribute(ATTR_CLASS);
String language = element.getAttribute(ATTR_LANGUAGE);
// IdeLog.logInfo(UnifiedEditorsPlugin.getDefault(),
// StringUtils.format("Attempting to register
// parser with class name {0} and language {1}", new
// String[] {parserClass, language}));
if (finderClass != null && language != null && language.length() > 0)
{
InstanceCreator creator = new InstanceCreator(element, ATTR_CLASS);
// IdeLog.logInfo(UnifiedEditorsPlugin.getDefault(),
// StringUtils.format("Registered parser
// for MIME type {0} in LanguageRegistry",
// language));
pairFinders.put(language, creator);
}
}
}
}
}
}
/**
* loadCodeFormatters
*/
private static void loadCodeFormatters()
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint(FORMATTER_ID);
if (ep != null)
{
IExtension[] extensions = ep.getExtensions();
for (int i = 0; i < extensions.length; i++)
{
IExtension extension = extensions[i];
IConfigurationElement[] elements = extension.getConfigurationElements();
for (int j = 0; j < elements.length; j++)
{
IConfigurationElement element = elements[j];
String elementName = element.getName();
if (!isActivityEnabled(element))
{
// DO NOTHING
continue;
}
else if (elementName.equals(TAG_FORMATTER))
{
String finderClass = element.getAttribute(ATTR_CLASS);
String language = element.getAttribute(ATTR_LANGUAGE);
// IdeLog.logInfo(UnifiedEditorsPlugin.getDefault(),
// StringUtils.format("Attempting to register
// parser with class name {0} and language {1}", new
// String[] {parserClass, language}));
if (finderClass != null && language != null && language.length() > 0)
{
InstanceCreator creator = new InstanceCreator(element, ATTR_CLASS);
// IdeLog.logInfo(UnifiedEditorsPlugin.getDefault(),
// StringUtils.format("Registered parser
// for MIME type {0} in LanguageRegistry",
// language));
formatters.put(language, creator);
}
}
}
}
}
}
/**
* Registers a language colorizer.
*
* @param language
* @param colorizer
*/
public static void registerLanguageColorizer(String language, LanguageColorizer colorizer)
{
if (!languageColorizers.containsKey(language))
{
languageColorizers.put(language, colorizer);
}
else
{
LanguageColorizer curr = languageColorizers.get(language);
curr.setCategoryColorizers(colorizer);
curr.setTokenColorizers(colorizer);
curr.setBackground(colorizer.getBackground());
curr.setCaretColor(colorizer.getCaretColor());
curr.setLineHighlightColor(colorizer.getLineHighlightColor());
curr.setSelectionBackground(colorizer.getSelectionBackground());
curr.setSelectionForeground(colorizer.getSelectionForeground());
curr.setFoldingBg(colorizer.getFoldingBg());
curr.setFoldingFg(colorizer.getFoldingFg());
}
}
/**
* registerParser
*
* @param language
* @param parser
* @deprecated use {@link ParsingRegistry#registerParser(String, IParser)}
*/
public static void registerParser(String language, IParser parser)
{
ParsingRegistry.registerParser(language, parser);
}
/**
* registerScanner
*
* @param language
* @param parser
* @deprecated use {@link ParsingRegistry#registerScanner(String, IParser)}
*/
public static void registerScanner(String language, IParser parser)
{
ParsingRegistry.registerScanner(language, parser);
}
/**
* registerTokenList
*
* @param tokenList
* @deprecated use {@link ParsingRegistry#registerScanner(TokenList)}
*/
public static void registerTokenList(TokenList tokenList)
{
ParsingRegistry.registerTokenList(tokenList);
}
/**
* registerTokenList
*
* @param tokenList
* @param fileExtension
* @deprecated use {@link ParsingRegistry#registerTokenList(TokenList, String)}
*/
public static void registerTokenList(TokenList tokenList, String fileExtension)
{
ParsingRegistry.registerTokenList(tokenList, fileExtension);
}
/**
* Restores a colorizer to its defaults
*
* @param language
*/
public static void restoreDefaultColorization(String language)
{
colorizerReader.restoreDefault(language);
}
/**
* Sets the pref id
*
* @param language
* @param preferenceId
*/
public static void setPreferenceId(String language, String preferenceId)
{
colorizerReader.setPreferenceId(language, preferenceId);
}
/**
* Unregisters a language colorizer
*
* @param language
*/
public static void unregisterLanguageColorizer(String language)
{
LanguageColorizer curr = languageColorizers.remove(language);
if (curr != null)
{
LanguageColorizer colorizer = new LanguageColorizer(curr.getLanguage());
curr.setCategoryColorizers(colorizer);
curr.setTokenColorizers(colorizer);
curr.setBackground(colorizer.getBackground());
curr.setCaretColor(colorizer.getCaretColor());
curr.setLineHighlightColor(colorizer.getLineHighlightColor());
curr.setSelectionBackground(colorizer.getSelectionBackground());
curr.setSelectionForeground(colorizer.getSelectionForeground());
}
}
/**
* Unregisters a language parser
*
* @param language
* @deprecated use {@link ParsingRegistry#unregisterParser(String)}
*/
public static void unregisterParser(String language)
{
ParsingRegistry.unregisterParser(language);
}
/**
* Unregisters a language scanner
*
* @param language
* @deprecated use {@link ParsingRegistry#unregisterScanner(String)}
*/
public static void unregisterScanner(String language)
{
ParsingRegistry.unregisterScanner(language);
}
/**
* Clears the cached token list if it exists in the registry
*
* @param language
* @deprecated use {@link ParsingRegistry#clearTokenList(String)}
*/
public static void clearTokenList(String language)
{
ParsingRegistry.clearTokenList(language);
}
/**
* unregisterTokenList
*
* @param tokenList
* @deprecated use {@link ParsingRegistry#unregisterTokenList(TokenList)}
*/
public static void unregisterTokenList(TokenList tokenList)
{
ParsingRegistry.unregisterTokenList(tokenList);
}
}