/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Frits Jalvingh - Contribution for Bug 459831 - [launching] Support attaching
 *     	external annotations to a JRE container
 *******************************************************************************/
package org.eclipse.jdt.internal.launching;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.LibraryLocation;
import org.eclipse.jdt.launching.VMStandin;
import org.eclipse.osgi.util.NLS;
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 VM definitions such as the VM 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>
 *
 * @since 2.1
 */
public class VMDefinitionsContainer {

	/**
	 * Map of VMInstallTypes to Lists of corresponding VMInstalls.
	 */
	private Map<IVMInstallType, List<IVMInstall>> fVMTypeToVMMap;

	/**
	 * Cached list of VMs in this container
	 */
	private List<IVMInstall> fVMList;

	/**
	 * VMs managed by this container whose install locations don't actually exist.
	 */
	private List<IVMInstall> fInvalidVMList;

	/**
	 * The composite identifier of the default VM.  This consists of the install type ID
	 * plus an ID for the VM.
	 */
	private String fDefaultVMInstallCompositeID;

	/**
	 * The identifier of the connector to use for the default VM.
	 */
	private String fDefaultVMInstallConnectorTypeID;

	/**
	 * Contains any error/information status of parsing XML
	 */
	private MultiStatus fStatus;

	/**
	 * Constructs an empty VM container
	 */
	public VMDefinitionsContainer() {
		fVMTypeToVMMap = new HashMap<>(10);
		fInvalidVMList = new ArrayList<>(10);
		fVMList = new ArrayList<>(10);
	}

	/**
	 * Add the specified VM to the VM definitions managed by this container.
	 * <p>
	 * If distinguishing valid from invalid VMs is important, the specified VM must
	 * have already had its install location set.  An invalid VM is one whose install
	 * location doesn't exist.
	 * </p>
	 *
	 * @param vm the VM to be added to this container
	 */
	public void addVM(IVMInstall vm) {
		if (!fVMList.contains(vm)) {
			IVMInstallType vmInstallType = vm.getVMInstallType();
			List<IVMInstall> vmList = fVMTypeToVMMap.get(vmInstallType);
			if (vmList == null) {
				vmList = new ArrayList<>(3);
				fVMTypeToVMMap.put(vmInstallType, vmList);
			}
			vmList.add(vm);
			File installLocation = vm.getInstallLocation();
			if (installLocation == null || vmInstallType.validateInstallLocation(installLocation).getSeverity() == IStatus.ERROR) {
				fInvalidVMList.add(vm);
			}
			fVMList.add(vm);
		}
	}

	/**
	 * Add all VM's in the specified list to the VM definitions managed by this container.
	 * <p>
	 * If distinguishing valid from invalid VMs is important, the specified VMs must
	 * have already had their install locations set.  An invalid VM is one whose install
	 * location doesn't exist.
	 * </p>
	 *
	 * @param vmList a list of VMs to be added to this container
	 */
	public void addVMList(List<IVMInstall> vmList) {
		Iterator<IVMInstall> iterator = vmList.iterator();
		while (iterator.hasNext()) {
			addVM(iterator.next());
		}
	}

	/**
	 * Return a mapping of VM install types to lists of VMs.  The keys of this map are instances of
	 * <code>IVMInstallType</code>.  The values are instances of <code>java.util.List</code>
	 * which contain instances of <code>IVMInstall</code>.
	 *
	 * @return Map the mapping of VM install types to lists of VMs
	 */
	public Map<IVMInstallType, List<IVMInstall>> getVMTypeToVMMap() {
		return fVMTypeToVMMap;
	}

	/**
	 * Return a list of all VMs in this container, including any invalid VMs.  An invalid
	 * VM 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 VMs managed by this container
	 */
	public List<IVMInstall> getVMList() {
		return fVMList;
	}

	/**
	 * Return a list of all valid VMs in this container.  A valid VM is one whose install
	 * location exists on the file system.  The order of the list is not specified.
	 *
	 * @return List
	 */
	public List<IVMInstall> getValidVMList() {
		List<IVMInstall> vms = getVMList();
		List<IVMInstall> resultList = new ArrayList<>(vms.size());
		resultList.addAll(vms);
		resultList.removeAll(fInvalidVMList);
		return resultList;
	}

