/** * GRANITE DATA SERVICES * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.builder.util; import static org.granite.builder.GraniteBuilder.FLEX_BUILDER_ID; import static org.granite.builder.GraniteBuilder.GRANITE_BUILDER_ID; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; 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.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.granite.builder.GraniteActivator; import org.granite.util.ClassUtil; /** * @author Franck WOLFF */ public class ProjectUtil { public static final Comparator<IPath> IPATH_COMPARATOR = new Comparator<IPath>() { @Override public int compare(IPath path1, IPath path2) { return path1.toString().compareTo(path2.toString()); } }; public static IProject[] getAllProjects(IProject project) { if (project == null) return new IProject[0]; return project.getWorkspace().getRoot().getProjects(); } public static IProject[] getAllOtherGraniteProjects(IProject project) throws CoreException { if (project == null) return new IProject[0]; List<IProject> projects = new ArrayList<IProject>(); for (IProject p : getAllProjects(project)) { if (!p.equals(project) && isGraniteProject(p)) projects.add(p); } return projects.toArray(new IProject[projects.size()]); } public static IProject getProject(IProject project, String name) { if (project == null || name == null) return null; return project.getWorkspace().getRoot().getProject(name); } public static boolean isGraniteProject(IProject project) throws CoreException { if (project != null && project.exists() && project.isOpen()) { for (ICommand command : project.getDescription().getBuildSpec()) { if (GRANITE_BUILDER_ID.equals(command.getBuilderName())) return true; } } return false; } public static boolean isFlexBuilderProject(IProject project) throws CoreException { if (project != null && project.exists() && project.isOpen()) { for (ICommand command : project.getDescription().getBuildSpec()) { if (FLEX_BUILDER_ID.equals(command.getBuilderName())) return true; } } return false; } public static List<IPath> makeRelative(List<IPath> paths) { if (paths == null) return null; return Arrays.asList(makeRelative(paths.toArray(new IPath[paths.size()]))); } public static IPath[] makeRelative(IPath[] paths) { if (paths != null) { for (int i = 0; i < paths.length; i++) paths[i] = paths[i].makeRelative(); } return paths; } public static File getWorkspaceFile(IProject project) { IWorkspace workspace = project.getWorkspace(); return workspace.getRoot().getLocation().toFile().getAbsoluteFile(); } public static URI getWorkspaceURI(IProject project) { return getWorkspaceFile(project).toURI(); } public static File getProjectFile(IProject project) { try { return FileUtil.getLocationFile(project).getAbsoluteFile(); } catch (CoreException e) { throw new RuntimeException("Could not get " + project + " location file", e); } } public static URI getProjectURI(IProject project) { try { return FileUtil.getLocationURI(project); } catch (CoreException e) { throw new RuntimeException("Could not get " + project + " location URI", e); } } public static List<CpEntry> getFullResolvedClasspath(IJavaProject project) throws CoreException { return getFullClasspath(project, project.getResolvedClasspath(true)); } public static List<CpEntry> getFullClasspath(IJavaProject project) throws CoreException { return getFullClasspath(project, project.getRawClasspath()); } public static List<CpEntry> getFullClasspath(IJavaProject project, IClasspathEntry[] classpathEntries) throws CoreException { List<CpEntry> classpath = new ArrayList<CpEntry>(); IWorkspaceRoot workspace = project.getProject().getWorkspace().getRoot(); IPath path = null; try { // Output locations. if (project.getOutputLocation() != null) { path = project.getOutputLocation(); File file = workspace.findMember(path).getLocation().toFile(); classpath.add(new CpEntry(path.makeRelative().toString(), path, file, CpEntry.CpeKind.PROJECT_OUTPUT_DIR)); } for (IClasspathEntry cpe : classpathEntries) { if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE && cpe.getOutputLocation() != null) { path = cpe.getOutputLocation(); File file = workspace.findMember(path).getLocation().toFile(); classpath.add(new CpEntry(path.makeRelative().toString(), path, file, CpEntry.CpeKind.SOURCE_OUTPUT_DIR)); } } // Project jars. for (IClasspathEntry cpe : classpathEntries) { if (cpe.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { path = cpe.getPath(); if (path != null) { IResource member = workspace.findMember(path); String description = path.lastSegment(); if (path.segmentCount() > 1) description += " - " + path.removeLastSegments(1).makeRelative(); if (member != null) classpath.add(new CpEntry(description, path, member.getLocation().toFile(), CpEntry.CpeKind.LIB_JAR)); else classpath.add(new CpEntry(description, path, path.toFile(), CpEntry.CpeKind.LIB_JAR)); } } } // Containers jars/directories. for (IClasspathEntry cpe : classpathEntries) { if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { path = cpe.getPath(); IClasspathContainer container = JavaCore.getClasspathContainer(path, project); String description = container.getDescription(); CpEntry entry = new CpEntry(description, path, (path != null ? path.toFile() : null), CpEntry.CpeKind.CONTAINER_JAR); for (IClasspathEntry ccpe : container.getClasspathEntries()) { path = ccpe.getPath(); String label = path.lastSegment(); if (path.segmentCount() > 1) label += " - " + path.removeLastSegments(1).makeRelative(); File file = path.toFile(); IResource resource = workspace.findMember(path); if (resource != null) file = resource.getLocation().toFile(); entry.getChildren().add(new CpEntry(label, path, file, CpEntry.CpeKind.LIB_JAR)); } classpath.add(entry); } } } catch (Exception e) { String msg = "Problem with classpath location: " + path; throw new CoreException(createErrorStatus(msg, e)); } return classpath; } public static List<IPath> getSourceFolders(IJavaProject project) throws CoreException { List<IPath> paths = new ArrayList<IPath>(); for (IClasspathEntry cpe : project.getRawClasspath()) { if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) paths.add(cpe.getPath()); } return paths; } public static IPath getOutputFolder(IJavaProject project, IClasspathEntry cpe) throws CoreException { if (cpe.getOutputLocation() != null) return cpe.getOutputLocation(); return project.getOutputLocation(); } public static List<IPath> getOutputFolders(IJavaProject project) throws CoreException { List<IPath> paths = new ArrayList<IPath>(); for (IClasspathEntry cpe : project.getRawClasspath()) { if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath output = cpe.getOutputLocation(); if (output != null) paths.add(output); } } IPath output = project.getOutputLocation(); if (output != null) paths.add(output); return paths; } public static IPath getJavaPath(IJavaProject project, IFile classFile, boolean keepInner) throws CoreException { IPath classPath = classFile.getFullPath(); List<IPath> outputFolders = getOutputFolders(project); IPath classOutputFolder = null; for (IPath outputFolder : outputFolders) { if (outputFolder.isPrefixOf(classPath)) { classOutputFolder = outputFolder; break; } } if (classOutputFolder == null) return null; classPath = classPath.removeFirstSegments(classOutputFolder.segmentCount()); String sPath = classPath.toString(); sPath = sPath.substring(0, sPath.length() - classPath.getFileExtension().length() - 1); if (!keepInner) { int iDollar = sPath.indexOf('$'); if (iDollar != -1) sPath = sPath.substring(iDollar); } sPath += ".java"; return new Path(sPath); } public static JavaClassInfo getJavaClassInfo(IJavaProject project, Class<?> clazz) { try { URI clazzUri = ClassUtil.findResource(clazz).toURI(); URI projectUri = getProjectURI(project.getProject()); URI relativeURI = projectUri.relativize(clazzUri); return getJavaClassInfo(project, project.getProject().getFile(relativeURI.toString())); } catch (Exception e) { return null; } } public static JavaClassInfo getJavaClassInfo(IJavaProject project, IFile resource) throws CoreException { // classPath = "<project name>/<output folder>/<package>/<file>.class" IPath classPath = resource.getFullPath().makeRelative(); // Find output folder: "<project name>/<output folder>". IPath outputFolder = null; if (project.getOutputLocation() != null && project.getOutputLocation().isPrefixOf(classPath)) outputFolder = project.getOutputLocation(); else { for (IClasspathEntry cpe : project.getRawClasspath()) { if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath output = cpe.getOutputLocation(); if (output != null && output.isPrefixOf(classPath)) { outputFolder = output; break; } } } } if (outputFolder == null) return null; // Compute class name. IPath relativeClassPath = classPath.removeFirstSegments(outputFolder.segmentCount()); IPath relativeClassName = relativeClassPath.removeFileExtension(); String className = relativeClassName.toPortableString().replace('/', '.'); // Compute java source path: "<package>/<class name>[$<inner class>].java". String javaFullPath = relativeClassName.addFileExtension("java").toPortableString(); String javaFilePath = javaFullPath; int iDollar = javaFilePath.indexOf('$'); if (iDollar != -1) javaFilePath = javaFilePath.substring(0, iDollar) + ".java"; IJavaElement javaElement = project.findElement(new Path(javaFilePath)); if (javaElement == null) return null; IJavaElement sourceFolder = javaElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); if (sourceFolder == null) return null; IPath folderPath = sourceFolder.getPath().makeRelative(); if (folderPath.segmentCount() > 0) folderPath = folderPath.removeFirstSegments(1); // Fix issues with project not in the workspace directory. outputFolder = project.getProject().getWorkspace().getRoot().findMember(outputFolder).getLocation(); return new JavaClassInfo( folderPath.toPortableString(), javaFullPath, className, new File(outputFolder.toPortableString(), relativeClassPath.toPortableString()) ); } public static IStatus createErrorStatus(String message) { return new Status(IStatus.ERROR, GraniteActivator.PLUGIN_ID, message); } public static IStatus createErrorStatus(String message, Throwable t) { return new Status(IStatus.ERROR, GraniteActivator.PLUGIN_ID, IStatus.OK, message, t); } public static class CpEntry { public enum CpeKind { PROJECT_OUTPUT_DIR, SOURCE_OUTPUT_DIR, CONTAINER_JAR, LIB_JAR } private final String description; private final IPath path; private final File file; private final CpeKind kind; private final List<CpEntry> children = new ArrayList<CpEntry>(); public CpEntry(String description, IPath path, File file, CpeKind kind) { this.description = description; this.path = path; this.file = file; this.kind = kind; } public String getDescription() { return description; } public IPath getPath() { return path; } public File getFile() { return file; } public CpeKind getKind() { return kind; } public List<CpEntry> getChildren() { return children; } public boolean exists() { return (file != null && file.exists()); } public URL toURL() throws IOException { if (file == null) return null; return file.getCanonicalFile().toURI().toURL(); } @Override public String toString() { return "[" + kind + "] " + path + " -> " + file; } } }