/*******************************************************************************
* Copyright (c) 2015 Zend Technologies 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:
* Zend Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.php.internal.debug.core.debugger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.*;
import org.eclipse.php.internal.debug.core.Logger;
import org.eclipse.php.internal.debug.core.PHPDebugPlugin;
/**
* Debugger settings providers registry.
*
* @author Bartlomiej Laczkowski
*/
public class DebuggerSettingsProviderRegistry {
private static Map<String, IDebuggerSettingsProvider> providersMap = null;
private class Entry {
IConfigurationElement element;
String id;
String debuggerId;
String overridenProviderId;
public Entry(IConfigurationElement element, String id, String debuggerId, String overridenProviderId) {
this.element = element;
this.id = id;
this.debuggerId = debuggerId;
this.overridenProviderId = overridenProviderId;
}
}
protected static final String PROP_ID = "id"; //$NON-NLS-1$
protected static final String PROP_DEBUGGER_ID = "debuggerId"; //$NON-NLS-1$
protected static final String PROP_OVERRIDES = "overrides"; //$NON-NLS-1$
protected static final String PROP_PROVIDER = "provider"; //$NON-NLS-1$
/**
* The name of extension point to read providers from
*/
public static final String EXTENSION_POINT_ID = PHPDebugPlugin.getDefault().getBundle().getSymbolicName()
+ ".phpDebuggerSettingsProviders"; //$NON-NLS-1$
/**
* The default instance for reading registry.
*/
private static DebuggerSettingsProviderRegistry instance;
/**
* Returns registered providers for given debugger type id.
*
* @param debuggerId
* the related debugger id
* @return a debugger settings provider or <code>null</code>
*/
public static synchronized final IDebuggerSettingsProvider getProvider(String debuggerId) {
Map<String, IDebuggerSettingsProvider> providers = getProviders();
return providers.get(debuggerId);
}
/**
* Returns all registered providers.
*/
protected static final Map<String, IDebuggerSettingsProvider> getProviders() {
if (providersMap == null) {
providersMap = getDefault().readFromExtensionPoint();
}
return providersMap;
}
protected static DebuggerSettingsProviderRegistry getDefault() {
if (instance == null) {
instance = new DebuggerSettingsProviderRegistry();
}
return instance;
}
/**
* Reads the extension point
*/
protected Map<String, IDebuggerSettingsProvider> readFromExtensionPoint() {
final List<Entry> entries = new ArrayList<Entry>();
IConfigurationElement[] configurationElements = Platform.getExtensionRegistry()
.getConfigurationElementsFor(EXTENSION_POINT_ID);
for (final IConfigurationElement element : configurationElements) {
String id = element.getAttribute(PROP_ID);
String overridenProviderId = element.getAttribute(PROP_OVERRIDES);
String debuggerId = element.getAttribute(PROP_DEBUGGER_ID);
entries.add(new Entry(element, id, debuggerId, overridenProviderId));
}
return fetchProviders(entries);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Object createInstance(IConfigurationElement element, String propertyName, Class instanceClass)
throws CoreException {
final Object object = element.createExecutableExtension(propertyName);
if (!instanceClass.isAssignableFrom(object.getClass())) {
String message = String.format("Invalid typecast for %s", element.getAttribute(propertyName)); //$NON-NLS-1$
IStatus status = new Status(IStatus.ERROR, PHPDebugPlugin.getDefault().getBundle().getSymbolicName(),
message);
throw new CoreException(status);
}
return object;
}
private Map<String, IDebuggerSettingsProvider> fetchProviders(List<Entry> entries) {
Map<String, IDebuggerSettingsProvider> providers = new HashMap<String, IDebuggerSettingsProvider>();
List<Entry> highestLevelEntries = new ArrayList<Entry>();
for (Entry entry : entries) {
boolean isHighestLevel = true;
for (Entry e : entries) {
if (entry.id.equals(e.overridenProviderId)) {
isHighestLevel = false;
break;
}
}
if (isHighestLevel)
highestLevelEntries.add(entry);
}
for (Entry entry : highestLevelEntries) {
IDebuggerSettingsProvider provider;
try {
provider = (IDebuggerSettingsProvider) createInstance(entry.element, PROP_PROVIDER,
IDebuggerSettingsProvider.class);
} catch (CoreException e) {
Logger.logException("Could not instantiate debugger settings provider from extension point data.", e); //$NON-NLS-1$
continue;
}
if (provider instanceof AbstractDebuggerSettingsProvider) {
((AbstractDebuggerSettingsProvider) provider).setId(entry.id);
((AbstractDebuggerSettingsProvider) provider).load();
}
providers.put(entry.debuggerId, provider);
}
return providers;
}
}