	/**
	 * Returns the composite ID for the default VM.  The composite ID consists
	 * of an ID for the VM install type together with an ID for VM.  This is
	 * necessary because VM ids by themselves are not necessarily unique across
	 * VM install types.
	 *
	 * @return String returns the composite ID of the current default VM
	 */
	public String getDefaultVMInstallCompositeID(){
		return fDefaultVMInstallCompositeID;
	}

	/**
	 * Sets the composite ID for the default VM.  The composite ID consists
	 * of an ID for the VM install type together with an ID for VM.  This is
	 * necessary because VM ids by themselves are not necessarily unique across
	 * VM install types.
	 *
	 * @param id identifies the new default VM using a composite ID
	 */
	public void setDefaultVMInstallCompositeID(String id){
		fDefaultVMInstallCompositeID = id;
	}

	/**
	 * Return the default VM's connector type ID.
	 *
	 * @return String the current value of the default VM's connector type ID
	 */
	public String getDefaultVMInstallConnectorTypeID() {
		return fDefaultVMInstallConnectorTypeID;
	}

	/**
	 * Set the default VM's connector type ID.
	 *
	 * @param id the new value of the default VM's connector type ID
	 */
	public void  setDefaultVMInstallConnectorTypeID(String id){
		fDefaultVMInstallConnectorTypeID = id;
	}

	/**
	 * Return the VM 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 CoreException if serialization of the XML document failed
	 */
	public String getAsXML() throws CoreException {

		// Create the Document and the top-level node
		Document doc = DebugPlugin.newDocument();
		Element config = doc.createElement("vmSettings");    //$NON-NLS-1$
		doc.appendChild(config);

		// Set the defaultVM attribute on the top-level node
		if (getDefaultVMInstallCompositeID() != null) {
			config.setAttribute("defaultVM", getDefaultVMInstallCompositeID()); //$NON-NLS-1$
		}

		// Set the defaultVMConnector attribute on the top-level node
		if (getDefaultVMInstallConnectorTypeID() != null) {
			config.setAttribute("defaultVMConnector", getDefaultVMInstallConnectorTypeID()); //$NON-NLS-1$
		}

		// Create a node for each install type represented in this container
		Set<IVMInstallType> vmInstallTypeSet = getVMTypeToVMMap().keySet();
		Iterator<IVMInstallType> keyIterator = vmInstallTypeSet.iterator();
		while (keyIterator.hasNext()) {
			IVMInstallType vmInstallType = keyIterator.next();
			Element vmTypeElement = vmTypeAsElement(doc, vmInstallType);
			config.appendChild(vmTypeElement);
		}

		// Serialize the Document and return the resulting String
		return DebugPlugin.serializeDocument(doc);
	}

	/**
	 * Create and return a node for the specified VM install type in the specified Document.
	 *
	 * @param doc the backing {@link Document}
	 * @param vmType the {@link IVMInstallType} to create an {@link Element} for
	 * @return the new {@link Element}
	 */
	private Element vmTypeAsElement(Document doc, IVMInstallType vmType) {

		// Create a node for the VM type and set its 'id' attribute
		Element element= doc.createElement("vmType");   //$NON-NLS-1$
		element.setAttribute("id", vmType.getId());     //$NON-NLS-1$

		// For each VM of the specified type, create a subordinate node for it
		List<IVMInstall> vmList = getVMTypeToVMMap().get(vmType);
		Iterator<IVMInstall> vmIterator = vmList.iterator();
		while (vmIterator.hasNext()) {
			IVMInstall vm = vmIterator.next();
			Element vmElement = vmAsElement(doc, vm);
			element.appendChild(vmElement);
		}

		return element;
	}

