blob: f3bc7e92038b6311fea84118fbfeee22c4521fa6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.launching;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver;
import org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver2;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.LibraryLocation;
/**
* Resolves for JRELIB_VARIABLE and JRE_CONTAINER
*/
public class JRERuntimeClasspathEntryResolver implements IRuntimeClasspathEntryResolver2 {
private static IAccessRule[] EMPTY_RULES = new IAccessRule[0];
/**
* @see IRuntimeClasspathEntryResolver#resolveRuntimeClasspathEntry(IRuntimeClasspathEntry, ILaunchConfiguration)
*/
@Override
public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, ILaunchConfiguration configuration) throws CoreException {
IVMInstall jre = null;
if (entry.getType() == IRuntimeClasspathEntry.CONTAINER && entry.getPath().segmentCount() > 1) {
// a specific VM
jre = JREContainerInitializer.resolveVM(entry.getPath());
} else {
// default VM for config
jre = JavaRuntime.computeVMInstall(configuration);
}
if (jre == null) {
// cannot resolve JRE
return new IRuntimeClasspathEntry[0];
}
return resolveLibraryLocations(jre, entry.getClasspathProperty());
}
/**
* @see IRuntimeClasspathEntryResolver#resolveRuntimeClasspathEntry(IRuntimeClasspathEntry, IJavaProject)
*/
@Override
public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
IVMInstall jre = null;
if (entry.getType() == IRuntimeClasspathEntry.CONTAINER && entry.getPath().segmentCount() > 1) {
// a specific VM
jre = JREContainerInitializer.resolveVM(entry.getPath());
} else {
// default VM for project
jre = JavaRuntime.getVMInstall(project);
}
if (jre == null) {
// cannot resolve JRE
return new IRuntimeClasspathEntry[0];
}
return resolveLibraryLocations(jre, entry.getClasspathProperty());
}
/**
* Resolves library locations for the given VM install
* @param vm the VM
* @param kind the entry kind
* @return the array of {@link IRuntimeClasspathEntry}s
*/
protected IRuntimeClasspathEntry[] resolveLibraryLocations(IVMInstall vm, int kind) {
LibraryLocation[] libs = vm.getLibraryLocations();
LibraryLocation[] defaultLibs = vm.getVMInstallType().getDefaultLibraryLocations(vm.getInstallLocation());
boolean overrideJavadoc = false;
if (libs == null) {
// default system libraries
libs = defaultLibs;
overrideJavadoc = true;
} else if (!isSameArchives(libs, defaultLibs)) {
// determine if bootpath should be explicit
kind = IRuntimeClasspathEntry.BOOTSTRAP_CLASSES;
}
if (kind == IRuntimeClasspathEntry.BOOTSTRAP_CLASSES) {
File vmInstallLocation= vm.getInstallLocation();
if (vmInstallLocation != null) {
LibraryInfo libraryInfo= LaunchingPlugin.getLibraryInfo(vmInstallLocation.getAbsolutePath());
if (libraryInfo != null) {
// only return endorsed and bootstrap classpath entries if we have the info
// libraries in the 'ext' directories are not loaded by the boot class loader
String[] extensionDirsArray = libraryInfo.getExtensionDirs();
Set<String> extensionDirsSet = new HashSet<>();
for (int i = 0; i < extensionDirsArray.length; i++) {
extensionDirsSet.add(extensionDirsArray[i]);
}
List<IRuntimeClasspathEntry> resolvedEntries = new ArrayList<>(libs.length);
for (int i = 0; i < libs.length; i++) {
LibraryLocation location = libs[i];
IPath libraryPath = location.getSystemLibraryPath();
String dir = libraryPath.toFile().getParent();
// exclude extension directory entries
if (!extensionDirsSet.contains(dir)) {
resolvedEntries.add(resolveLibraryLocation(vm, location, kind, overrideJavadoc));
}
}
return resolvedEntries.toArray(new IRuntimeClasspathEntry[resolvedEntries.size()]);
}
}
}
List<IRuntimeClasspathEntry> resolvedEntries = new ArrayList<>(libs.length);
for (int i = 0; i < libs.length; i++) {
IPath systemLibraryPath = libs[i].getSystemLibraryPath();
if (systemLibraryPath.toFile().exists()) {
resolvedEntries.add(resolveLibraryLocation(vm, libs[i], kind, overrideJavadoc));
}
}
return resolvedEntries.toArray(new IRuntimeClasspathEntry[resolvedEntries.size()]);
}
/**
* Return whether the given list of libraries refer to the same archives in the same
* order. Only considers the binary archive (not source or javadoc locations).
*
* @param libs the locations
* @param defaultLibs the default locations
* @return whether the given list of libraries refer to the same archives in the same
* order
*/
public static boolean isSameArchives(LibraryLocation[] libs, LibraryLocation[] defaultLibs) {
if (libs.length != defaultLibs.length) {
return false;
}
IPath dpath = null, lpath = null;
for (int i = 0; i < defaultLibs.length; i++) {
dpath = defaultLibs[i].getSystemLibraryPath();
lpath = libs[i].getSystemLibraryPath();
if(Platform.getOS().equals(Platform.OS_WIN32)) {
//the .equals method of IPath ignores trailing separators so we must as well
if (!dpath.removeTrailingSeparator().toOSString().equalsIgnoreCase(lpath.removeTrailingSeparator().toOSString())) {
return false;
}
} else if (!dpath.equals(lpath)) {
return false;
}
}
return true;
}
/**
* @see IRuntimeClasspathEntryResolver#resolveVMInstall(IClasspathEntry)
*/
@Override
public IVMInstall resolveVMInstall(IClasspathEntry entry) {
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_VARIABLE:
if (entry.getPath().segment(0).equals(JavaRuntime.JRELIB_VARIABLE)) {
return JavaRuntime.getDefaultVMInstall();
}
break;
case IClasspathEntry.CPE_CONTAINER:
if (entry.getPath().segment(0).equals(JavaRuntime.JRE_CONTAINER)) {
return JREContainerInitializer.resolveVM(entry.getPath());
}
break;
default:
break;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver2#isVMInstallReference(org.eclipse.jdt.core.IClasspathEntry)
*/
@Override
public boolean isVMInstallReference(IClasspathEntry entry) {
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_VARIABLE:
if (entry.getPath().segment(0).equals(JavaRuntime.JRELIB_VARIABLE)) {
return true;
}
break;
case IClasspathEntry.CPE_CONTAINER:
if (entry.getPath().segment(0).equals(JavaRuntime.JRE_CONTAINER)) {
return true;
}
break;
default:
break;
}
return false;
}
/**
* Returns a runtime classpath entry for the given library in the specified VM.
*
* @param vm the VM
* @param location the location
* @param kind the classpath entry kind
* @param overrideJavaDoc if the JavaDoc location should be overridden or not
* @return runtime classpath entry
* @since 3.2
*/
private IRuntimeClasspathEntry resolveLibraryLocation(IVMInstall vm, LibraryLocation location, int kind, boolean overrideJavaDoc) {
IPath libraryPath = location.getSystemLibraryPath();
URL javadocLocation = location.getJavadocLocation();
if (overrideJavaDoc && javadocLocation == null) {
javadocLocation = vm.getJavadocLocation();
}
IClasspathAttribute[] attributes = null;
if (javadocLocation == null) {
attributes = new IClasspathAttribute[0];
} else {
attributes = new IClasspathAttribute[]{JavaCore.newClasspathAttribute(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME, javadocLocation.toExternalForm())};
}
IClasspathEntry cpe = JavaCore.newLibraryEntry(libraryPath, location.getSystemLibraryPath(), location.getPackageRootPath(), EMPTY_RULES, attributes, false);
IRuntimeClasspathEntry resolved = new RuntimeClasspathEntry(cpe);
resolved.setClasspathProperty(kind);
IPath sourcePath = location.getSystemLibrarySourcePath();
if (sourcePath != null && !sourcePath.isEmpty()) {
resolved.setSourceAttachmentPath(sourcePath);
resolved.setSourceAttachmentRootPath(location.getPackageRootPath());
}
return resolved;
}
}