package net.sourceforge.pmd.eclipse.runtime.cmd; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; /** * This is a ClassLoader for the Build Path of an IJavaProject. */ public class JavaProjectClassLoader extends URLClassLoader { private static final Logger log = Logger.getLogger(JavaProjectClassLoader.class); private Set<IJavaProject> javaProjects = new HashSet<IJavaProject>(); private IWorkspaceRoot workspaceRoot; public JavaProjectClassLoader(ClassLoader parent, IProject project) { super(new URL[0], parent); try { if (!project.hasNature(JavaCore.NATURE_ID)) { throw new IllegalArgumentException("The project " + project + " is not a java project"); } } catch (CoreException e) { throw new IllegalArgumentException("The project " + project + " is not a java project", e); } workspaceRoot = project.getProject().getWorkspace().getRoot(); IJavaProject javaProject = JavaCore.create(project); addURLs(javaProject, false); // No longer need these things, drop references javaProjects = null; workspaceRoot = null; } private static IProject projectFor(IJavaProject javaProject, IClasspathEntry classpathEntry) { return javaProject.getProject().getWorkspace().getRoot().getProject(classpathEntry.getPath().toString()); } private void addURLs(IJavaProject javaProject, boolean exportsOnly) { if (javaProjects.contains(javaProject)) return; javaProjects.add(javaProject); try { // Add default output location addURL(javaProject.getOutputLocation()); // Add each classpath entry IClasspathEntry[] classpathEntries = javaProject.getResolvedClasspath(true); for (IClasspathEntry classpathEntry : classpathEntries) { if (classpathEntry.isExported() || !exportsOnly) { switch (classpathEntry.getEntryKind()) { // Recurse on projects case IClasspathEntry.CPE_PROJECT: IProject project = projectFor(javaProject, classpathEntry); IJavaProject javaProj = JavaCore.create(project); if (javaProj != null) { addURLs(javaProj, true); } break; // Library case IClasspathEntry.CPE_LIBRARY: addURL(classpathEntry); break; // Only Source entries with custom output location need to be added case IClasspathEntry.CPE_SOURCE: IPath outputLocation = classpathEntry.getOutputLocation(); if (outputLocation != null) { addURL(outputLocation); } break; // Variable and Container entries should not be happening, because we've asked for resolved entries. case IClasspathEntry.CPE_VARIABLE: case IClasspathEntry.CPE_CONTAINER: break; } } } } catch (JavaModelException e) { log.debug("MalformedURLException occurred: " + e.getLocalizedMessage(), e); } } private void addURL(IClasspathEntry classpathEntry) { addURL(classpathEntry.getPath()); } private void addURL(IPath path) { try { if (workspaceRoot.exists(path)) { // path = workspaceRoot.getFileForLocation(path).getFullPath(); //path = workspaceRoot.getFile(path).getFullPath(); path = workspaceRoot.getLocation().append(path); } URL url = path.toFile().getAbsoluteFile().toURI().toURL(); addURL(url); } catch (MalformedURLException e) { log.debug("MalformedURLException occurred: " + e.getLocalizedMessage(), e); } } }