	/**
	 * Create and return a node for the specified VM in the specified Document.
	 *
	 * @param doc the backing {@link Document}
	 * @param vm the {@link IVMInstall} to create an {@link Element} for
	 * @return the new {@link Element} representing the given {@link IVMInstall}
	 */
	private Element vmAsElement(Document doc, IVMInstall vm) {

		// Create the node for the VM and set its 'id' & 'name' attributes
		Element element= doc.createElement("vm");        //$NON-NLS-1$
		element.setAttribute("id", vm.getId());	         //$NON-NLS-1$
		element.setAttribute("name", vm.getName());      //$NON-NLS-1$

		// Determine and set the 'path' attribute for the VM
		String installPath= "";                          //$NON-NLS-1$
		File installLocation= vm.getInstallLocation();
		if (installLocation != null) {
			installPath= installLocation.getAbsolutePath();
		}
		element.setAttribute("path", installPath);       //$NON-NLS-1$

		// If the 'libraryLocations' attribute is specified, create a node for it
		LibraryLocation[] libraryLocations= vm.getLibraryLocations();
		if (libraryLocations != null) {
			Element libLocationElement = libraryLocationsAsElement(doc, libraryLocations);
			element.appendChild(libLocationElement);
		}

		// Java doc location
		URL url = vm.getJavadocLocation();
		if (url != null) {
			element.setAttribute("javadocURL", url.toExternalForm()); //$NON-NLS-1$
		}

		if (vm instanceof IVMInstall2) {
			String vmArgs = ((IVMInstall2)vm).getVMArgs();
			if (vmArgs != null && vmArgs.length() > 0) {
				element.setAttribute("vmargs", vmArgs); //$NON-NLS-1$
			}
		} else {
			String[] vmArgs = vm.getVMArguments();
			if (vmArgs != null && vmArgs.length > 0) {
				StringBuffer buffer = new StringBuffer();
				for (int i = 0; i < vmArgs.length; i++) {
					buffer.append(vmArgs[i] + " "); //$NON-NLS-1$
				}
				element.setAttribute("vmargs", buffer.toString()); //$NON-NLS-1$
			}
		}

		// VM attributes
		if (vm instanceof AbstractVMInstall) {
			Map<String, String> attributes = ((AbstractVMInstall)vm).getAttributes();
			if (!attributes.isEmpty()) {
				Element attrElement = doc.createElement("attributeMap"); //$NON-NLS-1$
				Iterator<Entry<String, String>> iterator = attributes.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, String> entry = iterator.next();
					Element entryElement = doc.createElement("entry"); //$NON-NLS-1$
					entryElement.setAttribute("key", entry.getKey()); //$NON-NLS-1$
					entryElement.setAttribute("value", entry.getValue()); //$NON-NLS-1$
					attrElement.appendChild(entryElement);
				}
				element.appendChild(attrElement);
			}
		}

