| /******************************************************************************* |
| * Copyright (c) 2004, 2005 Richard Hoefter and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bug 95298 |
| * IBM Corporation - nlsing and incorporating into Eclipse |
| *******************************************************************************/ |
| |
| package org.eclipse.ant.internal.ui.datatransfer; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| |
| import org.eclipse.ant.internal.ui.AntUIPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jdt.core.IClasspathContainer; |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.launching.IVMInstall; |
| import org.eclipse.jdt.launching.JavaRuntime; |
| |
| /** |
| * Class to store classpath settings of an Eclipse project. |
| * |
| * <p>NOTE: The constructed classpath does not contain items of the subprojects. |
| * Instead create an object of this class for each project returned by |
| * {@link eclipse2ant.util.EclipseUtil#getClasspathProjectsRecursive(IJavaProject)}. |
| */ |
| public class EclipseClasspath |
| { |
| public List srcDirs = new ArrayList(); |
| public List classDirs = new ArrayList(); |
| public List inclusionLists = new ArrayList(); |
| public List exclusionLists = new ArrayList(); |
| |
| public Map class2sourcesMap = new TreeMap(); |
| public Map class2includesMap = new TreeMap(); |
| public Map class2excludesMap = new TreeMap(); |
| |
| public Map variable2valueMap = new TreeMap(); |
| public List rawClassPathEntries = new ArrayList(); |
| public List rawClassPathEntriesAbsolute = new ArrayList(); |
| |
| private IJavaProject project; |
| private String newProjectRoot; |
| private String jreLocation; |
| |
| public EclipseClasspath(IJavaProject project) throws JavaModelException |
| { |
| this(project, null); |
| } |
| |
| /** |
| * @param newProjectRoot replace project root, e.g. with a variable ${project.location} |
| */ |
| public EclipseClasspath(IJavaProject project, String newProjectRoot) throws JavaModelException |
| { |
| this.project = project; |
| jreLocation = getJRELocation(); |
| this.newProjectRoot = newProjectRoot; |
| IClasspathEntry entries[] = project.getRawClasspath(); |
| for (int i = 0; i < entries.length; i++) |
| { |
| handleSources(entries[i]); |
| handleVariables(entries[i]); |
| handleJars(entries[i]); |
| handleUserLibraries(entries[i]); |
| } |
| addClasses(); |
| initClassMaps(); |
| } |
| |
| private String getJRELocation() { |
| try { |
| IVMInstall install= JavaRuntime.getVMInstall(project); |
| if (install != null) { |
| File installLocation= install.getInstallLocation(); |
| if (installLocation != null) { |
| return new Path(installLocation.toString()).toString(); |
| } |
| } |
| } catch (CoreException e) { |
| AntUIPlugin.log(e); |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Get class directories without duplicates. |
| */ |
| public List getClassDirsUnique() |
| { |
| return removeDuplicates(classDirs); |
| } |
| |
| private void handleSources(IClasspathEntry entry) throws JavaModelException |
| { |
| String projectRoot = ExportUtil.getProjectRoot(project); |
| String defaultClassDir = project.getOutputLocation().toString(); |
| if (entry.getContentKind() == IPackageFragmentRoot.K_SOURCE && |
| entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) |
| { |
| // found source path |
| IPath srcDirPath = entry.getPath(); |
| IPath classDirPath = entry.getOutputLocation(); |
| String srcDir = ExportUtil.removeProjectRoot((srcDirPath != null) ? srcDirPath.toString() : projectRoot, project.getProject()); |
| String classDir = ExportUtil.removeProjectRoot((classDirPath != null) ? classDirPath.toString() : defaultClassDir, project.getProject()); |
| srcDirs.add(srcDir); |
| classDirs.add(classDir); |
| IPath[] inclusions = entry.getInclusionPatterns(); |
| List inclusionList = new ArrayList(); |
| for (int j = 0; j < inclusions.length; j++) |
| { |
| if (inclusions[j] != null) |
| { |
| inclusionList.add(ExportUtil.removeProjectRoot(inclusions[j].toString(), project.getProject())); |
| } |
| } |
| inclusionLists.add(inclusionList); |
| IPath[] exclusions = entry.getExclusionPatterns(); |
| List exclusionList = new ArrayList(); |
| for (int j = 0; j < exclusions.length; j++) |
| { |
| if (exclusions[j] != null) |
| { |
| exclusionList.add(ExportUtil.removeProjectRoot(exclusions[j].toString(), project.getProject())); |
| } |
| } |
| exclusionLists.add(exclusionList); |
| } |
| } |
| |
| /** |
| * Convert sources/classes directories and inclusion/exclusion filters to map representation. |
| * As several source directories may compile to same class directory this is a useful conversion |
| * of the result of {@link #handleSources}. |
| */ |
| private void initClassMaps() |
| { |
| for (int i = 0; i < srcDirs.size(); i++) |
| { |
| String srcDir = (String) srcDirs.get(i); |
| String classDir = (String) classDirs.get(i); |
| List includeList = (List) inclusionLists.get(i); |
| List excludeList = (List) exclusionLists.get(i); |
| Set sources = (Set) class2sourcesMap.get(classDir); |
| if (sources == null) |
| { |
| sources = new TreeSet(); |
| } |
| sources.add(srcDir); |
| class2sourcesMap.put(classDir, sources); |
| Set includes = (Set) class2includesMap.get(classDir); |
| if (includes == null) |
| { |
| includes = new TreeSet(); |
| } |
| includes.addAll(includeList); |
| class2includesMap.put(classDir, includes); |
| Set excludes = (Set) class2excludesMap.get(classDir); |
| if (excludes == null) |
| { |
| excludes = new TreeSet(); |
| } |
| excludes.addAll(excludeList); |
| class2excludesMap.put(classDir, excludes); |
| } |
| } |
| |
| private void handleJars(IClasspathEntry entry) |
| { |
| if (entry.getContentKind() == IPackageFragmentRoot.K_BINARY && |
| entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) |
| { |
| String jarFile = entry.getPath().toString(); |
| // ignore JRE libraries |
| if (jarFile.startsWith(jreLocation)) |
| { |
| return; |
| } |
| StringBuffer jarFileBuffer = new StringBuffer(); |
| StringBuffer jarFileAbsoluteBuffer = new StringBuffer(); |
| String jarFileAbsolute = ExportUtil.resolve(entry.getPath()); |
| if (jarFileAbsolute == null) |
| { |
| jarFileAbsolute = jarFile; // jarFile was already absolute |
| if (handleSubProjectClassesDirectory(jarFile, jarFileBuffer, jarFileAbsoluteBuffer)) |
| { |
| jarFile = jarFileBuffer.toString(); |
| jarFileAbsolute = jarFileAbsoluteBuffer.toString(); |
| } |
| } |
| String jarFileOld = jarFile; |
| if (newProjectRoot == null) |
| { |
| jarFile = ExportUtil.removeProjectRoot(jarFile, project.getProject()); |
| } |
| else |
| { |
| jarFile = ExportUtil.replaceProjectRoot(jarFile, project.getProject(), newProjectRoot); |
| } |
| if (jarFile.equals(jarFileOld)) |
| { |
| if (handleSubProjectClassesDirectory(jarFile, jarFileBuffer, jarFileAbsoluteBuffer)) |
| { |
| jarFile = jarFileBuffer.toString(); |
| jarFileAbsolute = jarFileAbsoluteBuffer.toString(); |
| } |
| } |
| rawClassPathEntries.add(jarFile); |
| rawClassPathEntriesAbsolute.add(jarFileAbsolute); |
| } |
| } |
| |
| /** |
| * Checks if file is a class directory of a subproject and fills string buffers with resolved values. |
| * @param file file to check |
| * @param jarFile filled with file location with varibale reference ${project.location}, |
| * which is also added to variable2valueMap |
| * @param jarFileAbsolute filled with absolute file location |
| * @return true if file is a classes directory |
| */ |
| private boolean handleSubProjectClassesDirectory(String file, StringBuffer jarFile, StringBuffer jarFileAbsolute) |
| { |
| // class directory of a subproject? |
| if (file != null && file.indexOf('/') == 0) |
| { |
| int i = file.indexOf("/", 1); //$NON-NLS-1$ |
| i = (i != -1) ? i : file.length(); |
| String subproject = file.substring(1, i); |
| IJavaProject javaproject = ExportUtil.getJavaProjectByName(subproject); |
| if (javaproject != null) |
| { |
| jarFile.setLength(0); |
| jarFileAbsolute.setLength(0); |
| String location = javaproject.getProject().getName() + ".location"; //$NON-NLS-1$ |
| jarFileAbsolute.append(ExportUtil.replaceProjectRoot(file, javaproject.getProject(), ExportUtil.getProjectRoot(javaproject))); |
| jarFile.append(ExportUtil.replaceProjectRoot(file, javaproject.getProject(), "${" + location + "}")); //$NON-NLS-1$ //$NON-NLS-2$ |
| variable2valueMap.put(location, ExportUtil.getProjectRoot(javaproject)); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private void handleVariables(IClasspathEntry entry) |
| { |
| if (entry.getContentKind() == IPackageFragmentRoot.K_SOURCE && |
| entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) |
| { |
| // found variable |
| String e = entry.getPath().toString(); |
| int index = e.indexOf('/'); |
| if (index == -1) |
| { |
| index = e.indexOf('\\'); |
| } |
| String variable = e; |
| String path = ""; //$NON-NLS-1$ |
| if (index != -1) |
| { |
| variable = e.substring(0, index); |
| path = e.substring(index); |
| } |
| String value = JavaCore.getClasspathVariable(variable).toString(); |
| variable2valueMap.put(variable, value); |
| rawClassPathEntriesAbsolute.add(value + path); |
| rawClassPathEntries.add("${" + variable + "}" + path); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private void handleUserLibraries(IClasspathEntry entry) throws JavaModelException |
| { |
| if (entry.getContentKind() == IPackageFragmentRoot.K_SOURCE && |
| entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) |
| { |
| // found (user) library |
| // String e = entry.getPath().toString(); // org.eclipse.jdt.USER_LIBRARY/MyLib |
| //JavaCore.USER_LIBRARY_CONTAINER_ID |
| IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project); |
| IClasspathEntry entries[] = container.getClasspathEntries(); |
| for (int i = 0; i < entries.length; i++) |
| { |
| handleJars(entries[i]); |
| } |
| } |
| } |
| |
| /** |
| * Add classDirs in front of classpath. |
| */ |
| private void addClasses() |
| { |
| for (Iterator iter = classDirs.iterator(); iter.hasNext();) |
| { |
| String classDir = (String) iter.next(); |
| if (newProjectRoot != null) |
| { |
| classDir = newProjectRoot + '/' + classDir; |
| } |
| rawClassPathEntries.add(0, classDir); |
| rawClassPathEntriesAbsolute.add(0, classDir); |
| } |
| } |
| |
| /** |
| * Get classpath for given project. |
| */ |
| public static String getClasspath(IJavaProject project) throws JavaModelException |
| { |
| List items = EclipseClasspath.getClasspathList(project); |
| return toString(items, File.pathSeparator); |
| } |
| |
| /** |
| * Get classpath for given project. |
| */ |
| public static String getClasspath(IJavaProject project, boolean includeSubProjects) throws JavaModelException |
| { |
| List items = EclipseClasspath.getClasspathList(project, includeSubProjects); |
| return toString(items, File.pathSeparator); |
| } |
| |
| /** |
| * Get classpath for given project. |
| */ |
| public static List getClasspathList(IJavaProject project) throws JavaModelException |
| { |
| EclipseClasspath instance = new EclipseClasspath(project, ExportUtil.getProjectRoot(project)); |
| return instance.removeDuplicates(instance.rawClassPathEntriesAbsolute); |
| } |
| |
| /** |
| * Get classpath for given project. |
| */ |
| public static List getClasspathList(IJavaProject project, boolean includeSubProjects) throws JavaModelException |
| { |
| EclipseClasspath instance = new EclipseClasspath(project, ExportUtil.getProjectRoot(project)); |
| List classpath = instance.rawClassPathEntriesAbsolute; |
| if (!includeSubProjects) |
| { |
| return instance.removeDuplicates(classpath); |
| } |
| Set subprojects = ExportUtil.getClasspathProjectsRecursive(project); |
| for (Iterator iter = subprojects.iterator(); iter.hasNext();) |
| { |
| IJavaProject subproject = (IJavaProject) iter.next(); |
| instance = new EclipseClasspath(subproject, ExportUtil.getProjectRoot(subproject)); |
| classpath.addAll(instance.rawClassPathEntriesAbsolute); |
| } |
| return instance.removeDuplicates(classpath); |
| } |
| |
| public static String toString(Collection c, String separator) |
| { |
| StringBuffer b = new StringBuffer(); |
| for (Iterator iter = c.iterator(); iter.hasNext();) |
| { |
| b.append((String) iter.next()); |
| b.append(separator); |
| } |
| if (c.size() > 0) { |
| b.delete(b.length() - separator.length(), b.length()); |
| } |
| return b.toString(); |
| } |
| |
| /** |
| * Remove duplicates preserving original order. |
| * @param l list to remove duplicates from |
| * @return new list without duplicates |
| */ |
| protected List removeDuplicates(List l) |
| { |
| List res = new ArrayList(); |
| for (Iterator iter = l.iterator(); iter.hasNext();) |
| { |
| Object element = iter.next(); |
| if (!res.contains(element)) |
| { |
| res.add(element); |
| } |
| } |
| return res; |
| } |
| } |