/*******************************************************************************
* Copyright (c) 2012 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.koneki.ldt.debug.ui.internal.interpreters;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
import org.eclipse.dltk.internal.launching.IInterpreterInstallExtensionContainer;
import org.eclipse.dltk.internal.launching.InterpreterDefinitionsContainer;
import org.eclipse.dltk.launching.EnvironmentVariable;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.IInterpreterInstallType;
import org.eclipse.dltk.launching.LibraryLocation;
import org.eclipse.dltk.launching.ScriptRuntime.DefaultInterpreterEntry;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/////////////////////////////////////////////////////////////////////////////////////
// This code contains a lot of code copied from org.eclipse.dltk.internal.launching.InterpreterDefinitionsContainer
// to workaround DLTK BUG 390358
/////////////////////////////////////////////////////////////////////////////////////
//CHECKSTYLE:OFF
public class LuaInterpreterDefinitionsContainer extends InterpreterDefinitionsContainer {
private final class DefaultInterpreterComparator implements Comparator<DefaultInterpreterEntry> {
public int compare(DefaultInterpreterEntry entry0, DefaultInterpreterEntry entry1) {
String k0 = entry0.getEnvironment() + ":" + entry0.getNature(); //$NON-NLS-1$
String k1 = entry1.getEnvironment() + ":" + entry1.getNature(); //$NON-NLS-1$
return k0.compareTo(k1);
}
}
private static final String PATH_ATTR = "path"; //$NON-NLS-1$
private static final String INTERPRETER_NAME_ATTR = "name"; //$NON-NLS-1$
private static final String INTERPRETER_TAG = "interpreter"; //$NON-NLS-1$
private static final String INTERPRETER_TYPE_TAG = "interpreterType"; //$NON-NLS-1$
private static final String ID_ATTR = "id"; //$NON-NLS-1$
private static final String NATURE_ATTR = "nature"; //$NON-NLS-1$
private static final String ENVIRONMENT_ATTR = "environment"; //$NON-NLS-1$
private static final String DEFAULT_INTERPRETER_TAG = "defaultInterpreter"; //$NON-NLS-1$
private static final String INTERPRETER_SETTINGS_TAG = "interpreterSettings"; //$NON-NLS-1$
private static final String VARIABLE_VALUE_ATTR = "variableValue"; //$NON-NLS-1$
private static final String VARIABLE_NAME_ATTR = "variableName"; //$NON-NLS-1$
private static final String LIBRARY_PATH_ATTR = "libraryPath"; //$NON-NLS-1$
private static final String IARGS_ATTR = "iargs"; //$NON-NLS-1$
private static final String ENVIRONMENT_VARIABLES_TAG = "environmentVariables"; //$NON-NLS-1$
private static final String ENVIRONMENT_VARIABLE_TAG = "environmentVariable"; //$NON-NLS-1$
private static final String LIBRARY_LOCATIONS_TAG = "libraryLocations"; //$NON-NLS-1$
private static final String LIBRARY_LOCATION_TAG = "libraryLocation"; //$NON-NLS-1$
private static final String ENVIRONMENT_ID = "environmentId"; //$NON-NLS-1$
private static final String EXTENSIONS_TAG = "extensions"; //$NON-NLS-1$
/**
* Cached list of Interpreters in this container
*/
private List<IInterpreterInstall> fInterpreterList;
// /**
// * Interpreters managed by this container whose install locations don't
// * actually exist.
// */
// private List fInvalidInterpreterList;
/**
* The composite identifier of the default Interpreter. This consists of the install type ID plus an ID for the Interpreter.
*/
// map bind default interpreter to each nature
private Map<DefaultInterpreterEntry, String> fDefaultInterpreterInstallCompositeID;
/**
* The identifier of the connector to use for the default Interpreter.
*/
// map bind default connector to each nature
private Map<DefaultInterpreterEntry, String> fDefaultInterpreterInstallConnectorTypeID;
/**
* Constructs an empty Interpreter container
*/
public LuaInterpreterDefinitionsContainer() {
new ArrayList<Object>(10);
fInterpreterList = new ArrayList<IInterpreterInstall>(10);
fDefaultInterpreterInstallCompositeID = new HashMap<DefaultInterpreterEntry, String>();
fDefaultInterpreterInstallConnectorTypeID = new HashMap<DefaultInterpreterEntry, String>();
}
/**
* Returns list of default interpreters natures TODO: rename
*
* @return
*/
public DefaultInterpreterEntry[] getInterpreterNatures() {
Set<DefaultInterpreterEntry> s = new HashSet<DefaultInterpreterEntry>(fDefaultInterpreterInstallCompositeID.keySet());
for (IInterpreterInstall install : fInterpreterList) {
s.add(new DefaultInterpreterEntry(install.getNatureId(), install.getEnvironmentId()));
}
return s.toArray(new DefaultInterpreterEntry[s.size()]);
}
/**
* Returns the composite ID for the default Interpreter. The composite ID consists of an ID for the Interpreter install type together with an ID
* for Interpreter. This is necessary because Interpreter ids by themselves are not necessarily unique across Interpreter install types.
*
* @return String returns the composite ID of the current default Interpreter
*/
public String getDefaultInterpreterInstallCompositeID(DefaultInterpreterEntry nature) {
return fDefaultInterpreterInstallCompositeID.get(nature);
}
public String[] getDefaultInterpreterInstallCompositeID() {
Collection<String> ids = fDefaultInterpreterInstallCompositeID.values();
return ids.toArray(new String[ids.size()]);
}
/**
* Sets the composite ID for the default Interpreter. The composite ID consists of an ID for the Interpreter install type together with an ID for
* Interpreter. This is necessary because Interpreter ids by themselves are not necessarily unique across Interpreter install types.
*
* @param id
* identifies the new default Interpreter using a composite ID
*/
public void setDefaultInterpreterInstallCompositeID(DefaultInterpreterEntry nature, String id) {
if (id != null)
fDefaultInterpreterInstallCompositeID.put(nature, id);
else
fDefaultInterpreterInstallCompositeID.remove(nature);
}
/**
* Return the default Interpreter's connector type ID.
*
* @return String the current value of the default Interpreter's connector type ID
*/
public String getDefaultInterpreterInstallConnectorTypeID(DefaultInterpreterEntry nature) {
return fDefaultInterpreterInstallConnectorTypeID.get(nature);
}
/**
* Set the default Interpreter's connector type ID.
*
* @param id
* the new value of the default Interpreter's connector type ID
*/
public void setDefaultInterpreterInstallConnectorTypeID(DefaultInterpreterEntry nature, String id) {
fDefaultInterpreterInstallConnectorTypeID.put(nature, id);
}
/**
* Return the Interpreter definitions contained in this object as a String of XML. The String is suitable for storing in the workbench
* preferences.
* <p>
* The resulting XML is compatible with the static method <code>parseXMLIntoContainer</code>.
* </p>
*
* @return String the results of flattening this object into XML
* @throws IOException
* if this method fails. Reasons include:
* <ul>
* <li>serialization of the XML document failed</li>
* </ul>
* @throws ParserConfigurationException
* if creation of the XML document failed
* @throws TransformerException
* if serialization of the XML document failed
*/
@Override
public String getAsXML() throws ParserConfigurationException, IOException, TransformerException {
// Create the Document and the top-level node
Document doc = DLTKLaunchingPlugin.getDocument();
Element config = doc.createElement(INTERPRETER_SETTINGS_TAG);
doc.appendChild(config);
// Set the defaultInterpreter attribute on the top-level node
List<DefaultInterpreterEntry> keys = new ArrayList<DefaultInterpreterEntry>();
keys.addAll(fDefaultInterpreterInstallCompositeID.keySet());
Collections.sort(keys, new DefaultInterpreterComparator());
for (Iterator<DefaultInterpreterEntry> iter = keys.iterator(); iter.hasNext();) {
DefaultInterpreterEntry entry = iter.next();
Element defaulte = doc.createElement(DEFAULT_INTERPRETER_TAG);
config.appendChild(defaulte);
defaulte.setAttribute(NATURE_ATTR, entry.getNature());
defaulte.setAttribute(ENVIRONMENT_ATTR, entry.getEnvironment());
defaulte.setAttribute(ID_ATTR, fDefaultInterpreterInstallCompositeID.get(entry));
}
List<DefaultInterpreterEntry> keys2 = new ArrayList<DefaultInterpreterEntry>();
keys2.addAll(fDefaultInterpreterInstallConnectorTypeID.keySet());
Collections.sort(keys2, new DefaultInterpreterComparator());
// Set the defaultInterpreterConnector attribute on the top-level node
for (Iterator<DefaultInterpreterEntry> iter = keys2.iterator(); iter.hasNext();) {
DefaultInterpreterEntry entry = iter.next();
Element defaulte = doc.createElement("defaultInterpreterConnector"); //$NON-NLS-1$
config.appendChild(defaulte);
defaulte.setAttribute(NATURE_ATTR, entry.getNature());
defaulte.setAttribute(ENVIRONMENT_ATTR, entry.getEnvironment());
defaulte.setAttribute(ID_ATTR, fDefaultInterpreterInstallConnectorTypeID.get(entry));
}
// Create a node for each install type represented in this container
Set<IInterpreterInstallType> InterpreterInstallTypeSet = getInterpreterTypeToInterpreterMap().keySet();
Iterator<IInterpreterInstallType> keyIterator = InterpreterInstallTypeSet.iterator();
while (keyIterator.hasNext()) {
IInterpreterInstallType InterpreterInstallType = keyIterator.next();
Element InterpreterTypeElement = interpreterTypeAsElement(doc, InterpreterInstallType);
config.appendChild(InterpreterTypeElement);
}
// Serialize the Document and return the resulting String
return DLTKLaunchingPlugin.serializeDocument(doc);
}
/**
* Create and return a node for the specified Interpreter install type in the specified Document.
*/
private Element interpreterTypeAsElement(Document doc, IInterpreterInstallType InterpreterType) {
// Create a node for the Interpreter type and set its 'id' attribute
Element element = doc.createElement(INTERPRETER_TYPE_TAG);
element.setAttribute(ID_ATTR, InterpreterType.getId());
// For each Interpreter of the specified type, create a subordinate node
// for it
List<IInterpreterInstall> InterpreterList = getInterpreterTypeToInterpreterMap().get(InterpreterType);
Iterator<IInterpreterInstall> InterpreterIterator = InterpreterList.iterator();
while (InterpreterIterator.hasNext()) {
IInterpreterInstall Interpreter = InterpreterIterator.next();
Element InterpreterElement = interpreterAsElement(doc, Interpreter);
element.appendChild(InterpreterElement);
}
return element;
}
/**
* Create and return a node for the specified Interpreter in the specified Document.
*/
private Element interpreterAsElement(Document doc, IInterpreterInstall interpreter) {
// Create the node for the Interpreter and set its 'id' & 'name'
// attributes
Element element = doc.createElement(INTERPRETER_TAG);
element.setAttribute(ID_ATTR, interpreter.getId());
element.setAttribute(INTERPRETER_NAME_ATTR, interpreter.getName());
element.setAttribute(ENVIRONMENT_ID, interpreter.getInstallLocation().getEnvironmentId());
// Determine and set the 'path' attribute for the Interpreter
String installPath = ""; //$NON-NLS-1$
IFileHandle installLocation = interpreter.getRawInstallLocation();
if (installLocation != null) {
installPath = installLocation.getPath().toPortableString();
}
element.setAttribute(PATH_ATTR, installPath);
// If the 'libraryLocations' attribute is specified, create a node for
// it
LibraryLocation[] libraryLocations = interpreter.getLibraryLocations();
if (libraryLocations != null) {
Element libLocationElement = libraryLocationsAsElement(doc, libraryLocations);
element.appendChild(libLocationElement);
}
EnvironmentVariable[] environmentVariables = interpreter.getEnvironmentVariables();
if (environmentVariables != null) {
Element environmentVariableElement = environmentVariablesAsElement(doc, environmentVariables);
element.appendChild(environmentVariableElement);
}
// ///////////////////////////////////////////////////////////////////////////////////
// START HACK CUSTOM CODE
// ///////////////////////////////////////////////////////////////////////////////////
// TODO BUG_ECLIPSE 390358
final String interpreterArgs = interpreter.getInterpreterArgs();
if (interpreterArgs != null && interpreterArgs.length() > 0) {
element.setAttribute(IARGS_ATTR, interpreterArgs);
}
// ///////////////////////////////////////////////////////////////////////////////////
// END HACK CUSTOM CODE
// ///////////////////////////////////////////////////////////////////////////////////
if (interpreter instanceof IInterpreterInstallExtensionContainer) {
String extensions = ((IInterpreterInstallExtensionContainer) interpreter).saveExtensions();
if (extensions != null && extensions.length() != 0) {
final Element extensionsElement = doc.createElement(EXTENSIONS_TAG);
extensionsElement.appendChild(doc.createCDATASection(extensions));
element.appendChild(extensionsElement);
}
}
return element;
}
/**
* Create and return a 'libraryLocations' node. This node owns subordinate nodes that list individual library locations.
*/
private static Element libraryLocationsAsElement(Document doc, LibraryLocation[] locations) {
Element root = doc.createElement(LIBRARY_LOCATIONS_TAG);
for (int i = 0; i < locations.length; i++) {
Element element = doc.createElement(LIBRARY_LOCATION_TAG);
element.setAttribute(LIBRARY_PATH_ATTR, locations[i].getLibraryPath().toString());
root.appendChild(element);
}
return root;
}
private static Element environmentVariablesAsElement(Document doc, EnvironmentVariable[] variables) {
Element root = doc.createElement(ENVIRONMENT_VARIABLES_TAG);
for (int i = 0; i < variables.length; i++) {
Element element = doc.createElement(ENVIRONMENT_VARIABLE_TAG);
element.setAttribute(VARIABLE_NAME_ATTR, variables[i].getName());
element.setAttribute(VARIABLE_VALUE_ATTR, variables[i].getValue());
root.appendChild(element);
}
return root;
}
}
// CHECKSTYLE:ON