/*******************************************************************************
* Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) 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:
* Thomas Holland - initial API and implementation
*******************************************************************************/
package de.innot.avreclipse.core.targets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IRegistryEventListener;
import org.eclipse.core.runtime.Platform;
import de.innot.avreclipse.AVRPlugin;
/**
* Manages the tools for the target configuration.
* <p>
* This class manages the
* </p>
* <p>
* This class implements the singleton pattern. There is only one instance of this class, accessible
* with {@link #getDefault()}.
* </p>
*
* @author Thomas Holland
* @since 2.4
*
*/
public class ToolManager implements IRegistryEventListener {
private static volatile ToolManager fInstance = null;
private final static String NAMESPACE = AVRPlugin.PLUGIN_ID;
public final static String EXTENSIONPOINT = NAMESPACE + ".targetToolFactories";
private final static String ELEMENT_FACTORY = "toolfactory";
public final static String AVRPROGRAMMERTOOL = "avr.tool.programmer";
public final static String AVRGDBSERVER = "avr.tool.gdbserver";
private Map<String, IToolFactory> fFactoryRegistry;
private Map<String, Long> fInterfaceLastCallMap;
/**
* Get the default tool manager.
*
* @return Default tool manager instance.
*/
public static ToolManager getDefault() {
if (fInstance == null) {
fInstance = new ToolManager();
}
return fInstance;
}
// prevent instantiation
private ToolManager() {
}
/**
* Get a list of all extension point ids used for the target tools.
* <p>
* The list is used by the AVRPlugin class to register the toolmanager as a listener for
* additions/removal of tool extension plugins.
* </p>
*
* @return Array with the unique extension points for the toolmanager.
*/
public String[] getExtensionPointIDs() {
String[] extpoints = new String[1];
extpoints[0] = EXTENSIONPOINT;
return extpoints;
}
/**
* Get the name of the tool with the given id.
* <p>
* This is the same as <code>getTool(targetconfig, id).getName()</code>, but without needing a
* target configuration.
* </p>
*
* @param id
* A tool id vaue
* @return The human readable name of the tool, or <code>null</code> if no tool with the given
* id exists.
*/
public String getToolName(String id) {
String name = null;
Map<String, IToolFactory> registry = getRegistry();
if (registry.containsKey(id)) {
IToolFactory factory = registry.get(id);
name = factory.getName();
}
return name;
}
/**
* Get the tool with the given id for the given hardware configuration.
*
* @param hc
* The hardware configuration the tool is applicable for.
* @param id
* The tool id value.
* @return The tool, or <code>null</code> if no tool exists for the given id.
*/
public ITargetConfigurationTool getTool(ITargetConfiguration hc, String id) {
Map<String, IToolFactory> registry = getRegistry();
ITargetConfigurationTool tool = null;
if (registry.containsKey(id)) {
IToolFactory factory = registry.get(id);
tool = factory.createTool(hc);
}
return tool;
}
/**
* Get an array with the id values of all available tools.
*
* @param tooltype
* Type of tool. If <code>null</code> all tools are returned.
* @return List with tool id values.
*/
public List<String> getAllTools(String tooltype) {
Map<String, IToolFactory> registry = getRegistry();
List<String> resultids = new ArrayList<String>();
for (IToolFactory factory : registry.values()) {
if (tooltype == null || factory.isType(tooltype)) {
resultids.add(factory.getId());
}
}
return resultids;
}
/**
* Remember the system time the given programmer port was last accessed.
*
* @param programmerport
* The name of the port, e.g. <code>/dev/usb</code>
* @param lastfinish
* last access time in ms (from <code>System.currentTimeMillis()</code>)
*/
public synchronized void setLastAccess(String programmerport, long lastfinish) {
if (fInterfaceLastCallMap == null) {
fInterfaceLastCallMap = new HashMap<String, Long>();
}
fInterfaceLastCallMap.put(programmerport, lastfinish);
}
/**
* Get the system time of the last access to the given programmer port.
*
* @param programmerport
* The name of the port, e.g. <code>/dev/usb</code>
* @return the system time (in millis) of the last access, or <code>0</code> if the port has not
* been accessed before.
*/
public synchronized long getLastAccess(String programmerport) {
Long lastfinish = 0L;
if (fInterfaceLastCallMap != null) {
if (fInterfaceLastCallMap.containsKey(programmerport)) {
lastfinish = fInterfaceLastCallMap.get(programmerport);
}
}
return lastfinish;
}
/**
* Load all gdbserverTool extensions.
* <p>
* The list is cached until some extensions are either added or removed
* </p>
*
* @see #added(IExtension[])
*
*/
private Map<String, IToolFactory> getRegistry() {
if (fFactoryRegistry == null) {
fFactoryRegistry = new HashMap<String, IToolFactory>();
IConfigurationElement[] elements = Platform.getExtensionRegistry()
.getConfigurationElementsFor(EXTENSIONPOINT);
for (IConfigurationElement element : elements) {
String type = element.getName();
if (ELEMENT_FACTORY.equalsIgnoreCase(type)) {
// Get an instance of the implementing class
// and add it to the registry
Object obj;
try {
obj = element.createExecutableExtension("class");
} catch (CoreException e) {
// TODO log exception
continue;
}
if (obj instanceof IToolFactory) {
IToolFactory factory = (IToolFactory) obj;
String id = factory.getId();
fFactoryRegistry.put(id, factory);
} else {
// invalid class
// TODO: log exception
}
}
}
}
return fFactoryRegistry;
}
/*
* (non-Javadoc)
* @see
* org.eclipse.core.runtime.IRegistryEventListener#added(org.eclipse.core.runtime.IExtension[])
*/
public void added(IExtension[] extensions) {
// Check if the extensions matches the extension used by this manager.
// To keep things simple we just invalidate the current list of known extensions so that the
// list will be regenerated the next time getTool() is called.
for (IExtension ext : extensions) {
if (ext.getUniqueIdentifier().equals(EXTENSIONPOINT)) {
fFactoryRegistry = null;
}
}
}
/*
* (non-Javadoc)
* @see
* org.eclipse.core.runtime.IRegistryEventListener#added(org.eclipse.core.runtime.IExtensionPoint
* [])
*/
public void added(IExtensionPoint[] extensionPoints) {
// Don't care if any extension points have changed
}
/*
* (non-Javadoc)
* @see
* org.eclipse.core.runtime.IRegistryEventListener#removed(org.eclipse.core.runtime.IExtension
* [])
*/
public void removed(IExtension[] extensions) {
// remove or add doesn't matter for our simple implementation.
added(extensions);
}
/*
* (non-Javadoc)
* @see
* org.eclipse.core.runtime.IRegistryEventListener#removed(org.eclipse.core.runtime.IExtensionPoint
* [])
*/
public void removed(IExtensionPoint[] extensionPoints) {
// Don't care if any extension points have changed
}
}