package jetbrains.buildServer.eclipse.agent.builder.ant; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import jetbrains.buildServer.eclipse.java.BuildDescriptor; import jetbrains.buildServer.eclipse.java.IClasspathContainer; import jetbrains.buildServer.eclipse.java.IClasspathEntry; import jetbrains.buildServer.eclipse.java.JDTConstants; import jetbrains.buildServer.eclipse.java.JDTUtil; import jetbrains.buildServer.eclipse.java.PlatformDescriptor; import org.jetbrains.annotations.NotNull; public class EclipseClasspath { protected List srcDirs = new ArrayList(); protected List classDirs = new ArrayList(); protected List> inclusionLists = new ArrayList>(); protected List> exclusionLists = new ArrayList>(); protected Map variable2valueMap = new LinkedHashMap(); protected List rawClassPathEntries = new ArrayList(); protected List rawClassPathEntriesAbsolute = new ArrayList(); private File/*IJavaProject*/project; @SuppressWarnings("unused") private PlatformDescriptor platform; private BuildDescriptor build; private static Map userLibraryCache = new HashMap(); /** * Initialize object with classpath of given project. * * @param platform * @param collection * @param unresolvedLibs */ public EclipseClasspath(final @NotNull PlatformDescriptor platform, final @NotNull BuildDescriptor build, final @NotNull File project, final @NotNull Collection unresolvedLibs, final @NotNull Collection unresolvedVars) throws /*JavaModel*/Exception { // this.project = project; this.platform = platform; this.build = build; this.project = project; handle(JDTUtil.getRawClasspath(project)/*.getRawClasspath()*/, unresolvedLibs, unresolvedVars); } // /** // * Initialize object with runtime classpath of given launch configuration. // * @param project project that contains given launch configuration conf // * @param conf launch configuration // * @param bootstrap if true only bootstrap entries are added, if false only // * non-bootstrap entries are added // */ // public EclipseClasspath(File /*IJavaProject */project, /*ILaunchConfiguration conf,*/ boolean bootstrap) // throws /*Core*/Exception // { // this.project = project; // // // convert IRuntimeClasspathEntry to IClasspathEntry // IRuntimeClasspathEntry[] runtimeEntries; // // see AbstractJavaLaunchConfigurationDelegate // runtimeEntries = JavaRuntime.computeUnresolvedRuntimeClasspath(conf); // List classpathEntries = new ArrayList(runtimeEntries.length); // for (int i = 0; i < runtimeEntries.length; i++) // { // IRuntimeClasspathEntry entry = runtimeEntries[i]; // if ( bootstrap && (entry.getClasspathProperty() == IRuntimeClasspathEntry.BOOTSTRAP_CLASSES) || // ! bootstrap && (entry.getClasspathProperty() != IRuntimeClasspathEntry.BOOTSTRAP_CLASSES)) // { // // NOTE: See AbstractJavaLaunchConfigurationDelegate.getBootpathExt() // // for an alternate bootclasspath detection // if (entry.getClass().getName().equals("org.eclipse.jdt.internal.launching.VariableClasspathEntry")) //$NON-NLS-1$ // { // IClasspathEntry e = convertVariableClasspathEntry(entry); // if (e != null) // { // classpathEntries.add(e); // } // } // else if (entry.getClass().getName().equals("org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry")) //$NON-NLS-1$ // { // IClasspathEntry e = JavaCore.newProjectEntry(entry.getPath()); // classpathEntries.add(e); // } // else if (entry.getClasspathEntry() != null) // { // classpathEntries.add(entry.getClasspathEntry()); // } // } // else if (bootstrap && entry.toString().startsWith(JavaRuntime.JRE_CONTAINER)) // { // classpathEntries.add(entry.getClasspathEntry()); // } // else if (bootstrap && entry.toString().startsWith(JavaCore.USER_LIBRARY_CONTAINER_ID)) // { // classpathEntries.add(entry.getClasspathEntry()); // } // } // IClasspathEntry[] entries = // (IClasspathEntry[]) classpathEntries.toArray(new IClasspathEntry[classpathEntries.size()]); // // handle(entries); // } private void handle(IClasspathEntry[] entries, Collection unresolvedLibs, Collection unresolvedVars) throws /*JavaModel*/Exception { for (int i = 0; i < entries.length; i++) { handleSources(entries[i]); unresolvedVars.addAll(handleVariables(entries[i])); handleJars(entries[i]); unresolvedLibs.addAll(handleLibraries(entries[i])); handleProjects(entries[i]); } } private void handleSources(IClasspathEntry entry) throws /*JavaModel*/Exception { String projectRoot = JDTUtil.getProjectRoot(project); final File outputLocation = JDTUtil.getOutputLocation(project); String defaultClassDir = outputLocation.getPath();// project.getOutputLocation().toString(); String defaultClassDirAbsolute = JDTUtil.resolve(JDTUtil.getOutputLocation(project)/*project.getOutputLocation()*/); if (entry.getContentKind() == JDTConstants.IPackageFragmentRoot_K_SOURCE && entry.getEntryKind() == JDTConstants.IClasspathEntry_CPE_SOURCE) { // found source path File/*IPath*/srcDirPath = entry.getPath(); File/*IPath*/classDirPath = entry.getOutputLocation(); String srcDir = handleLinkedResource(srcDirPath); JDTUtil.removeProjectRoot((srcDirPath != null) ? srcDirPath.toString() : projectRoot, project/*.getProject()*/); String classDir = JDTUtil.removeProjectRoot((classDirPath != null) ? classDirPath.toString() : defaultClassDir, project/*.getProject()*/); srcDirs.add(srcDir); classDirs.add(classDir); String classDirAbsolute = (classDirPath != null) ? JDTUtil.resolve(classDirPath) : defaultClassDirAbsolute; rawClassPathEntries.add(classDir); rawClassPathEntriesAbsolute.add(classDirAbsolute); String/*IPath*/[] inclusions = entry.getInclusionPatterns(); List inclusionList = new ArrayList(); for (int j = 0; j < inclusions.length; j++) { if (inclusions[j] != null) { inclusionList.add(JDTUtil.removeProjectRoot(inclusions[j].toString(), project/*.getProject()*/)); } } inclusionLists.add(inclusionList); String/*IPath*/[] exclusions = entry.getExclusionPatterns(); List exclusionList = new ArrayList(); for (int j = 0; j < exclusions.length; j++) { if (exclusions[j] != null) { exclusionList.add(JDTUtil.removeProjectRoot(exclusions[j].toString(), project/*.getProject()*/)); } } exclusionLists.add(exclusionList); } } /** * Check if given source path is a linked resource. Add values to * {@link #variable2valueMap} accordingly. * * @param srcDirPath * source dir as IPath * @return source directory with reference, e.g. ${MYPATH}/src, if it is no * link, orginal source dir is returned */ private String handleLinkedResource(final File/*IPath*/srcDirPath) { String projectRoot = JDTUtil.getProjectRoot(project); String srcDir = JDTUtil.removeProjectRoot((srcDirPath != null) ? srcDirPath.toString() : projectRoot, project/*.getProject()*/); if (srcDirPath == null) { return srcDir; } // IFile file; // try // { // file = ResourcesPlugin.getWorkspace().getRoot().getFile(srcDirPath); // } // catch (IllegalArgumentException e) // { // return srcDir; // } //TODO: perhaps should not support Linked Resources? // if (file.isLinked()) // { // String pathVariable = file.getRawLocation().segment(0).toString(); // IPath pathVariableValue = file.getWorkspace().getPathVariableManager().getValue(pathVariable); // if (pathVariableValue != null) // { // // path variable was used // String pathVariableExtension = file.getRawLocation().removeFirstSegments(1).toString(); // Bug 192726 // String relativePath = ExportUtil.getRelativePath(pathVariableValue.toString(), // projectRoot); // variable2valueMap.put(pathVariable + ".pathvariable", relativePath); //$NON-NLS-1$ // variable2valueMap.put(srcDir + ".link", //$NON-NLS-1$ // "${" + pathVariable + ".pathvariable}/" + pathVariableExtension); //$NON-NLS-1$ //$NON-NLS-2$ // } // else // { // String relativePath = ExportUtil.getRelativePath(file.getLocation() + "", //$NON-NLS-1$ // projectRoot); // variable2valueMap.put(srcDir + ".link", relativePath); //$NON-NLS-1$ // } // srcDir = "${" + srcDir + ".link}"; //$NON-NLS-1$ //$NON-NLS-2$ // } return srcDir; } private void handleJars(IClasspathEntry entry) { if (entry.getContentKind() == JDTConstants.IPackageFragmentRoot_K_BINARY && entry.getEntryKind() == JDTConstants.IClasspathEntry_CPE_LIBRARY) { String jarFile = entry.getPath().toString(); StringBuffer jarFileBuffer = new StringBuffer(); StringBuffer jarFileAbsoluteBuffer = new StringBuffer(); String jarFileAbsolute = JDTUtil.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; jarFile = JDTUtil.removeProjectRoot(jarFile, project/*.getProject()*/); 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 variable 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); i = (i != -1) ? i : file.length(); String subproject = file.substring(1, i); File/*IJavaProject*/javaproject = JDTUtil.getJavaProjectByName(subproject); if (javaproject != null) { jarFile.setLength(0); jarFileAbsolute.setLength(0); String location = JDTUtil.getProjectName(javaproject)/*javaproject.getProject().getName()*/+ ".location"; //$NON-NLS-1$ jarFileAbsolute.append(JDTUtil.replaceProjectRoot(file, javaproject/*.getProject()*/, JDTUtil.getProjectRoot(javaproject))); jarFile.append(JDTUtil.replaceProjectRoot(file, javaproject/*.getProject()*/, "${" + location + "}")); //$NON-NLS-1$ //$NON-NLS-2$ String projectRoot = JDTUtil.getProjectRoot(project); String relativePath = JDTUtil.getRelativePath(JDTUtil.getProjectRoot(javaproject), projectRoot); variable2valueMap.put(location, relativePath); return true; } } return false; } private Collection handleVariables(IClasspathEntry entry) { final ArrayList unresolved = new ArrayList(); if (entry.getContentKind() == JDTConstants.IPackageFragmentRoot_K_SOURCE && entry.getEntryKind() == JDTConstants.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); } File/*IPath*/value = JDTUtil./*JavaCore.*/getClasspathVariable(variable); if (value != null) { String projectRoot = JDTUtil.getProjectRoot(project); String relativePath = JDTUtil.getRelativePath(value.toString(), projectRoot); variable2valueMap.put(variable, relativePath); } else if (variable2valueMap.get(variable) == null) { // only add empty value, if variable is new variable2valueMap.put(variable, ""); //$NON-NLS-1$ unresolved.add(variable); } rawClassPathEntriesAbsolute.add(value + path); rawClassPathEntries.add("${" + variable + "}" + path); //$NON-NLS-1$ //$NON-NLS-2$ } return unresolved; } private Collection handleLibraries(IClasspathEntry entry) throws /*JavaModel*/Exception { final ArrayList unresolved = new ArrayList(); if (entry.getContentKind() == JDTConstants.IPackageFragmentRoot_K_SOURCE && entry.getEntryKind() == JDTConstants.IClasspathEntry_CPE_CONTAINER) { // found library IClasspathContainer container = JDTUtil/*JavaCore*/.getClasspathContainer(entry.getPath(), platform, build, project); if (container == null) { // jar missing (project not compile clean) unresolved.add(entry.getPath().toString()); return unresolved; } String jar = entry.getPath().toString(); String refName; if (jar.startsWith(JDTConstants.JavaRuntime_JRE_CONTAINER)) { // JRE System Library refName = "${jre.container}"; //$NON-NLS-1$ } else if (jar.startsWith(JDTConstants.JavaCore_USER_LIBRARY_CONTAINER)) { // User Library String libraryName = container.getDescription(); refName = "${" + libraryName + ".userclasspath}"; //$NON-NLS-1$ //$NON-NLS-2$ if (container.getKind() == IClasspathContainer.K_SYSTEM) { refName = "${" + libraryName + ".bootclasspath}"; //$NON-NLS-1$ //$NON-NLS-2$ } } else { // Library dependencies: e.g. Plug-in Dependencies String libraryName = container.getDescription(); refName = "${" + libraryName + ".libraryclasspath}"; //$NON-NLS-1$ //$NON-NLS-2$ } userLibraryCache.put(refName, container); srcDirs.add(refName); classDirs.add(refName); rawClassPathEntries.add(refName); rawClassPathEntriesAbsolute.add(refName); inclusionLists.add(new ArrayList()); exclusionLists.add(new ArrayList()); } return unresolved; } private void handleProjects(IClasspathEntry entry) { if (entry.getContentKind() == JDTConstants.IPackageFragmentRoot_K_SOURCE && entry.getEntryKind() == JDTConstants.IClasspathEntry_CPE_PROJECT) { // found required project on build path String subProjectRoot = entry.getPath().toString(); File/*IJavaProject*/subProject = JDTUtil.getJavaProject(subProjectRoot); if (subProject == null) { // project was not loaded in workspace System.err.println(/*);AntUIPlugin.log(*/"project is not loaded in workspace: " + subProjectRoot/*, null*/); //$NON-NLS-1$ return; } // only add an indicator that this is a project reference String classpathRef = "${" + JDTUtil.getProjectName(subProject)/*subProject.getProject().getName()*/+ ".classpath}"; //$NON-NLS-1$ //$NON-NLS-2$ srcDirs.add(classpathRef); classDirs.add(classpathRef); rawClassPathEntries.add(classpathRef); rawClassPathEntriesAbsolute.add(classpathRef); inclusionLists.add(new ArrayList()); exclusionLists.add(new ArrayList()); } } // /** // * Get runtime classpath items for given project separated with path separator. // */ // public static String getClasspath(IJavaProject project) throws /*Core*/Exception // { // List items = getClasspathList(project); // return ExportUtil.toString(items, File.pathSeparator); // } // // /** // * Get runtime classpath items for given project. // */ // public static List getClasspathList(IJavaProject project) throws /*Core*/Exception // { // String[] classpath = JavaRuntime.computeDefaultRuntimeClassPath(project); // return Arrays.asList(classpath); // } /** * Check if given string is a reference. */ public static boolean isReference(String s) { return isProjectReference(s) || isUserLibraryReference(s) || isUserSystemLibraryReference(s) || isLibraryReference(s) || isJreReference(s); // NOTE: A linked resource is no reference } /** * Check if given string is a project reference. */ public static boolean isProjectReference(String s) { return s.startsWith("${") && s.endsWith(".classpath}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Resolves given project reference to a project. * * @return null if project is not resolvable */ public static File/*IJavaProject*/resolveProjectReference(String s) { String name = JDTUtil.removePrefixAndSuffix(s, "${", ".classpath}"); //$NON-NLS-1$ //$NON-NLS-2$ return JDTUtil.getJavaProjectByName(name); } /** * Check if given string is a user library reference. */ public static boolean isUserLibraryReference(String s) { return s.startsWith("${") && s.endsWith(".userclasspath}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Check if given string is a user system library reference. This library is * added to the compiler boot classpath. */ public static boolean isUserSystemLibraryReference(String s) { return s.startsWith("${") && s.endsWith(".bootclasspath}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Check if given string is a library reference. e.g. Plug-in dependencies are * library references. * */ public static boolean isLibraryReference(String s) { return s.startsWith("${") && s.endsWith(".libraryclasspath}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Check if given string is a JRE reference. */ public static boolean isJreReference(String s) { return s.equals("${jre.container}"); //$NON-NLS-1$ } /** * Resolves given user (system) library or plugin reference to its container. * *

* NOTE: The library can only be resolved if an EclipseClasspath object was * created which had a reference to this library. The class holds an internal * cache to circumvent that UserLibraryManager is an internal class. * * @return null if library is not resolvable */ public static IClasspathContainer resolveUserLibraryReference(String s) { return /*(IClasspathContainer) */userLibraryCache.get(s); } /** * Check if given string is a linked resource. * */ public static boolean isLinkedResource(String s) { return s.startsWith("${") && s.endsWith(".link}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Get source folder name of a linked resource. * * @see #isLinkedResource(String) */ public static String getLinkedResourceName(String s) { return JDTUtil.removePrefixAndSuffix(s, "${", ".link}"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Resolves given linked resource to an absolute file location. */ public String resolveLinkedResource(String s) { String name = JDTUtil.removePrefixAndSuffix(s, "${", "}"); //$NON-NLS-1$ //$NON-NLS-2$ String value = (String) variable2valueMap.get(name); String suffix = ".pathvariable}"; //$NON-NLS-1$ int i = value.indexOf(suffix); if (i != -1) { // path variable String pathVariable = value.substring(0, i + suffix.length() - 1); pathVariable = JDTUtil.removePrefix(pathVariable, "${"); //$NON-NLS-1$ return (String) variable2valueMap.get(pathVariable) + value.substring(i + suffix.length()); } return value; } /** * Convert a VariableClasspathEntry to a IClasspathEntry. * *

* This is a workaround as entry.getClasspathEntry() returns null. */ // private IClasspathEntry convertVariableClasspathEntry(IRuntimeClasspathEntry entry) // { // try // { // Document doc = ExportUtil.parseXmlString(entry.getMemento()); // Element element = (Element) doc.getElementsByTagName("memento").item(0); //$NON-NLS-1$ // String variableString = element.getAttribute("variableString"); //$NON-NLS-1$ // ExportUtil.addVariable(variable2valueMap, variableString, ExportUtil.getProjectRoot(project)); // // remove ${...} from string to be conform for handleVariables() // variableString = ExportUtil.removePrefix(variableString, "${");//$NON-NLS-1$ // int i = variableString.indexOf('}'); // if (i != -1) // { // variableString = variableString.substring(0, i) // + variableString.substring(i + 1); // } // IPath path = new Path(variableString); // return JavaCore.newVariableEntry(path, null, null); // } // catch (Exception e) // { // AntUIPlugin.log(e); // return null; // } // // } }