package org.eclipse.jdt.internal.launching.environments;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.launching.LaunchingPlugin;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallChangedListener;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.PropertyChangeEvent;
import org.eclipse.jdt.launching.VMStandin;
import org.eclipse.jdt.launching.environments.CompatibleEnvironment;
import org.eclipse.jdt.launching.environments.IAccessRuleParticipant;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
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.SAXException;
public class EnvironmentsManager implements IExecutionEnvironmentsManager, IVMInstallChangedListener, IPreferenceChangeListener {
private static final String ANALYZER_ELEMENT = "analyzer";
static final String ENVIRONMENT_ELEMENT = "environment";
static final String RULE_PARTICIPANT_ELEMENT = "ruleParticipant";
private static EnvironmentsManager fgManager = null;
private static final String PREF_DEFAULT_ENVIRONMENTS_XML = "org.eclipse.jdt.launching.PREF_DEFAULT_ENVIRONMENTS_XML";
private TreeSet<IExecutionEnvironment> fEnvironments = null;
private Set<AccessRuleParticipant> fRuleParticipants = null;
private Map<String, IExecutionEnvironment> fEnvironmentsMap = null;
private Map<String, Analyzer> fAnalyzers = null;
private boolean fIsUpdatingDefaults = false;
private boolean fInitializedCompatibilities = false;
private static final String VM_ID = "vmId";
private static final String ENVIRONMENT_ID = "environmentId";
private static final String DEFAULT_ENVIRONMENT = "defaultEnvironment";
private static final String DEFAULT_ENVIRONMENTS = "defaultEnvironments";
public static EnvironmentsManager getDefault() {
if (fgManager == null) {
fgManager = new EnvironmentsManager();
}
return fgManager;
}
private EnvironmentsManager() {
JavaRuntime.addVMInstallChangedListener(this);
InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).addPreferenceChangeListener(this);
}
@Override
public synchronized IExecutionEnvironment[] getExecutionEnvironments() {
initializeExtensions();
return fEnvironments.toArray(new IExecutionEnvironment[fEnvironments.size()]);
}
public synchronized IAccessRuleParticipant[] getAccessRuleParticipants() {
initializeExtensions();
return fRuleParticipants.toArray(new IAccessRuleParticipant[fRuleParticipants.size()]);
}
@Override
public synchronized IExecutionEnvironment getEnvironment(String id) {
initializeExtensions();
return fEnvironmentsMap.get(id);
}
public synchronized Analyzer[] getAnalyzers() {
initializeExtensions();
Collection<Analyzer> collection = fAnalyzers.values();
return collection.toArray(new Analyzer[collection.size()]);
}
private String getExecutionEnvironmentCompliance(IExecutionEnvironment executionEnvironment) {
String desc = executionEnvironment.getId();
if (desc.indexOf(JavaCore.VERSION_13) != -1) {
return JavaCore.VERSION_13;
} else if (desc.indexOf(JavaCore.VERSION_12) != -1) {
return JavaCore.VERSION_12;
} else if (desc.indexOf(JavaCore.VERSION_11) != -1) {
return JavaCore.VERSION_11;
} else if (desc.indexOf(JavaCore.VERSION_10) != -1) {
return JavaCore.VERSION_10;
} else if (desc.indexOf(JavaCore.VERSION_9) != -1) {
return JavaCore.VERSION_9;
} else if (desc.indexOf(JavaCore.VERSION_1_8) != -1) {
return JavaCore.VERSION_1_8;
} else if (desc.indexOf(JavaCore.VERSION_1_7) != -1) {
return JavaCore.VERSION_1_7;
} else if (desc.indexOf(JavaCore.VERSION_1_6) != -1) {
return JavaCore.VERSION_1_6;
} else if (desc.indexOf(JavaCore.VERSION_1_5) != -1) {
return JavaCore.VERSION_1_5;
} else if (desc.indexOf(JavaCore.VERSION_1_4) != -1) {
return JavaCore.VERSION_1_4;
} else if (desc.indexOf(JavaCore.VERSION_1_3) != -1) {
return JavaCore.VERSION_1_3;
} else if (desc.indexOf(JavaCore.VERSION_1_2) != -1) {
return JavaCore.VERSION_1_2;
} else if (desc.indexOf(JavaCore.VERSION_1_1) != -1) {
return JavaCore.VERSION_1_1;
} else if (desc.indexOf("1.0") != -1) {
return "1.0";
}
return JavaCore.VERSION_1_3;
}
private synchronized void initializeExtensions() {
if (fEnvironments == null) {
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, JavaRuntime.EXTENSION_POINT_EXECUTION_ENVIRONMENTS);
IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
fEnvironments = new TreeSet<>(new Comparator<IExecutionEnvironment>() {
@Override
public int compare(IExecutionEnvironment o1, IExecutionEnvironment o2) {
String compliance1 = getExecutionEnvironmentCompliance(o1);
String compliance2 = getExecutionEnvironmentCompliance(o2);
int result = JavaCore.compareJavaVersions(compliance1, compliance2);
if (result == 0) {
return o1.getId().compareTo(o2.getId());
}
return result;
}
});
fRuleParticipants = new LinkedHashSet<>();
fEnvironmentsMap = new HashMap<>(configs.length);
fAnalyzers = new HashMap<>(configs.length);
for (int i = 0; i < configs.length; i++) {
IConfigurationElement element = configs[i];
String name = element.getName();
if (name.equals(ENVIRONMENT_ELEMENT)) {
String id = element.getAttribute("id");
if (id == null) {
LaunchingPlugin.log(NLS.bind("Execution environment must specify \"id\" attribute. Contributed by {0}.", new String[]{element.getContributor().getName()}));
} else {
IExecutionEnvironment env = new ExecutionEnvironment(element);
fEnvironments.add(env);
fEnvironmentsMap.put(id, env);
}
} else if (name.equals(ANALYZER_ELEMENT)) {
String id = element.getAttribute("id");
if (id == null) {
LaunchingPlugin.log(NLS.bind("Execution environment analyzer must specify \"id\" attribute. Contributed by {0}", new String[]{element.getContributor().getName()}));
} else {
fAnalyzers.put(id, new Analyzer(element));
}
} else if (name.equals(RULE_PARTICIPANT_ELEMENT)) {
String id = element.getAttribute("id");
if (id == null) {
LaunchingPlugin.log(NLS.bind("Execution environment rule participant must specify \"id\" attribute. Contributed by {0}", new String[]{element.getContributor().getName()}));
} else {
fRuleParticipants.add(new AccessRuleParticipant(element));
}
}
}
}
}
void initializeCompatibilities() {
IVMInstallType[] installTypes = JavaRuntime.getVMInstallTypes();
synchronized (this) {
if (!fInitializedCompatibilities) {
fInitializedCompatibilities = true;
for (int i = 0; i < installTypes.length; i++) {
IVMInstallType type = installTypes[i];
IVMInstall[] installs = type.getVMInstalls();
for (int j = 0; j < installs.length; j++) {
IVMInstall install = installs[j];
analyze(install, new NullProgressMonitor());
}
}
initializeDefaultVMs();
}
}
}
private synchronized void initializeDefaultVMs() {
String xml = InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).get(PREF_DEFAULT_ENVIRONMENTS_XML, "");
try {
if (xml.length() > 0) {
DocumentBuilder parser = LaunchingPlugin.getParser();
Document document = parser.parse(new ByteArrayInputStream(xml.getBytes()));
Element envs = document.getDocumentElement();
NodeList list = envs.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 element = (Element) node;
if (element.getNodeName().equals(DEFAULT_ENVIRONMENT)) {
String envId = element.getAttribute(ENVIRONMENT_ID);
String vmId = element.getAttribute(VM_ID);
ExecutionEnvironment environment = (ExecutionEnvironment) getEnvironment(envId);
if (environment != null) {
IVMInstall vm = JavaRuntime.getVMFromCompositeId(vmId);
if (vm != null) {
environment.initDefaultVM(vm);
}
}
}
}
}
}
} catch (CoreException e) {
LaunchingPlugin.log(e);
} catch (SAXException e) {
LaunchingPlugin.log(e);
} catch (IOException e) {
LaunchingPlugin.log(e);
}
}
private String getDefatulVMsAsXML() {
int count = 0;
try {
Document doc = DebugPlugin.newDocument();
Element envs = doc.createElement(DEFAULT_ENVIRONMENTS);
doc.appendChild(envs);
IExecutionEnvironment[] environments = getExecutionEnvironments();
for (int i = 0; i < environments.length; i++) {
IExecutionEnvironment env = environments[i];
IVMInstall vm = env.getDefaultVM();
if (vm != null) {
count++;
Element element = doc.createElement(DEFAULT_ENVIRONMENT);
element.setAttribute(ENVIRONMENT_ID, env.getId());
element.setAttribute(VM_ID, JavaRuntime.getCompositeIdFromVM(vm));
envs.appendChild(element);
}
}
if (count > 0) {
return DebugPlugin.serializeDocument(doc);
}
} catch (CoreException e) {
LaunchingPlugin.log(e);
}
return "";
}
private void analyze(IVMInstall vm, IProgressMonitor monitor) {
Analyzer[] analyzers = getAnalyzers();
for (int i = 0; i < analyzers.length; i++) {
Analyzer analyzer = analyzers[i];
try {
CompatibleEnvironment[] environments = analyzer.analyze(vm, monitor);
for (int j = 0; j < environments.length; j++) {
CompatibleEnvironment compatibleEnvironment = environments[j];
ExecutionEnvironment environment = (ExecutionEnvironment) compatibleEnvironment.getCompatibleEnvironment();
environment.add(vm, compatibleEnvironment.isStrictlyCompatbile());
}
} catch (CoreException e) {
LaunchingPlugin.log(e);
}
}
}
@Override
public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) {
}
@Override
public synchronized void vmChanged(PropertyChangeEvent event) {
IVMInstall vm = (IVMInstall) event.getSource();
if (vm instanceof VMStandin) {
return;
}
vmRemoved(vm);
vmAdded(vm);
}
@Override
public synchronized void vmAdded(IVMInstall vm) {
if (vm instanceof VMStandin) {
return;
}
analyze(vm, new NullProgressMonitor());
}
@Override
public synchronized void vmRemoved(IVMInstall vm) {
if (vm instanceof VMStandin) {
return;
}
IExecutionEnvironment[] environments = getExecutionEnvironments();
for (int i = 0; i < environments.length; i++) {
ExecutionEnvironment environment = (ExecutionEnvironment) environments[i];
environment.remove(vm);
}
}
synchronized void updateDefaultVMs() {
try {
fIsUpdatingDefaults = true;
InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).put(PREF_DEFAULT_ENVIRONMENTS_XML, getDefatulVMsAsXML());
} finally {
fIsUpdatingDefaults = false;
}
}
@Override
public void preferenceChange(PreferenceChangeEvent event) {
if (fIsUpdatingDefaults) {
return;
}
if (event.getKey().equals(PREF_DEFAULT_ENVIRONMENTS_XML)) {
initializeDefaultVMs();
}
}
}