package org.eclipse.jdt.internal.launching;
import java.util.Arrays;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
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.core.JavaModelException;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class RuntimeClasspathEntry implements IRuntimeClasspathEntry {
private int fType = -1;
private int fClasspathProperty = -1;
private IClasspathEntry fClasspathEntry = null;
private IClasspathEntry fResolvedEntry = null;
private IJavaProject fJavaProject = null;
private IPath fInvalidPath;
public RuntimeClasspathEntry(IClasspathEntry entry) {
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_PROJECT:
setType(PROJECT);
break;
case IClasspathEntry.CPE_LIBRARY:
setType(ARCHIVE);
break;
case IClasspathEntry.CPE_VARIABLE:
setType(VARIABLE);
break;
default:
throw new IllegalArgumentException(NLS.bind(LaunchingMessages.RuntimeClasspathEntry_Illegal_classpath_entry__0__1, new String[] {entry.toString()}));
}
setClasspathEntry(entry);
initializeClasspathProperty();
}
public RuntimeClasspathEntry(IClasspathEntry entry, int classpathProperty) {
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_CONTAINER:
setType(CONTAINER);
break;
case IClasspathEntry.CPE_PROJECT:
setType(PROJECT);
break;
case IClasspathEntry.CPE_LIBRARY:
setType(ARCHIVE);
break;
case IClasspathEntry.CPE_VARIABLE:
setType(VARIABLE);
break;
default:
throw new IllegalArgumentException(NLS.bind(LaunchingMessages.RuntimeClasspathEntry_Illegal_classpath_entry__0__1, new String[] {
entry.toString() }));
}
setClasspathEntry(entry);
setClasspathProperty(classpathProperty);
}
public RuntimeClasspathEntry(Element root) throws CoreException {
try {
setType(Integer.parseInt(root.getAttribute("type")));
} catch (NumberFormatException e) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry_type_2, e);
}
try {
setClasspathProperty(Integer.parseInt(root.getAttribute("path")));
} catch (NumberFormatException e) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry_location_3, e);
}
IPath sourcePath = null;
IPath rootPath = null;
String path = root.getAttribute("sourceAttachmentPath");
if (path != null && path.length() > 0) {
sourcePath = new Path(path);
}
path = root.getAttribute("sourceRootPath");
if (path != null && path.length() > 0) {
rootPath = new Path(path);
}
switch (getType()) {
case PROJECT :
String name = root.getAttribute("projectName");
if (isEmpty(name)) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry___missing_project_name_4, null);
} else {
IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
setClasspathEntry(JavaCore.newProjectEntry(proj.getFullPath()));
}
break;
case ARCHIVE :
path = root.getAttribute("externalArchive");
if (isEmpty(path)) {
path = root.getAttribute("internalArchive");
if (isEmpty(path)) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry___missing_archive_path_5, null);
} else {
setClasspathEntry(createLibraryEntry(sourcePath, rootPath, path));
}
} else {
setClasspathEntry(createLibraryEntry(sourcePath, rootPath, path));
}
break;
case VARIABLE :
String var = root.getAttribute("containerPath");
if (isEmpty(var)) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry___missing_variable_name_6, null);
} else {
setClasspathEntry(JavaCore.newVariableEntry(new Path(var), sourcePath, rootPath));
}
break;
case CONTAINER :
var = root.getAttribute("containerPath");
if (isEmpty(var)) {
abort(LaunchingMessages.RuntimeClasspathEntry_Unable_to_recover_runtime_class_path_entry___missing_variable_name_6, null);
} else {
setClasspathEntry(JavaCore.newContainerEntry(new Path(var)));
}
break;
}
String name = root.getAttribute("javaProject");
if (isEmpty(name)) {
fJavaProject = null;
} else {
IProject project2 = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
fJavaProject = JavaCore.create(project2);
}
}
private IClasspathEntry createLibraryEntry(IPath sourcePath, IPath rootPath, String path) {
Path p = new Path(path);
if (!p.isAbsolute())
{
fInvalidPath = p;
return null;
}
return JavaCore.newLibraryEntry(p, sourcePath, rootPath);
}
protected void abort(String message, Throwable e) throws CoreException {
IStatus s = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR, message, e);
throw new CoreException(s);
}
@Override
public int getType() {
return fType;
}
private void setType(int type) {
fType = type;
}
private void setClasspathEntry(IClasspathEntry entry) {
fClasspathEntry = entry;
fResolvedEntry = null;
}
@Override
public IClasspathEntry getClasspathEntry() {
return fClasspathEntry;
}
@Override
public String getMemento() throws CoreException {
Document doc = DebugPlugin.newDocument();
Element node = doc.createElement("runtimeClasspathEntry");
doc.appendChild(node);
node.setAttribute("type", (new Integer(getType())).toString());
node.setAttribute("path", (new Integer(getClasspathProperty())).toString());
switch (getType()) {
case PROJECT :
node.setAttribute("projectName", getPath().lastSegment());
break;
case ARCHIVE :
IResource res = getResource();
if (res == null) {
node.setAttribute("externalArchive", getPath().toString());
} else {
node.setAttribute("internalArchive", res.getFullPath().toString());
}
break;
case VARIABLE :
case CONTAINER :
node.setAttribute("containerPath", getPath().toString());
break;
}
if (getSourceAttachmentPath() != null) {
node.setAttribute("sourceAttachmentPath", getSourceAttachmentPath().toString());
}
if (getSourceAttachmentRootPath() != null) {
node.setAttribute("sourceRootPath", getSourceAttachmentRootPath().toString());
}
if (getExternalAnnotationsPath() != null) {
node.setAttribute("externalAnnotationsPath", getExternalAnnotationsPath().toString());
}
if (getJavaProject() != null) {
node.setAttribute("javaProject", getJavaProject().getElementName());
}
return DebugPlugin.serializeDocument(doc);
}
@Override
public IPath getPath() {
IClasspathEntry entry = getClasspathEntry();
return entry != null ? entry.getPath() : fInvalidPath;
}
@Override
public IResource getResource() {
switch (getType()) {
case CONTAINER:
case VARIABLE:
return null;
default:
return getResource(getPath());
}
}
protected IResource getResource(IPath path) {
if (path != null) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
if (getType() == PROJECT) {
IResource member = root.findMember(path);
if (member != null) {
return member;
}
}
IFile file = root.getFileForLocation(path);
if (file != null) {
return file;
}
if (getType() != ARCHIVE) {
IContainer container = root.getContainerForLocation(path);
if (container != null) {
return container;
}
}
@SuppressWarnings("deprecation")
IFile[] files = root.findFilesForLocation(path);
if (files.length > 0) {
return files[0];
}
if (getType() != ARCHIVE) {
@SuppressWarnings("deprecation")
IContainer[] containers = root.findContainersForLocation(path);
if (containers.length > 0) {
return containers[0];
}
}
return root.findMember(path);
}
return null;
}
@Override
public IPath getSourceAttachmentPath() {
IClasspathEntry entry = getClasspathEntry();
return entry != null ? entry.getSourceAttachmentPath() : null;
}
@Override
public void setSourceAttachmentPath(IPath path) {
if (path != null && path.isEmpty()) {
path = null;
}
updateClasspathEntry(getPath(), path, getSourceAttachmentRootPath(), getExternalAnnotationsPath());
}
@Override
public IPath getExternalAnnotationsPath() {
IClasspathEntry entry = getClasspathEntry();
if (null != entry) {
String s = findClasspathAttribute(entry.getExtraAttributes(), IClasspathAttribute.EXTERNAL_ANNOTATION_PATH);
if (null != s) {
return new Path(s);
}
}
return null;
}
private static String findClasspathAttribute(IClasspathAttribute[] attributes, String name) {
for(int i = attributes.length; --i >= 0;) {
if(name.equals(attributes[i].getName())) {
return attributes[i].getValue();
}
}
return null;
}
@Override
public void setExternalAnnotationsPath(IPath path) {
if (path != null && path.isEmpty()) {
path = null;
}
updateClasspathEntry(getPath(), getSourceAttachmentPath(), getSourceAttachmentRootPath(), path);
}
@Override
public IPath getSourceAttachmentRootPath() {
IClasspathEntry entry = getClasspathEntry();
IPath path = entry != null ? getClasspathEntry().getSourceAttachmentRootPath() : null;
if (path == null && getSourceAttachmentPath() != null) {
return Path.EMPTY;
}
return path;
}
@Override
public void setSourceAttachmentRootPath(IPath path) {
if (path != null && path.isEmpty()) {
path = null;
}
updateClasspathEntry(getPath(), getSourceAttachmentPath(), path, getExternalAnnotationsPath());
}
private void initializeClasspathProperty() {
switch (getType()) {
case VARIABLE:
if (getVariableName().equals(JavaRuntime.JRELIB_VARIABLE)) {
setClasspathProperty(STANDARD_CLASSES);
} else {
setClasspathProperty(USER_CLASSES);
}
break;
case PROJECT:
case ARCHIVE:
setClasspathProperty(USER_CLASSES);
break;
default:
break;
}
}
@Override
public void setClasspathProperty(int location) {
fClasspathProperty = location;
}
@Override
public int getClasspathProperty() {
return fClasspathProperty;
}
@Override
public String getLocation() {
IPath path = null;
switch (getType()) {
case PROJECT :
IJavaProject pro = (IJavaProject) JavaCore.create(getResource());
if (pro != null) {
try {
path = pro.getOutputLocation();
} catch (JavaModelException e) {
LaunchingPlugin.log(e);
}
}
break;
case ARCHIVE :
path = getPath();
break;
case VARIABLE :
IClasspathEntry resolved = getResolvedClasspathEntry();
if (resolved != null) {
path = resolved.getPath();
}
break;
case CONTAINER :
break;
}
return resolveToOSPath(path);
}
protected String resolveToOSPath(IPath path) {
if (path != null) {
IResource res = null;
if (path.getDevice() == null) {
res = getResource(path);
}
if (res == null) {
return path.toOSString();
}
IPath location = res.getLocation();
if (location != null) {
return location.toOSString();
}
}
return null;
}
@Override
public String getVariableName() {
if (getType() == IRuntimeClasspathEntry.VARIABLE || getType() == IRuntimeClasspathEntry.CONTAINER) {
return getPath().segment(0);
}
return null;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof IRuntimeClasspathEntry) {
IRuntimeClasspathEntry r = (IRuntimeClasspathEntry)obj;
if (getType() == r.getType() && getClasspathProperty() == r.getClasspathProperty()) {
if (getType() == IRuntimeClasspathEntry.CONTAINER) {
String id = getPath().segment(0);
ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(id);
IJavaProject javaProject1 = getJavaProject();
IJavaProject javaProject2 = r.getJavaProject();
if (initializer == null || javaProject1 == null || javaProject2 == null) {
return getPath().equals(r.getPath());
}
Object comparisonID1 = initializer.getComparisonID(getPath(), javaProject1);
Object comparisonID2 = initializer.getComparisonID(r.getPath(), javaProject2);
return comparisonID1.equals(comparisonID2);
} else if (getPath() != null && getPath().equals(r.getPath())) {
IPath sa1 = getSourceAttachmentPath();
IPath root1 = getSourceAttachmentRootPath();
IPath sa2 = r.getSourceAttachmentPath();
IPath root2 = r.getSourceAttachmentRootPath();
return equal(sa1, sa2) && equal(root1, root2);
}
}
}
return false;
}
protected boolean equal(Object one, Object two) {
if (one == null) {
return two == null;
}
return one.equals(two);
}
@Override
public int hashCode() {
if (getType() == CONTAINER) {
return getPath().segment(0).hashCode() + getType();
}
return getPath().hashCode() + getType();
}
@Override
public String getSourceAttachmentLocation() {
IPath path = null;
switch (getType()) {
case VARIABLE :
case ARCHIVE :
IClasspathEntry resolved = getResolvedClasspathEntry();
if (resolved != null) {
path = resolved.getSourceAttachmentPath();
}
break;
default :
break;
}
return resolveToOSPath(path);
}
@Override
public String getSourceAttachmentRootLocation() {
IPath path = null;
switch (getType()) {
case VARIABLE :
case ARCHIVE :
IClasspathEntry resolved = getResolvedClasspathEntry();
if (resolved != null) {
path = resolved.getSourceAttachmentRootPath();
}
break;
default :
break;
}
if (path != null) {
return path.toOSString();
}
return null;
}
protected void updateClasspathEntry(IPath path, IPath sourcePath, IPath rootPath, IPath annotationsPath) {
IClasspathEntry entry = null;
IClasspathEntry original = getClasspathEntry();
switch (getType()) {
case ARCHIVE:
IClasspathAttribute[] extraAttributes = original.getExtraAttributes();
if (annotationsPath != null) {
extraAttributes = setClasspathAttribute(extraAttributes, IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, annotationsPath.toPortableString());
}
entry = JavaCore.newLibraryEntry(path, sourcePath, rootPath, original.getAccessRules(), extraAttributes, original.isExported());
break;
case VARIABLE:
entry = JavaCore.newVariableEntry(path, sourcePath, rootPath);
break;
default:
return;
}
setClasspathEntry(entry);
}
private static IClasspathAttribute[] setClasspathAttribute(IClasspathAttribute[] attributes, String name, String value) {
for (int i = attributes.length; --i >= 0;) {
if (name.equals(attributes[i].getName())) {
IClasspathAttribute[] nw = Arrays.copyOf(attributes, attributes.length);
nw[i] = JavaCore.newClasspathAttribute(name, value);
return nw;
}
}
IClasspathAttribute[] nw = Arrays.copyOf(attributes, attributes.length + 1);
nw[attributes.length] = JavaCore.newClasspathAttribute(name, value);
return nw;
}
protected IClasspathEntry getResolvedClasspathEntry() {
if (fResolvedEntry == null) {
fResolvedEntry = JavaCore.getResolvedClasspathEntry(getClasspathEntry());
}
return fResolvedEntry;
}
protected boolean isEmpty(String string) {
return string == null || string.length() == 0;
}
@Override
public String toString() {
if (fClasspathEntry != null) {
return fClasspathEntry.toString();
}
return super.toString();
}
@Override
public IJavaProject getJavaProject() {
return fJavaProject;
}
public void setJavaProject(IJavaProject project) {
fJavaProject = project;
}
@Override
public boolean isAutomodule() {
IClasspathAttribute[] extraAttributes = getClasspathEntry().getExtraAttributes();
for (IClasspathAttribute attribute : extraAttributes) {
if (IClasspathAttribute.MODULE.equals(attribute.getName()) && Boolean.TRUE.toString().equals(attribute.getValue())) {
return true;
}
}
return false;
}
}