package org.eclipse.jdt.internal.launching.environments;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.internal.launching.EEVMInstall;
import org.eclipse.jdt.internal.launching.EEVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.IVMInstall3;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.CompatibleEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentAnalyzerDelegate;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
public class ExecutionEnvironmentAnalyzer implements IExecutionEnvironmentAnalyzerDelegate {
private static final String JavaSE_13 = "JavaSE-13";
private static final String JavaSE_12 = "JavaSE-12";
private static final String JavaSE_11 = "JavaSE-11";
private static final String JavaSE_10_Plus = "JavaSE-10+";
private static final String JavaSE_10 = "JavaSE-10";
static final String JavaSE_9 = "JavaSE-9";
private static final String JavaSE_1_8 = "JavaSE-1.8";
private static final String JavaSE_1_7 = "JavaSE-1.7";
private static final String JavaSE_1_6 = "JavaSE-1.6";
private static final String J2SE_1_5 = "J2SE-1.5";
private static final String J2SE_1_4 = "J2SE-1.4";
private static final String J2SE_1_3 = "J2SE-1.3";
private static final String J2SE_1_2 = "J2SE-1.2";
private static final String JRE_1_1 = "JRE-1.1";
private static final String CDC_FOUNDATION_1_1 = "CDC-1.1/Foundation-1.1";
private static final String CDC_FOUNDATION_1_0 = "CDC-1.0/Foundation-1.0";
private static final String OSGI_MINIMUM_1_0 = "OSGi/Minimum-1.0";
private static final String OSGI_MINIMUM_1_1 = "OSGi/Minimum-1.1";
private static final String OSGI_MINIMUM_1_2 = "OSGi/Minimum-1.2";
private static final String JAVA_SPEC_VERSION = "java.specification.version";
private static final String JAVA_SPEC_NAME = "java.specification.name";
private static final String JAVA_VERSION = "java.version";
private static final String[] VM_PROPERTIES = {JAVA_SPEC_NAME, JAVA_SPEC_VERSION, JAVA_VERSION};
private static final String FOUNDATION = "foundation";
private static final Map<String, String[]> mappings = new HashMap<>();
static {
mappings.put(CDC_FOUNDATION_1_0, new String[] {OSGI_MINIMUM_1_0});
mappings.put(CDC_FOUNDATION_1_1, new String[] {CDC_FOUNDATION_1_0, OSGI_MINIMUM_1_2});
mappings.put(OSGI_MINIMUM_1_1, new String[] {OSGI_MINIMUM_1_0});
mappings.put(OSGI_MINIMUM_1_2, new String[] {OSGI_MINIMUM_1_1});
mappings.put(J2SE_1_2, new String[] {JRE_1_1});
mappings.put(J2SE_1_3, new String[] {J2SE_1_2, CDC_FOUNDATION_1_0, OSGI_MINIMUM_1_0});
mappings.put(J2SE_1_4, new String[] {J2SE_1_3, CDC_FOUNDATION_1_1, OSGI_MINIMUM_1_2});
mappings.put(J2SE_1_5, new String[] {J2SE_1_4});
mappings.put(JavaSE_1_6, new String[] {J2SE_1_5});
mappings.put(JavaSE_1_7, new String[] {JavaSE_1_6});
mappings.put(JavaSE_1_8, new String[] { JavaSE_1_7 });
mappings.put(JavaSE_9, new String[] { JavaSE_1_8 });
mappings.put(JavaSE_10, new String[] { JavaSE_9 });
mappings.put(JavaSE_10_Plus, new String[] { JavaSE_13 });
mappings.put(JavaSE_11, new String[] { JavaSE_10 });
mappings.put(JavaSE_12, new String[] { JavaSE_11 });
mappings.put(JavaSE_13, new String[] { JavaSE_12 });
}
@Override
public CompatibleEnvironment[] analyze(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
ArrayList<CompatibleEnvironment> result = new ArrayList<>();
if (!(vm instanceof IVMInstall2)) {
return new CompatibleEnvironment[0];
}
IVMInstall2 vm2 = (IVMInstall2) vm;
List<String> types = null;
if (EEVMType.ID_EE_VM_TYPE.equals(vm.getVMInstallType().getId())) {
String eeId = ((EEVMInstall)vm).getAttribute(EEVMInstall.ATTR_EXECUTION_ENVIRONMENT_ID);
if (eeId != null) {
types = getTypes(eeId);
}
}
if (types == null) {
String javaVersion = vm2.getJavaVersion();
if (javaVersion == null) {
if ((vm instanceof IVMInstall3) && isFoundation1_0((IVMInstall3) vm)) {
types = getTypes(CDC_FOUNDATION_1_0);
} else if ((vm instanceof IVMInstall3) && isFoundation1_1((IVMInstall3) vm)) {
types = getTypes(CDC_FOUNDATION_1_1);
}
} else {
if (javaVersion.startsWith("13")) {
types = getTypes(JavaSE_13);
} else if (javaVersion.startsWith("12")) {
types = getTypes(JavaSE_12);
} else if (javaVersion.startsWith("11")) {
types = getTypes(JavaSE_11);
} else if (javaVersion.startsWith("10")) {
types = getTypes(JavaSE_10);
} else if (javaVersion.startsWith("9")) {
types = getTypes(JavaSE_9);
} else if (javaVersion.startsWith("1.8")) {
types = getTypes(JavaSE_1_8);
} else if (javaVersion.startsWith("1.7")) {
types = getTypes(JavaSE_1_7);
} else if (javaVersion.startsWith("1.6")) {
types = getTypes(JavaSE_1_6);
} else if (javaVersion.startsWith("1.5")) {
types = getTypes(J2SE_1_5);
} else if (javaVersion.startsWith("1.4")) {
types = getTypes(J2SE_1_4);
} else if (javaVersion.startsWith("1.3")) {
types = getTypes(J2SE_1_3);
} else if (javaVersion.startsWith("1.2")) {
types = getTypes(J2SE_1_2);
} else if (javaVersion.startsWith("1.1")) {
if ((vm instanceof IVMInstall3) && isFoundation1_1((IVMInstall3) vm)) {
types = getTypes(CDC_FOUNDATION_1_1);
} else {
types = getTypes(JRE_1_1);
}
} else if (javaVersion.startsWith("1.0")) {
if ((vm instanceof IVMInstall3) && isFoundation1_0((IVMInstall3) vm)) {
types = getTypes(CDC_FOUNDATION_1_0);
}
} else if (javaVersion.startsWith("1") && javaVersion.length() >= 2 && javaVersion.charAt(1) != '.') {
types = getTypes(JavaSE_10_Plus);
}
}
}
if (types != null) {
for (int i=0; i < types.size(); i++) {
addEnvironment(result, types.get(i), i ==0);
}
}
return result.toArray(new CompatibleEnvironment[result.size()]);
}
private boolean isFoundation(Map<String, String> properties) {
for (int i=0; i < VM_PROPERTIES.length; i++) {
String value = properties.get(VM_PROPERTIES[i]);
if (value == null) {
continue;
}
for (StringTokenizer tokenizer = new StringTokenizer(value); tokenizer.hasMoreTokens(); ) {
if (FOUNDATION.equalsIgnoreCase(tokenizer.nextToken())) {
return true;
}
}
}
return false;
}
private boolean isFoundation1_0(IVMInstall3 vm) throws CoreException {
Map<String, String> map = vm.evaluateSystemProperties(VM_PROPERTIES, null);
return isFoundation(map) ? "1.0".equals(map.get(JAVA_SPEC_VERSION)) : false;
}
private boolean isFoundation1_1(IVMInstall3 vm) throws CoreException {
Map<String, String> map = vm.evaluateSystemProperties(VM_PROPERTIES, null);
return isFoundation(map) ? "1.1".equals(map.get(JAVA_SPEC_VERSION)) : false;
}
private void addEnvironment(ArrayList<CompatibleEnvironment> result, String id, boolean strict) {
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
IExecutionEnvironment env = manager.getEnvironment(id);
if (env != null) {
result.add(new CompatibleEnvironment(env, strict));
}
}
private List<String> getTypes(String type) {
List<String> result = new ArrayList<>();
result.add(type);
String[] values = mappings.get(type);
if (values != null) {
for (int i=0; i<values.length; i++) {
result.addAll(getTypes(values[i]));
}
}
return result;
}
}