blob: 6cee6c286904d57cdbe357021bcf37c0c08250b6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.internal.launching;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
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.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.core.internal.environment.LazyFileHandle;
import org.eclipse.dltk.core.internal.environment.LocalEnvironment;
import org.eclipse.dltk.launching.EnvironmentVariable;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.IInterpreterInstallType;
import org.eclipse.dltk.launching.InterpreterStandin;
import org.eclipse.dltk.launching.LaunchingMessages;
import org.eclipse.dltk.launching.LibraryLocation;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.launching.ScriptRuntime.DefaultInterpreterEntry;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This is a container for interpreter definitions such as the interpreter
* definitions that are stored in the workbench preferences.
* <p>
* An instance of this class may be obtained from an XML document by calling
* <code>parseXMLIntoContainer</code>.
* </p>
* <p>
* An instance of this class may be translated into an XML document by calling
* <code>getAsXML</code>.
* </p>
* <p>
* Clients may instantiate this class; it is not intended to be subclassed.
* </p>
*/
@SuppressWarnings("deprecation")
public class InterpreterDefinitionsContainer {
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$
/**
* Map of InterpreterInstallTypes to Lists of corresponding
* InterpreterInstalls.
*/
private Map<IInterpreterInstallType, List<IInterpreterInstall>> fInterTypeToInterMap;
/**
* 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 InterpreterDefinitionsContainer() {
fInterTypeToInterMap = new HashMap<>(10);
// fInvalidInterpreterList = new ArrayList(10);
fInterpreterList = new ArrayList<>(10);
fDefaultInterpreterInstallCompositeID = new HashMap<>();
fDefaultInterpreterInstallConnectorTypeID = new HashMap<>();
}
/**
* Returns list of default interpreters natures TODO: rename
*
* @return
*/
public DefaultInterpreterEntry[] getInterpreterNatures() {
Set<DefaultInterpreterEntry> s = new HashSet<>(
fDefaultInterpreterInstallCompositeID.keySet());
for (IInterpreterInstall install : fInterpreterList) {
s.add(new DefaultInterpreterEntry(install.getNatureId(),
install.getEnvironmentId()));
}
return s.toArray(new DefaultInterpreterEntry[s.size()]);
}
/**
* Add the specified Interpreter to the Interpreter definitions managed by
* this container.
* <p>
* If distinguishing valid from invalid Interpreters is important, the
* specified Interpreter must have already had its install location set. An
* invalid Interpreter is one whose install location doesn't exist.
* </p>
*
* @param interpreter
* the Interpreter to be added to this container
*/
public void addInterpreter(IInterpreterInstall interpreter) {
addInterpreter(interpreter, false);
}
/**
* Add the specified Interpreter to the Interpreter definitions managed by
* this container.
* <p>
* If distinguishing valid from invalid Interpreters is important, the
* specified Interpreter must have already had its install location set. An
* invalid Interpreter is one whose install location doesn't exist.
* </p>
*
* @param interpreter
* the Interpreter to be added to this container
* @param overwrite
* overwite interpreter install anyway
*/
public void addInterpreter(IInterpreterInstall interpreter,
boolean overwrite) {
if (fInterpreterList.contains(interpreter) && overwrite) {
fInterpreterList.remove(interpreter);
}
if (!fInterpreterList.contains(interpreter) || overwrite) {
IInterpreterInstallType interpreterInstallType = interpreter
.getInterpreterInstallType();
List<IInterpreterInstall> interpreterList = fInterTypeToInterMap
.get(interpreterInstallType);
if (interpreterList == null) {
interpreterList = new ArrayList<>(3);
fInterTypeToInterMap.put(interpreterInstallType,
interpreterList);
}
if (interpreterList.contains(interpreter)) {
interpreterList.remove(interpreter);
}
interpreterList.add(interpreter);
// IFileHandle installLocation = Interpreter.getInstallLocation();
// if (installLocation == null
// || !InterpreterInstallType.validateInstallLocation(
// installLocation).isOK()) {
// fInvalidInterpreterList.add(Interpreter);
// }
fInterpreterList.add(interpreter);
}
}
/**
* Add all Interpreter's in the specified list to the Interpreter
* definitions managed by this container.
* <p>
* If distinguishing valid from invalid Interpreters is important, the
* specified Interpreters must have already had their install locations set.
* An invalid Interpreter is one whose install location doesn't exist.
* </p>
*
* @param interpreterList
* a list of Interpreters to be added to this container
*/
public void addInterpreterList(List<IInterpreterInstall> interpreterList) {
Iterator<IInterpreterInstall> iterator = interpreterList.iterator();
while (iterator.hasNext()) {
IInterpreterInstall Interpreter = iterator.next();
addInterpreter(Interpreter, false);
}
}
/**
* Return a mapping of Interpreter install types to lists of Interpreters.
* The keys of this map are instances of
* <code>IInterpreterInstallType</code>. The values are instances of
* <code>java.util.List</code> which contain instances of
* <code>IInterpreterInstall</code>.
*
* @return Map the mapping of Interpreter install types to lists of
* Interpreters
*/
public Map<IInterpreterInstallType, List<IInterpreterInstall>> getInterpreterTypeToInterpreterMap() {
return fInterTypeToInterMap;
}
/**
* Return a list of all Interpreters in this container, including any
* invalid Interpreters. An invalid Interpreter is one whose install
* location does not exist on the file system. The order of the list is not
* specified.
*
* @return List the data structure containing all Interpreters managed by
* this container
*/
public List<IInterpreterInstall> getInterpreterList() {
return fInterpreterList;
}
/**
* Return filtered list of all Interpreters in this container, including any
* invalid Interpreters. An invalid Interpreter is one whose install
* location does not exist on the file system. The order of the list is not
* specified.
*
* @return List the data structure containing all Interpreters managed by
* this container
*/
public List<IInterpreterInstall> getInterpreterList(
DefaultInterpreterEntry nature) {
List<IInterpreterInstall> res = new ArrayList<>(
fInterpreterList.size());
for (IInterpreterInstall interpreter : fInterpreterList) {
final String environmentId = interpreter.getEnvironmentId();
if (environmentId != null
&& interpreter.getInterpreterInstallType().getNatureId()
.equals(nature.getNature())
&& environmentId.equals(nature.getEnvironment()))
res.add(interpreter);
}
return res;
}
/**
* Return a list of all valid Interpreters in this container. A valid
* Interpreter is one whose install location exists on the file system. The
* order of the list is not specified.
*
* @return List
*/
public List<IInterpreterInstall> getValidInterpreterList() {
List<IInterpreterInstall> Interpreters = getInterpreterList();
List<IInterpreterInstall> resultList = new ArrayList<>(
Interpreters.size());
resultList.addAll(Interpreters);
// resultList.removeAll(fInvalidInterpreterList);
return resultList;
}
/**
* Return filtered list of valid Interpreters in this container. A valid
* Interpreter is one whose install location exists on the file system. The
* order of the list is not specified.
*
* @return List
*/
public List<IInterpreterInstall> getValidInterpreterList(
DefaultInterpreterEntry nature) {
List<IInterpreterInstall> interpreters = getInterpreterList(nature);
List<IInterpreterInstall> resultList = new ArrayList<>(
interpreters.size());
resultList.addAll(interpreters);
// resultList.removeAll(fInvalidInterpreterList);
return resultList;
}
/**
* 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
*/
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);
final Comparator<DefaultInterpreterEntry> comparator = (entry0,
entry1) -> {
String k0 = entry0.getEnvironment() + ":" + entry0.getNature(); //$NON-NLS-1$
String k1 = entry1.getEnvironment() + ":" + entry1.getNature(); //$NON-NLS-1$
return k0.compareTo(k1);
};
// Set the defaultInterpreter attribute on the top-level node
List<DefaultInterpreterEntry> keys = new ArrayList<>();
keys.addAll(fDefaultInterpreterInstallCompositeID.keySet());
Collections.sort(keys, comparator);
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<>();
keys2.addAll(fDefaultInterpreterInstallConnectorTypeID.keySet());
Collections.sort(keys2, comparator);
// 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);
}
final String InterpreterArgs = interpreter.getInterpreterArgs();
if (InterpreterArgs != null && InterpreterArgs.length() > 0) {
element.setAttribute(IARGS_ATTR, InterpreterArgs);
}
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;
}
public static InterpreterDefinitionsContainer parseXMLIntoContainer(
Reader inputStream) throws IOException {
InterpreterDefinitionsContainer container = new InterpreterDefinitionsContainer();
parseXMLIntoContainer(inputStream, container);
return container;
}
/**
* Parse the Interpreter definitions contained in the specified InputStream
* into the specified container.
* <p>
* The Interpreters in the returned container are instances of
* <code>InterpreterStandin</code>.
* </p>
* <p>
* This method has no side-effects. That is, no notifications are sent for
* Interpreter adds, changes, deletes, and the workbench preferences are not
* affected.
* </p>
* <p>
* If the <code>getAsXML</code> method is called on the returned container
* object, the resulting XML will be sematically equivalent (though not
* necessarily syntactically equivalent) as the XML contained in
* <code>inputStream</code>.
* </p>
*
* @param inputStream
* the <code>InputStream</code> containing XML that declares a
* set of Interpreters and a default Interpreter
* @param container
* the container to add the Interpreter defs to
* @return InterpreterDefinitionsContainer a container for the Interpreter
* objects declared in <code>inputStream</code>
* @throws IOException
* if this method fails. Reasons include:
* <ul>
* <li>the XML in <code>inputStream</code> was badly
* formatted</li>
* <li>the top-level node was not 'InterpreterSettings'</li>
* </ul>
*
*/
public static void parseXMLIntoContainer(Reader inputStream,
InterpreterDefinitionsContainer container) throws IOException {
Element config = null;
// Wrapper the stream for efficient parsing
try (BufferedReader stream = new BufferedReader(inputStream)) {
// Do the parsing and obtain the top-level node
DocumentBuilder parser = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
parser.setErrorHandler(new DefaultHandler());
config = parser.parse(new InputSource(stream)).getDocumentElement();
} catch (SAXException e) {
throw new IOException(LaunchingMessages.ScriptRuntime_badFormat);
} catch (ParserConfigurationException e) {
throw new IOException(LaunchingMessages.ScriptRuntime_badFormat);
}
// If the top-level node wasn't what we expected, bail out
if (!config.getNodeName().equalsIgnoreCase(INTERPRETER_SETTINGS_TAG)) {
throw new IOException(LaunchingMessages.ScriptRuntime_badFormat);
}
// Traverse the parsed structure and populate the InterpreterType to
// Interpreter Map
NodeList list = config.getChildNodes();
int length = list.getLength();
for (int i = 0; i < length; ++i) {
Node node = list.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element interpreterTypeElement = (Element) node;
if (interpreterTypeElement.getNodeName()
.equalsIgnoreCase(INTERPRETER_TYPE_TAG)) {
populateInterpreterTypes(interpreterTypeElement, container);
}
if (interpreterTypeElement.getNodeName()
.equalsIgnoreCase(DEFAULT_INTERPRETER_TAG)) {
String nature = interpreterTypeElement
.getAttribute(NATURE_ATTR);
String id = interpreterTypeElement.getAttribute(ID_ATTR);
String environment = interpreterTypeElement
.getAttribute(ENVIRONMENT_ATTR);
if ("".equals(environment)) { //$NON-NLS-1$
environment = LocalEnvironment.ENVIRONMENT_ID;
}
DefaultInterpreterEntry entry = new DefaultInterpreterEntry(
nature, environment);
container.setDefaultInterpreterInstallCompositeID(entry,
id);
}
if (interpreterTypeElement.getNodeName()
.equalsIgnoreCase("defaultInterpreterConnector")) { //$NON-NLS-1$
String nature = interpreterTypeElement
.getAttribute(NATURE_ATTR);
String environment = interpreterTypeElement
.getAttribute(ENVIRONMENT_ATTR);
String id = interpreterTypeElement.getAttribute(ID_ATTR);
DefaultInterpreterEntry entry = new DefaultInterpreterEntry(
nature, environment);
container.setDefaultInterpreterInstallConnectorTypeID(entry,
id);
}
}
}
}
/**
* For the specified Interpreter type node, parse all subordinate
* Interpreter definitions and add them to the specified container.
*/
private static void populateInterpreterTypes(Element interpreterTypeElement,
InterpreterDefinitionsContainer container) {
// Retrieve the 'id' attribute and the corresponding Interpreter type
// object
String id = interpreterTypeElement.getAttribute(ID_ATTR);
IInterpreterInstallType InterpreterType = ScriptRuntime
.getInterpreterInstallType(id);
if (InterpreterType != null) {
// For each Interpreter child node, populate the container with a
// subordinate node
NodeList InterpreterNodeList = interpreterTypeElement
.getChildNodes();
for (int i = 0; i < InterpreterNodeList.getLength(); ++i) {
Node InterpreterNode = InterpreterNodeList.item(i);
short type = InterpreterNode.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element InterpreterElement = (Element) InterpreterNode;
if (InterpreterElement.getNodeName()
.equalsIgnoreCase(INTERPRETER_TAG)) {
populateInterpreterForType(InterpreterType,
InterpreterElement, container);
}
}
}
} else {
DLTKLaunchingPlugin.log(NLS.bind(
"Interpreter type element with unknown id \"{0}\".", id)); //$NON-NLS-1$
}
}
/**
* Parse the specified Interpreter node, create a InterpreterStandin for it,
* and add this to the specified container.
*/
private static void populateInterpreterForType(
IInterpreterInstallType installType, Element element,
InterpreterDefinitionsContainer container) {
String id = element.getAttribute(ID_ATTR);
if (id != null) {
// Retrieve the 'path' attribute. If none, skip this node.
String installPath = element.getAttribute(PATH_ATTR);
if (installPath == null) {
return;
}
String envId = element.getAttribute(ENVIRONMENT_ID);
// IEnvironment env = EnvironmentManager.getEnvironmentById(envId);
// if (env == null) {
// return;
// }
// Create a InterpreterStandin for the node and set its 'name' &
// 'installLocation' attributes
InterpreterStandin standin = new InterpreterStandin(installType,
id);
standin.setName(element.getAttribute(INTERPRETER_NAME_ATTR));
// IFileHandle installLocation = env.getFile(new Path(installPath));
// standin.setInstallLocation(installLocation);
standin.setInstallLocation(
new LazyFileHandle(envId, new Path(installPath)));
container.addInterpreter(standin, false);
// Look for subordinate nodes. These may be 'libraryLocation',
// 'libraryLocations' or 'versionInfo'.
NodeList list = element.getChildNodes();
int length = list.getLength();
for (int i = 0; i < length; ++i) {
Node node = list.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element subElement = (Element) node;
String subElementName = subElement.getNodeName();
if (subElementName.equals(LIBRARY_LOCATION_TAG)) {
LibraryLocation loc = getLibraryLocation(subElement);
standin.setLibraryLocations(
new LibraryLocation[] { loc });
} else if (subElementName.equals(LIBRARY_LOCATIONS_TAG)) {
setLibraryLocations(standin, subElement);
} else if (subElementName
.equals(ENVIRONMENT_VARIABLE_TAG)) {
EnvironmentVariable var = getEnvironmentVariable(
subElement);
standin.setEnvironmentVariables(
new EnvironmentVariable[] { var });
} else if (subElementName
.equals(ENVIRONMENT_VARIABLES_TAG)) {
setEnvironmentVariables(standin, subElement);
} else if (subElementName.equals(EXTENSIONS_TAG)) {
StringBuffer body = null;
NodeList children = subElement.getChildNodes();
for (int j = 0; j < children.getLength(); ++j) {
Node child = children.item(j);
if (child
.getNodeType() == Node.CDATA_SECTION_NODE) {
if (body == null) {
body = new StringBuffer();
}
body.append(((CharacterData) child).getData());
}
}
if (body != null) {
standin.loadExtensions(body.toString());
}
}
}
}
// Interpreter Arguments
String args = element.getAttribute(IARGS_ATTR);
if (args != null && args.length() > 0) {
standin.setInterpreterArgs(args);
}
} else {
DLTKLaunchingPlugin.log(
"id attribute missing from Interpreter element specification."); //$NON-NLS-1$
}
}
/**
* Create & return a LibraryLocation object populated from the attribute
* values in the specified node.
*/
private static LibraryLocation getLibraryLocation(
Element libLocationElement) {
String interpreterEnvironmentArchive = libLocationElement
.getAttribute(LIBRARY_PATH_ATTR);
if (interpreterEnvironmentArchive != null) {
return new LibraryLocation(
Path.fromPortableString(interpreterEnvironmentArchive));
}
DLTKLaunchingPlugin
.log("Library location element is specified incorrectly."); //$NON-NLS-1$
return null;
}
private static EnvironmentVariable getEnvironmentVariable(
Element libLocationElement) {
String name = libLocationElement.getAttribute(VARIABLE_NAME_ATTR);
String value = libLocationElement.getAttribute(VARIABLE_VALUE_ATTR);
if (name != null && value != null) {
return new EnvironmentVariable(name, value);
}
DLTKLaunchingPlugin
.log("Environment variable element is specified incorrectly."); //$NON-NLS-1$
return null;
}
/**
* Set the LibraryLocations on the specified Interpreter, by extracting the
* subordinate nodes from the specified 'lirbaryLocations' node.
*/
private static void setLibraryLocations(IInterpreterInstall interpreter,
Element libLocationsElement) {
NodeList list = libLocationsElement.getChildNodes();
int length = list.getLength();
List<LibraryLocation> locations = new ArrayList<>(length);
for (int i = 0; i < length; ++i) {
Node node = list.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element libraryLocationElement = (Element) node;
if (libraryLocationElement.getNodeName()
.equals(LIBRARY_LOCATION_TAG)) {
locations.add(getLibraryLocation(libraryLocationElement));
}
}
}
interpreter.setLibraryLocations(
locations.toArray(new LibraryLocation[locations.size()]));
}
private static void setEnvironmentVariables(IInterpreterInstall interpreter,
Element environmentVariablesElement) {
NodeList list = environmentVariablesElement.getChildNodes();
int length = list.getLength();
List<EnvironmentVariable> variables = new ArrayList<>(length);
for (int i = 0; i < length; ++i) {
Node node = list.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element envVarElement = (Element) node;
if (envVarElement.getNodeName()
.equals(ENVIRONMENT_VARIABLE_TAG)) {
variables.add(getEnvironmentVariable(envVarElement));
}
}
}
interpreter.setEnvironmentVariables(
variables.toArray(new EnvironmentVariable[variables.size()]));
}
/**
* Removes the Interpreter from this container.
*
* @param interpreter
* Interpreter intall
*/
public void removeInterpreter(IInterpreterInstall interpreter) {
fInterpreterList.remove(interpreter);
// fInvalidInterpreterList.remove(Interpreter);
List<IInterpreterInstall> list = fInterTypeToInterMap
.get(interpreter.getInterpreterInstallType());
if (list != null) {
list.remove(interpreter);
}
}
}