// ============================================================================
//
// Copyright (C) 2006-2012 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.core.utils;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
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.ISafeRunnable;
import org.eclipse.core.runtime.Platform;
/**
* Template implementation of a registry reader that creates objects representing registry contents. Typically, an
* extension contains one element, but this reader handles multiple elements per extension.
*
* To start reading the extensions from the registry for an extension point, call the method <code>readRegistry</code>.
*
* To read children of an IConfigurationElement, call the method <code>readElementChildren</code> from your
* implementation of the method <code>readElement</code>, as it will not be done by default.
*
* @since 3.2
*/
public abstract class RegistryReader {
private static Logger log = Logger.getLogger(RegistryReader.class);
protected static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$
private boolean isInitialized;
private final String extensionPointId;
private final String pluginId;
private final IExtensionRegistry registry;
/**
* DOC sgandon class global comment. Detailled comment <br/>
*
* $Id: talend.epf 55206 2011-02-15 17:32:14Z mhirt $
*
*/
public abstract class RegistrySafeRunnable implements ISafeRunnable {
@Override
public void handleException(Throwable exception) {
log.error("error reading extention registry", exception); //$NON-NLS-1$
}
}
/**
* The constructor.
*/
protected RegistryReader(String aPluginId, String anExtensionPoint) {
this.registry = Platform.getExtensionRegistry();
this.pluginId = aPluginId;
this.extensionPointId = anExtensionPoint;
}
/**
* This method extracts description as a subelement of the given element.
*
* @return description string if defined, or empty string if not.
*/
protected String getDescription(IConfigurationElement config) {
IConfigurationElement[] children = config.getChildren(TAG_DESCRIPTION);
if (children.length >= 1) {
return children[0].getValue();
}
return "";//$NON-NLS-1$
}
/**
* Logs the error in the workbench log using the provided text and the information in the configuration element.
*/
protected static void logError(IConfigurationElement element, String text) {
IExtension extension = element.getDeclaringExtension();
StringBuffer buf = new StringBuffer();
buf.append("Plugin " + extension.getNamespaceIdentifier() + ", extension " + extension.getExtensionPointUniqueIdentifier());//$NON-NLS-2$//$NON-NLS-1$
buf.append("\n" + text);//$NON-NLS-1$
logError(0, buf.toString(), null);
}
/*
* Record an error against this plugin's log.
*
* @param aCode
*
* @param aMessage
*
* @param anException
*/
public static void logError(int aCode, String aMessage, Throwable anException) {
// Bundle bundle = FrameworkUtil.getBundle(RegistryReader.class);
log.log(Level.toLevel(aCode), aMessage, anException);
}
/**
* Logs a very common registry error when a required attribute is missing.
*/
protected static void logMissingAttribute(IConfigurationElement element, String attributeName) {
logError(element, "Required attribute '" + attributeName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
}
/**
* Logs a very common registry error when a required child is missing.
*/
protected static void logMissingElement(IConfigurationElement element, String elementName) {
logError(element, "Required sub element '" + elementName + "' not defined");//$NON-NLS-2$//$NON-NLS-1$
}
/**
* Logs a registry error when the configuration element is unknown.
*/
protected static void logUnknownElement(IConfigurationElement element) {
logError(element, "Unknown extension tag found: " + element.getName());//$NON-NLS-1$
}
/**
* Apply a reproducable order to the list of extensions provided, such that the order will not change as extensions
* are added or removed.
*/
protected IExtension[] orderExtensions(IExtension[] extensions) {
// By default, the order is based on plugin id sorted
// in ascending order. The order for a plugin providing
// more than one extension for an extension point is
// dependent in the order listed in the XML file.
IExtension[] sortedExtension = new IExtension[extensions.length];
System.arraycopy(extensions, 0, sortedExtension, 0, extensions.length);
Comparator<IExtension> comparer = new Comparator<IExtension>() {
@Override
public int compare(IExtension arg0, IExtension arg1) {
String s1 = arg0.getNamespaceIdentifier();
String s2 = arg1.getNamespaceIdentifier();
return s1.compareToIgnoreCase(s2);
}
};
Collections.sort(Arrays.asList(sortedExtension), comparer);
return sortedExtension;
}
/**
* Implement this method to read element's attributes. If children should also be read, then implementor is
* responsible for calling <code>readElementChildren</code>. Implementor is also responsible for logging missing
* attributes.
*
* @return true if element was recognized, false if not.
*/
protected abstract boolean readElement(IConfigurationElement element);
/**
* Read the element's children. This is called by the subclass' readElement method when it wants to read the
* children of the element.
*/
protected void readElementChildren(IConfigurationElement element) {
readElements(element.getChildren());
}
/**
* Read each element one at a time by calling the subclass implementation of <code>readElement</code>.
*
* Logs an error if the element was not recognized.
*/
protected void readElements(IConfigurationElement[] elements) {
for (int i = 0; i < elements.length; i++) {
if (!readElement(elements[i])) {
logUnknownElement(elements[i]);
}
}
}
/**
* Read one extension by looping through its configuration elements.
*/
protected void readExtension(IExtension extension) {
readElements(extension.getConfigurationElements());
}
/**
* Start the registry reading process using the supplied plugin ID and extension point.
*/
public void readRegistry() {
if (isInitialized) {
return;
}
synchronized (this) {
if (!isInitialized) {
IExtensionPoint point = registry.getExtensionPoint(pluginId, extensionPointId);
if (point == null) {
return;
}
IExtension[] extensions = point.getExtensions();
extensions = orderExtensions(extensions);
for (IExtension extension : extensions) {
readExtension(extension);
}
isInitialized = true;
}
}
}
}