/**
* 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.parsing.eclipse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
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.osgi.framework.Bundle;
import com.aptana.ide.lexer.ILexer;
import com.aptana.ide.lexer.LexerException;
import com.aptana.ide.lexer.LexerPlugin;
import com.aptana.ide.lexer.TokenList;
import com.aptana.ide.lexer.matcher.MatcherLexerBuilder;
import com.aptana.ide.parsing.IParser;
/**
* Maintains registry of token lists and parsers by language MIME type
*
* @author Kevin Sawicki (ksawicki@aptana.com)
* @author Kevin Lindsey
* @author Chris Williams
*/
public abstract class ParsingRegistry
{
private static final String TOKEN_LIST_ID = "com.aptana.ide.editors.tokenList"; //$NON-NLS-1$
private static final String PARSER_ID = "com.aptana.ide.editors.parser"; //$NON-NLS-1$
private static final String SCANNER_ID = "com.aptana.ide.editors.scanner"; //$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 ATTR_RESOURCE = "resource"; //$NON-NLS-1$
private static final String ATTR_EXTENSION = "extension"; //$NON-NLS-1$
private static final String TAG_PARSER = "parser"; //$NON-NLS-1$
private static final String TAG_SCANNER = "scanner"; //$NON-NLS-1$
private static final String TAG_TOKEN_LIST = "tokenList"; //$NON-NLS-1$
private static final String TAG_TEXT_MATCHER = "textMatcher"; //$NON-NLS-1$
private static Map<String, InstanceCreator> languageTokenLists = new HashMap<String, InstanceCreator>();
private static Map<String, InstanceCreator> extensionTokenLists = new HashMap<String, InstanceCreator>();
private static Map<String, InstanceCreator> languageParsers = new HashMap<String, InstanceCreator>();
private static Map<String, InstanceCreator> languageScanners = new HashMap<String, InstanceCreator>();
/**
* static constructor
*/
static
{
loadAll();
}
public static void clearAll()
{
languageTokenLists.clear();
extensionTokenLists.clear();
}
public static void loadAll()
{
loadTokenLists();
loadParsers();
loadScanners();
}
public static void reloadAll()
{
clearAll();
loadAll();
}
/**
* Creates the parser for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
*/
public static IParser getParser(String language)
{
if (!languageParsers.containsKey(language))
{
return null;
}
InstanceCreator creator = languageParsers.get(language);
return (IParser) creator.getCachedInstance();
}
/**
* Creates the parser for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
*/
public static IParser getScanner(String language)
{
if (!languageScanners.containsKey(language))
return null;
InstanceCreator creator = languageScanners.get(language);
return (IParser) creator.getCachedInstance();
}
/**
* Creates the token list for a language mime type
*
* @param language
* - language mime type
* @return ITokenList
*/
public static TokenList getTokenList(String language)
{
if (!languageTokenLists.containsKey(language))
return null;
InstanceCreator creator = languageTokenLists.get(language);
return (TokenList) creator.getCachedInstance();
}
/**
* getTokenListByExtension
*
* @param extension
* @return - token list
*/
public static TokenList getTokenListByExtension(String extension)
{
if (extension == null || extension.length() <= 0)
return null;
if (extension.startsWith(".")) //$NON-NLS-1$
{
extension = extension.substring(1);
}
if (!extensionTokenLists.containsKey(extension))
return null;
InstanceCreator creator = extensionTokenLists.get(extension);
return (TokenList) creator.getCachedInstance();
}
/**
* createParse
*
* @param language
* @return IParser
*/
public static IParser createParser(String language)
{
if (!languageParsers.containsKey(language))
return null;
InstanceCreator creator = languageParsers.get(language);
return (IParser) creator.createInstance();
}
/**
* createScanner
*
* @param language
* @return IParser
*/
public static IParser createScanner(String language)
{
if (!languageScanners.containsKey(language))
return null;
InstanceCreator creator = languageScanners.get(language);
return (IParser) creator.createInstance();
}
/**
* createTokenList
*
* @param input
* @return TokenList or null
* @throws LexerException
*/
public static TokenList createTokenList(InputStream input) throws LexerException
{
if (input == null)
return null;
// create lexer builder
MatcherLexerBuilder builder = new MatcherLexerBuilder();
// read input stream
builder.loadXML(input);
// finalize lexer
ILexer lexer = builder.buildLexer();
// get a list of languages
String[] languages = lexer.getLanguages();
// grab the first (and only) language token list
if (languages != null && languages.length > 0)
{
return (TokenList) lexer.getTokenList(languages[0]);
}
return null;
}
/**
* createTokenList
*
* @param language
* @return TokenList
*/
public static TokenList createTokenList(String language)
{
if (!languageTokenLists.containsKey(language))
return null;
InstanceCreator creator = languageTokenLists.get(language);
return (TokenList) creator.createInstance();
}
/**
* hasParser
*
* @param language
* @return boolean
*/
public static boolean hasParser(String language)
{
return languageParsers.containsKey(language);
}
/**
* hasScanner
*
* @param language
* @return boolean
*/
public static boolean hasScanner(String language)
{
return languageScanners.containsKey(language);
}
/**
* hasTokenList
*
* @param language
* @return boolean
*/
public static boolean hasTokenList(String language)
{
return languageTokenLists.containsKey(language);
}
/**
* loadTokenLists
*/
private static void loadTokenLists()
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint(TOKEN_LIST_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();
InstanceCreator instance = null;
String language = null;
String fileExtension = null;
if (!isActivityEnabled(element))
{
// Do nothing because this extension should not work.
continue;
}
else if (elementName.equals(TAG_TOKEN_LIST) && LexerPlugin.useCodeBasedLexer())
{
String tokenListClass = element.getAttribute(ATTR_CLASS);
language = element.getAttribute(ATTR_LANGUAGE);
fileExtension = element.getAttribute(ATTR_EXTENSION);
if (fileExtension != null && fileExtension.startsWith(".")) //$NON-NLS-1$
{
fileExtension = fileExtension.substring(1);
}
if (tokenListClass != null && language != null && language.length() > 0)
{
instance = new InstanceCreator(element, ATTR_CLASS);
}
}
else if (elementName.equals(TAG_TEXT_MATCHER) && LexerPlugin.useMatcherLexer())
{
String resourceName = element.getAttribute(ATTR_RESOURCE);
language = element.getAttribute(ATTR_LANGUAGE);
fileExtension = element.getAttribute(ATTR_EXTENSION);
if (fileExtension != null && fileExtension.startsWith(".")) //$NON-NLS-1$
{
fileExtension = fileExtension.substring(1);
}
if (resourceName != null && language != null && language.length() > 0)
{
instance = new InstanceCreator(element, resourceName)
{
public Object createInstance()
{
IExtension ext = element.getDeclaringExtension();
String pluginId = ext.getNamespaceIdentifier();
Bundle bundle = Platform.getBundle(pluginId);
URL resource = bundle.getResource(this.attributeName);
if (resource == null)
{
resource = bundle.getEntry(this.attributeName);
}
try
{
InputStream input = resource.openStream();
return createTokenList(input);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (LexerException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
};
}
}
if (instance != null)
{
languageTokenLists.put(language, instance);
if (fileExtension != null)
{
extensionTokenLists.put(fileExtension, instance);
}
}
}
}
}
}
private static boolean isActivityEnabled(IConfigurationElement element)
{
// TODO Auto-generated method stub
return true;
}
/**
* loadParsers
*/
private static void loadParsers()
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint(PARSER_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_PARSER))
{
String parserClass = element.getAttribute(ATTR_CLASS);
String language = element.getAttribute(ATTR_LANGUAGE);
if (parserClass != null && language != null && language.length() > 0)
{
InstanceCreator creator = new InstanceCreator(element, ATTR_CLASS);
languageParsers.put(language, creator);
}
}
}
}
}
}
/**
* loadScanners
*/
private static void loadScanners()
{
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint(SCANNER_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_SCANNER))
{
String parserClass = element.getAttribute(ATTR_CLASS);
String language = element.getAttribute(ATTR_LANGUAGE);
if (parserClass != null && language != null && language.length() > 0)
{
InstanceCreator creator = new InstanceCreator(element, ATTR_CLASS);
languageScanners.put(language, creator);
}
}
}
}
}
}
/**
* registerParser
*
* @param language
* @param parser
*/
public static void registerParser(String language, IParser parser)
{
if (languageParsers.containsKey(language) == false)
{
InstanceCreator creator = new InstanceCreator(null, null);
creator.setCache(parser);
languageParsers.put(language, creator);
}
else
{
InstanceCreator creator = languageParsers.get(language);
creator.setCache(parser);
}
}
/**
* registerScanner
*
* @param language
* @param parser
*/
public static void registerScanner(String language, IParser parser)
{
if (languageScanners.containsKey(language) == false)
{
InstanceCreator creator = new InstanceCreator(null, null);
creator.setCache(parser);
languageScanners.put(language, creator);
}
else
{
InstanceCreator creator = languageScanners.get(language);
creator.setCache(parser);
}
}
/**
* registerTokenList
*
* @param tokenList
*/
public static void registerTokenList(TokenList tokenList)
{
registerTokenList(tokenList, null);
}
/**
* registerTokenList
*
* @param tokenList
* @param fileExtension
*/
public static void registerTokenList(TokenList tokenList, String fileExtension)
{
String language = tokenList.getLanguage();
if (languageTokenLists.containsKey(language) == false)
{
InstanceCreator creator = new InstanceCreator(null, null);
creator.setCache(tokenList);
languageTokenLists.put(language, creator);
}
else
{
InstanceCreator creator = languageTokenLists.get(language);
creator.setCache(tokenList);
}
if (fileExtension != null && fileExtension.length() > 0)
{
if (fileExtension.startsWith(".")) //$NON-NLS-1$
{
fileExtension = fileExtension.substring(1);
}
if (extensionTokenLists.containsKey(fileExtension) == false)
{
InstanceCreator creator = new InstanceCreator(null, null);
creator.setCache(tokenList);
extensionTokenLists.put(fileExtension, creator);
}
else
{
InstanceCreator creator = extensionTokenLists.get(fileExtension);
creator.setCache(tokenList);
}
}
}
/**
* Unregisters a language parser
*
* @param language
*/
public static void unregisterParser(String language)
{
languageParsers.remove(language);
}
/**
* Unregisters a language scanner
*
* @param language
*/
public static void unregisterScanner(String language)
{
languageScanners.remove(language);
}
/**
* Clears the cached token list if it exists in the registry
*
* @param language
*/
public static void clearTokenList(String language)
{
if (languageTokenLists.containsKey(language))
{
InstanceCreator creator = languageTokenLists.get(language);
creator.setCache(null);
}
}
/**
* unregisterTokenList
*
* @param tokenList
*/
public static void unregisterTokenList(TokenList tokenList)
{
languageTokenLists.remove(tokenList.getLanguage());
}
}