		return element;
	}

	/**
	 * Create and return a 'libraryLocations' node.  This node owns subordinate nodes that
	 * list individual library locations.
	 *
	 * @param doc the backing {@link Document}
	 * @param locations the array of {@link LibraryLocation}s to create an {@link Element} for
	 * @return the new {@link Element} for the given {@link LibraryLocation}s
	 */
	private static Element libraryLocationsAsElement(Document doc, LibraryLocation[] locations) {
		Element root = doc.createElement("libraryLocations");       //$NON-NLS-1$
		for (int i = 0; i < locations.length; i++) {
			Element element = doc.createElement("libraryLocation");  //$NON-NLS-1$
			element.setAttribute("jreJar", locations[i].getSystemLibraryPath().toString()); //$NON-NLS-1$
			element.setAttribute("jreSrc", locations[i].getSystemLibrarySourcePath().toString()); //$NON-NLS-1$
			IPath annotationsPath = locations[i].getExternalAnnotationsPath();
			if (null != annotationsPath && !annotationsPath.isEmpty()) {
				element.setAttribute("jreExternalAnns", annotationsPath.toString()); //$NON-NLS-1$
			}

			IPath packageRootPath = locations[i].getPackageRootPath();
            if (packageRootPath != null) {
                element.setAttribute("pkgRoot", packageRootPath.toString()); //$NON-NLS-1$
            }

			URL javadocURL= locations[i].getJavadocLocation();
			if (javadocURL != null) {
				element.setAttribute("jreJavadoc", javadocURL.toExternalForm()); //$NON-NLS-1$
			}
			URL indexURL = locations[i].getIndexLocation();
			if(indexURL != null) {
				element.setAttribute("jreIndex", indexURL.toExternalForm()); //$NON-NLS-1$
			}
			root.appendChild(element);
		}
		return root;
	}

	public static VMDefinitionsContainer parseXMLIntoContainer(InputStream inputStream) throws IOException {
		VMDefinitionsContainer container = new VMDefinitionsContainer();
		parseXMLIntoContainer(inputStream, container);
		return container;
	}

	/**
	 * Parse the VM definitions contained in the specified InputStream into the
	 * specified container.
	 * <p>
	 * The VMs in the returned container are instances of <code>VMStandin</code>.
	 * </p>
	 * <p>
	 * This method has no side-effects.  That is, no notifications are sent for VM 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 semantically 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 VMs and a default VM
	 * @param container the container to add the VM definitions to
	 * @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 'vmSettings'</li>
	 * </ul>
	 * @since 3.2
	 */
	public static void parseXMLIntoContainer(InputStream inputStream, VMDefinitionsContainer container) throws IOException {


		// Do the parsing and obtain the top-level node
		Element config= null;
		// Wrapper the stream for efficient parsing
		try (InputStream stream = new BufferedInputStream(inputStream)) {
			DocumentBuilder parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
			parser.setErrorHandler(new DefaultHandler());
			config = parser.parse(new InputSource(stream)).getDocumentElement();
		} catch (SAXException e) {
			throw new IOException(LaunchingMessages.JavaRuntime_badFormat);
		} catch (ParserConfigurationException e) {
			throw new IOException(LaunchingMessages.JavaRuntime_badFormat);
		}

		// If the top-level node wasn't what we expected, bail out
		if (!config.getNodeName().equalsIgnoreCase("vmSettings")) { //$NON-NLS-1$
			throw new IOException(LaunchingMessages.JavaRuntime_badFormat);
		}

		// Populate the default VM-related fields
		container.setDefaultVMInstallCompositeID(config.getAttribute("defaultVM")); //$NON-NLS-1$
		container.setDefaultVMInstallConnectorTypeID(config.getAttribute("defaultVMConnector")); //$NON-NLS-1$

		// Traverse the parsed structure and populate the VMType to VM 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 vmTypeElement = (Element) node;
				if (vmTypeElement.getNodeName().equalsIgnoreCase("vmType")) { //$NON-NLS-1$
					populateVMTypes(vmTypeElement, container);
				}
			}
		}
	}

	/**
	 * For the specified VM type node, parse all subordinate VM definitions and add them
	 * to the specified container.
	 *
	 * @param vmTypeElement the {@link Element} to populate the {@link VMDefinitionsContainer} from
	 * @param container the {@link VMDefinitionsContainer} to populate from the {@link Element}
	 */
	private static void populateVMTypes(Element vmTypeElement, VMDefinitionsContainer container) {
		// Retrieve the 'id' attribute and the corresponding VM type object
		String id = vmTypeElement.getAttribute("id");         //$NON-NLS-1$
		IVMInstallType vmType= JavaRuntime.getVMInstallType(id);
		if (vmType != null) {
			// For each VM child node, populate the container with a subordinate node
			NodeList vmNodeList = vmTypeElement.getElementsByTagName("vm"); //$NON-NLS-1$
			for (int i = 0; i < vmNodeList.getLength(); ++i) {
				populateVMForType(vmType, (Element) vmNodeList.item(i), container);
			}
		} else {
			// status information for removed VMs (missing VM type)
			NodeList vmNodeList = vmTypeElement.getElementsByTagName("vm"); //$NON-NLS-1$
			for (int i = 0; i < vmNodeList.getLength(); ++i) {
				Element vmElement = (Element) vmNodeList.item(i);
				String installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
				String name = vmElement.getAttribute("name"); //$NON-NLS-1$
				IStatus status = null;
				if (name != null) {
					status = new Status(IStatus.INFO, LaunchingPlugin.ID_PLUGIN,
							NLS.bind(LaunchingMessages.VMDefinitionsContainer_0, new String[]{name}));
				} else if (installPath != null) {
					status = new Status(IStatus.INFO, LaunchingPlugin.ID_PLUGIN,
							NLS.bind(LaunchingMessages.VMDefinitionsContainer_0, new String[]{installPath}));
				} else {
					status = new Status(IStatus.INFO, LaunchingPlugin.ID_PLUGIN,
							NLS.bind(LaunchingMessages.VMDefinitionsContainer_2, new String[]{id}));
				}
				container.addStatus(status);
			}
		}
	}

	/**
	 * Parse the specified VM node, create a VMStandin for it, and add this to the
	 * specified container.
	 *
	 * @param vmType VM type
	 * @param vmElement XML element
	 * @param container container to add VM to
	 */
	private static void populateVMForType(IVMInstallType vmType, Element vmElement, VMDefinitionsContainer container) {
		String id= vmElement.getAttribute("id"); //$NON-NLS-1$
		if (id != null) {

			// Retrieve the 'path' attribute.  If none, skip this node.
			String installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
			String name = vmElement.getAttribute("name"); //$NON-NLS-1$
			if (name == null) {
				if (installPath == null) {
					container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
							NLS.bind(LaunchingMessages.VMDefinitionsContainer_3, new String[]{vmType.getName()})));
					return;
				}
				container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN, NLS.bind(LaunchingMessages.VMDefinitionsContainer_4, new String[]{installPath})));
				return;
			}
			if (installPath == null) {
				container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
						NLS.bind(LaunchingMessages.VMDefinitionsContainer_5, new String[]{name})));
				return;
			}

			// Create a VMStandin for the node and set its 'name' & 'installLocation' attributes
			VMStandin vmStandin = new VMStandin(vmType, id);
			vmStandin.setName(name);
			File installLocation= new File(installPath);
			vmStandin.setInstallLocation(installLocation);
			String install = installLocation.getAbsolutePath();
			//only consider a VM changed it is a standard VM
			boolean changed = StandardVMType.ID_STANDARD_VM_TYPE.equals(vmType.getId()) &&
										LaunchingPlugin.timeStampChanged(install);
			container.addVM(vmStandin);

			// Look for subordinate nodes.  These may be 'libraryLocation',
			// 'libraryLocations' or 'versionInfo'.
			if(!changed) {
				NodeList list = vmElement.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("libraryLocation")) { //$NON-NLS-1$
							LibraryLocation loc = getLibraryLocation(subElement);
						vmStandin.setLibraryLocations(new LibraryLocation[]{loc});
						} else if (subElementName.equals("libraryLocations")) { //$NON-NLS-1$
							setLibraryLocations(vmStandin, subElement);
						} else if (subElementName.equals("attributeMap")) { //$NON-NLS-1$
							NodeList entries = subElement.getElementsByTagName("entry"); //$NON-NLS-1$
							for (int j = 0; j < entries.getLength(); j++) {
								Node entryNode = entries.item(j);
								if (entryNode instanceof Element) {
									Element entryElement = (Element) entryNode;
									String key = entryElement.getAttribute("key"); //$NON-NLS-1$
									String value = entryElement.getAttribute("value"); //$NON-NLS-1$
									if (key != null && value != null) {
										vmStandin.setAttribute(key, value);
									}
								}
							}
						}
					}

					// javadoc URL
					String externalForm = vmElement.getAttribute("javadocURL"); //$NON-NLS-1$
					if (externalForm != null && externalForm.length() > 0) {
						try {
							vmStandin.setJavadocLocation(new URL(externalForm));
						} catch (MalformedURLException e) {
							container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
									NLS.bind(LaunchingMessages.VMDefinitionsContainer_6, new String[]{name}), e));
						}
					}
				}
			}
			// VM Arguments
			String vmArgs = vmElement.getAttribute("vmargs"); //$NON-NLS-1$
			if (vmArgs != null && vmArgs.length() >0) {
				vmStandin.setVMArgs(vmArgs);
			}
		} else {
			String installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
			String name = vmElement.getAttribute("name"); //$NON-NLS-1$
			if (name != null) {
				container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
						NLS.bind(LaunchingMessages.VMDefinitionsContainer_7, new String[]{name})));
			} else if (installPath != null) {
				container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
						NLS.bind(LaunchingMessages.VMDefinitionsContainer_7, new String[]{installPath})));
			} else {
				container.addStatus(new Status(IStatus.ERROR, LaunchingPlugin.ID_PLUGIN,
					NLS.bind(LaunchingMessages.VMDefinitionsContainer_9, new String[]{vmType.getName()})));
			}
		}
	}

	/**
	 * Create & return a LibraryLocation object populated from the attribute values
	 * in the specified node.
	 *
	 * @param libLocationElement the {@link Element} to parse the {@link LibraryLocation} from
	 * @return the new {@link LibraryLocation} or <code>null</code> if the {@link Element} was malformed
	 */
	private static LibraryLocation getLibraryLocation(Element libLocationElement) {
		String jreJar= libLocationElement.getAttribute("jreJar"); //$NON-NLS-1$
		String jreSrc= libLocationElement.getAttribute("jreSrc"); //$NON-NLS-1$
		String pkgRoot= libLocationElement.getAttribute("pkgRoot"); //$NON-NLS-1$
		String jreJavadoc= libLocationElement.getAttribute("jreJavadoc"); //$NON-NLS-1$
		String jreIndex= libLocationElement.getAttribute("jreIndex"); //$NON-NLS-1$
		String externalAnns = libLocationElement.getAttribute("jreExternalAnns"); //$NON-NLS-1$
		// javadoc URL
		URL javadocURL= null;
		if (jreJavadoc.length() == 0) {
			jreJavadoc= null;
		} else {
			try {
				javadocURL= new URL(jreJavadoc);
			} catch (MalformedURLException e) {
				LaunchingPlugin.log("Library location javadoc element is specified incorrectly.");  //$NON-NLS-1$
			}
		}
		// index URL
		URL indexURL= null;
		if (jreIndex.length() == 0) {
			jreIndex= null;
		} else {
			try {
				indexURL= new URL(jreIndex);
			} catch (MalformedURLException e) {
				LaunchingPlugin.log("Library location jre index element is specified incorrectly.");  //$NON-NLS-1$
			}
		}
		if (jreJar != null && jreSrc != null && pkgRoot != null) {
			return new LibraryLocation(new Path(jreJar), new Path(jreSrc), new Path(pkgRoot), javadocURL, indexURL
					, externalAnns == null ? null : new Path(externalAnns));
		}
		LaunchingPlugin.log("Library location element is specified incorrectly.");  //$NON-NLS-1$
		return null;
	}

	/**
	 * Set the LibraryLocations on the specified VM, by extracting the subordinate
	 * nodes from the specified 'lirbaryLocations' node.
	 *
	 * @param vm the {@link IVMInstall} to populate from the given {@link Element}
	 * @param libLocationsElement the {@link Element} to populate the {@link IVMInstall} with
	 */
	private static void setLibraryLocations(IVMInstall vm, 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("libraryLocation")) { //$NON-NLS-1$
					locations.add(getLibraryLocation(libraryLocationElement));
				}
			}
		}
		vm.setLibraryLocations(locations.toArray(new LibraryLocation[locations.size()]));
	}

	/**
	 * Removes the VM from this container.
	 *
	 * @param vm VM install
	 */
	public void removeVM(IVMInstall vm) {
		fVMList.remove(vm);
		fInvalidVMList.remove(vm);
		List<IVMInstall> list = fVMTypeToVMMap.get(vm.getVMInstallType());
		if (list != null) {
			list.remove(vm);
		}
	}

	private void addStatus(IStatus status) {
		if (fStatus == null) {
			fStatus = new MultiStatus(LaunchingPlugin.ID_PLUGIN, 0, LaunchingMessages.VMDefinitionsContainer_10, null);
		}
		fStatus.add(status);
	}

	/**
	 * Returns status from parsing VM installs or <code>null</code> if none.
	 *
	 * @return status or <code>null</code>
	 */
	public IStatus getStatus() {
		return fStatus;
	}
}
