| /******************************************************************************* |
| * Copyright (c) 2004, 2017 Richard Hoefter and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bug 95300, bug 95297, bug 128104, bug 201180, bug 288830 |
| * IBM Corporation - NLS'ing and incorporating into Eclipse. |
| * - Bug 177833 Class created from combination of all utility classes of contribution |
| * - Bug 267459 Java project with an external jar file from C:\ on the build path throws a NPE during the Ant Buildfile generation. |
| * - bug fixing |
| *******************************************************************************/ |
| |
| package org.eclipse.ant.internal.ui.datatransfer; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.OutputKeys; |
| import javax.xml.transform.Result; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerConfigurationException; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.TransformerFactoryConfigurationError; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| |
| import org.eclipse.ant.internal.core.IAntCoreConstants; |
| import org.eclipse.ant.internal.ui.AntUIPlugin; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaModelMarker; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.junit.JUnitCore; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.swt.widgets.Shell; |
| import org.w3c.dom.Document; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Collection of utility methods to help when exporting to an Ant build file. |
| */ |
| public class ExportUtil { |
| private ExportUtil() { |
| } |
| |
| /** |
| * Get resource from selection. |
| */ |
| public static IResource getResource(ISelection selection) { |
| if (selection instanceof IStructuredSelection) { |
| for (Iterator<IAdaptable> iter = ((IStructuredSelection) selection).iterator(); iter.hasNext();) { |
| IAdaptable adaptable = iter.next(); |
| return adaptable.getAdapter(IResource.class); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Get Java project from resource. |
| */ |
| public static IJavaProject getJavaProjectByName(String name) { |
| try { |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name); |
| if (project.exists()) { |
| return JavaCore.create(project); |
| } |
| } |
| catch (IllegalArgumentException iae) { |
| // do nothing |
| } |
| return null; |
| } |
| |
| /** |
| * Get project root for given project. |
| */ |
| public static String getProjectRoot(IJavaProject project) { |
| if (project == null) { |
| return null; |
| } |
| IResource resource = project.getResource(); |
| if (resource == null) { |
| return null; |
| } |
| IPath location = resource.getLocation(); |
| if (location == null) { |
| return null; |
| } |
| return location.toString(); |
| } |
| |
| /** |
| * Convert Eclipse path to absolute filename. |
| * |
| * @param file |
| * Project root optionally followed by resource name. An absolute path is simply converted to a string. |
| * @return full qualified path |
| */ |
| public static String resolve(IPath file) { |
| if (file == null) { |
| return null; |
| } |
| try { |
| IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(file); |
| URI uri = f.getLocationURI(); |
| return (uri != null) ? uri.toString() : f.toString(); |
| } |
| catch (IllegalArgumentException e) { |
| // resource is missing |
| String projectName = removePrefix(file.toString(), "/"); //$NON-NLS-1$ |
| IJavaProject project = getJavaProjectByName(projectName); |
| if (project != null) { |
| return getProjectRoot(project); |
| } |
| // project is null because file is not enclosed in a project i.e. |
| // external jar |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=267459 |
| return file.toOSString(); |
| } |
| } |
| |
| /** |
| * Get Java project for given root. |
| */ |
| public static IJavaProject getJavaProject(String root) { |
| IPath path = new Path(root); |
| if (path.segmentCount() == 1) { |
| return getJavaProjectByName(root); |
| } |
| IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path); |
| if (resource != null && resource.getType() == IResource.PROJECT) { |
| if (resource.exists()) { |
| return (IJavaProject) JavaCore.create(resource); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Remove project root from given project file. |
| */ |
| public static String removeProjectRoot(String file, IProject project) { |
| String res = removePrefix(file, '/' + project.getName() + '/'); |
| if (res.equals('/' + project.getName())) { |
| return "."; //$NON-NLS-1$ |
| } |
| return res; |
| } |
| |
| /** |
| * Remove project root from given project file. |
| * |
| * @param newProjectRoot |
| * replace project root, e.g. with a variable ${project.location} |
| */ |
| public static String replaceProjectRoot(String file, IProject project, String newProjectRoot) { |
| String res = removeProjectRoot(file, project); |
| if (res.equals(".")) //$NON-NLS-1$ |
| { |
| return newProjectRoot; |
| } |
| if (newProjectRoot == null) { |
| return res; |
| } |
| if (!res.equals(file)) { |
| return newProjectRoot + '/' + res; |
| } |
| return res; |
| } |
| |
| /** |
| * Get for given project all directly dependent projects. |
| * |
| * @return set of IJavaProject objects |
| */ |
| public static List<IJavaProject> getClasspathProjects(IJavaProject project) throws JavaModelException { |
| List<IJavaProject> projects = new ArrayList<>(); |
| IClasspathEntry entries[] = project.getRawClasspath(); |
| addClasspathProjects(projects, entries); |
| return sortProjectsUsingBuildOrder(projects); |
| } |
| |
| private static void addClasspathProjects(List<IJavaProject> projects, IClasspathEntry[] entries) { |
| for (int i = 0; i < entries.length; i++) { |
| IClasspathEntry classpathEntry = entries[i]; |
| if (classpathEntry.getContentKind() == IPackageFragmentRoot.K_SOURCE && classpathEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { |
| // found required project on build path |
| String subProjectRoot = classpathEntry.getPath().toString(); |
| IJavaProject subProject = getJavaProject(subProjectRoot); |
| // is project available in workspace |
| if (subProject != null) { |
| projects.add(subProject); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get for given project all directly and indirectly dependent projects. |
| * |
| * @return set of IJavaProject objects |
| */ |
| public static List<IJavaProject> getClasspathProjectsRecursive(IJavaProject project) throws JavaModelException { |
| LinkedList<IJavaProject> result = new LinkedList<>(); |
| getClasspathProjectsRecursive(project, result); |
| return sortProjectsUsingBuildOrder(result); |
| } |
| |
| private static void getClasspathProjectsRecursive(IJavaProject project, LinkedList<IJavaProject> result) throws JavaModelException { |
| List<IJavaProject> projects = getClasspathProjects(project); |
| for (Iterator<IJavaProject> iter = projects.iterator(); iter.hasNext();) { |
| IJavaProject javaProject = iter.next(); |
| if (!result.contains(javaProject)) { |
| result.addFirst(javaProject); |
| getClasspathProjectsRecursive(javaProject, result); // recursion |
| } |
| } |
| } |
| |
| /** |
| * Sort projects according to General -> Workspace -> Build Order. |
| * |
| * @param javaProjects |
| * list of IJavaProject objects |
| * @return list of IJavaProject objects with new order |
| */ |
| private static List<IJavaProject> sortProjectsUsingBuildOrder(List<IJavaProject> javaProjects) { |
| if (javaProjects.isEmpty()) { |
| return javaProjects; |
| } |
| List<IJavaProject> result = new ArrayList<>(javaProjects.size()); |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| String[] buildOrder = workspace.getDescription().getBuildOrder(); |
| if (buildOrder == null) {// default build order |
| IProject[] projects = new IProject[javaProjects.size()]; |
| int i = 0; |
| for (Iterator<IJavaProject> iter = javaProjects.iterator(); iter.hasNext(); i++) { |
| IJavaProject javaProject = iter.next(); |
| projects[i] = javaProject.getProject(); |
| } |
| IWorkspace.ProjectOrder po = ResourcesPlugin.getWorkspace().computeProjectOrder(projects); |
| projects = po.projects; |
| buildOrder = new String[projects.length]; |
| for (i = 0; i < projects.length; i++) { |
| buildOrder[i] = projects[i].getName(); |
| } |
| } |
| |
| for (int i = 0; i < buildOrder.length && !javaProjects.isEmpty(); i++) { |
| String projectName = buildOrder[i]; |
| for (Iterator<IJavaProject> iter = javaProjects.iterator(); iter.hasNext();) { |
| IJavaProject javaProject = iter.next(); |
| if (javaProject.getProject().getName().equals(projectName)) { |
| result.add(javaProject); |
| iter.remove(); |
| } |
| } |
| } |
| // add any remaining projects not specified in the build order |
| result.addAll(javaProjects); |
| return result; |
| } |
| |
| /** |
| * Returns cyclic dependency marker for a given project. |
| * |
| * <p> |
| * See org.eclipse.jdt.core.tests.model.ClasspathTests.numberOfCycleMarkers. |
| * |
| * @param javaProject |
| * project for which cyclic dependency marker should be found |
| * @return cyclic dependency marker for a given project or <code>null</code> if there is no such marker |
| * @throws CoreException |
| */ |
| public static IMarker getCyclicDependencyMarker(IJavaProject javaProject) throws CoreException { |
| IMarker[] markers = javaProject.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ONE); |
| for (int i = 0; i < markers.length; i++) { |
| IMarker marker = markers[i]; |
| String cycleAttr = (String) marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED); |
| if (cycleAttr != null && cycleAttr.equals("true")) //$NON-NLS-1$ |
| { |
| return marker; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Find JUnit tests. Same tests are also returned by Eclipse run configuration wizard. |
| * |
| * @param containerHandle |
| * project, package or source folder |
| */ |
| public static IType[] findTestsInContainer(String containerHandle) { |
| IJavaElement container = JavaCore.create(containerHandle); |
| if (container == null) { |
| return new IType[0]; |
| } |
| try { |
| return JUnitCore.findTestTypes(container, new NullProgressMonitor()); |
| } |
| catch (OperationCanceledException e) { |
| AntUIPlugin.log(e); |
| } |
| catch (CoreException e) { |
| AntUIPlugin.log(e); |
| } |
| return new IType[0]; |
| } |
| |
| /** |
| * Compares projects by project name. |
| */ |
| public static synchronized Comparator<IJavaProject> getJavaProjectComparator() { |
| if (javaProjectComparator == null) { |
| javaProjectComparator = new JavaProjectComparator(); |
| } |
| return javaProjectComparator; |
| } |
| |
| private static Comparator<IJavaProject> javaProjectComparator; |
| |
| private static class JavaProjectComparator implements Comparator<IJavaProject> { |
| @Override |
| public int compare(IJavaProject o1, IJavaProject o2) { |
| IJavaProject j1 = o1; |
| IJavaProject j2 = o2; |
| return j1.getProject().getName().compareTo(j2.getProject().getName()); |
| } |
| } |
| |
| /** |
| * Compares IFile objects. |
| */ |
| public static synchronized Comparator<IFile> getIFileComparator() { |
| if (fileComparator == null) { |
| fileComparator = new IFileComparator(); |
| } |
| return fileComparator; |
| } |
| |
| private static Comparator<IFile> fileComparator; |
| |
| private static class IFileComparator implements Comparator<IFile> { |
| @Override |
| public int compare(IFile o1, IFile o2) { |
| IFile f1 = o1; |
| IFile f2 = o2; |
| return f1.toString().compareTo(f2.toString()); |
| } |
| } |
| |
| /** |
| * Compares IType objects. |
| */ |
| public static synchronized Comparator<IType> getITypeComparator() { |
| if (typeComparator == null) { |
| typeComparator = new TypeComparator(); |
| } |
| return typeComparator; |
| } |
| |
| private static Comparator<IType> typeComparator; |
| |
| private static class TypeComparator implements Comparator<IType> { |
| @Override |
| public int compare(IType o1, IType o2) { |
| IType t1 = o1; |
| IType t2 = o2; |
| return t1.getFullyQualifiedName().compareTo(t2.getFullyQualifiedName()); |
| } |
| } |
| |
| /** |
| * Platform specific newline character(s). |
| */ |
| public static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$ |
| |
| public static String removePrefix(String s, String prefix) { |
| if (s == null) { |
| return null; |
| } |
| if (s.startsWith(prefix)) { |
| return s.substring(prefix.length()); |
| } |
| return s; |
| } |
| |
| /** |
| * Remove suffix from given string. |
| */ |
| public static String removeSuffix(String s, String suffix) { |
| if (s == null) { |
| return null; |
| } |
| if (s.endsWith(suffix)) { |
| return s.substring(0, s.length() - suffix.length()); |
| } |
| return s; |
| } |
| |
| /** |
| * Remove prefix and suffix from given string. |
| */ |
| public static String removePrefixAndSuffix(String s, String prefix, String suffix) { |
| return removePrefix(removeSuffix(s, suffix), prefix); |
| } |
| |
| /** |
| * Convert document to formatted XML string. |
| */ |
| public static String toString(Document doc) throws TransformerConfigurationException, TransformerFactoryConfigurationError, TransformerException { |
| // NOTE: There are different transformer implementations in the wild, |
| // which are configured differently |
| // regarding the indent size: |
| // Java 1.4: org.apache.xalan.transformer.TransformerIdentityImpl |
| // Java 1.5: |
| // com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl |
| |
| StringWriter writer = new StringWriter(); |
| Source source = new DOMSource(doc); |
| Result result = new StreamResult(writer); |
| TransformerFactory factory = TransformerFactory.newInstance(); |
| // https://ant.apache.org/manual/Tasks/style.html |
| // Need this feature to set true for Java 9 to enable extension Functions in the presence of Security manager |
| factory.setFeature("http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions", Boolean.TRUE); //$NON-NLS-1$ |
| boolean indentFallback = false; |
| try { |
| // indent using TransformerImpl |
| factory.setAttribute("indent-number", "4"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| catch (IllegalArgumentException e) { |
| // option not supported, set indent size below |
| indentFallback = true; |
| } |
| Transformer transformer = factory.newTransformer(); |
| transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ |
| if (indentFallback) { |
| // indent using TransformerIdentityImpl |
| transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| transformer.transform(source, result); |
| return writer.toString(); |
| } |
| |
| /** |
| * Read XML file. |
| */ |
| public static Document parseXmlFile(File file) throws SAXException, IOException, ParserConfigurationException { |
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| factory.setValidating(false); |
| Document doc = factory.newDocumentBuilder().parse(file); |
| return doc; |
| } |
| |
| /** |
| * Read XML string. |
| */ |
| public static Document parseXmlString(String s) throws SAXException, IOException, ParserConfigurationException { |
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| factory.setValidating(false); |
| Document doc = factory.newDocumentBuilder().parse(new ByteArrayInputStream(s.getBytes())); |
| return doc; |
| } |
| |
| /** |
| * Converts collection to a separated string. |
| * |
| * @param c |
| * collection |
| * @param separator |
| * string to separate items |
| * @return collection items separated with given separator |
| */ |
| public static String toString(Collection<String> c, String separator) { |
| StringBuilder b = new StringBuilder(); |
| for (Iterator<String> iter = c.iterator(); iter.hasNext();) { |
| b.append(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 |
| */ |
| public static List<String> removeDuplicates(List<String> l) { |
| List<String> res = new ArrayList<>(); |
| for (Iterator<String> iter = l.iterator(); iter.hasNext();) { |
| String element = iter.next(); |
| if (!res.contains(element)) { |
| res.add(element); |
| } |
| } |
| return res; |
| } |
| |
| /** |
| * Check if given file exists that was not written by this export. |
| */ |
| public static boolean existsUserFile(String filename) { |
| File buildFile = new File(filename); |
| if (buildFile.exists()) { |
| try (BufferedReader in = new BufferedReader(new FileReader(buildFile))) { |
| int i = BuildFileCreator.WARNING.indexOf(NEWLINE); |
| String warning = BuildFileCreator.WARNING.substring(0, i); |
| String line; |
| while ((line = in.readLine()) != null) { |
| if (line.contains(warning)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| catch (FileNotFoundException e) { |
| return false; |
| } |
| catch (IOException e) { |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Request write access to given file. Depending on the version control plug-in opens a confirm checkout dialog. |
| * |
| * @param shell |
| * parent instance for dialogs |
| * @param file |
| * file to request write access for |
| * @return <code>true</code> if user confirmed checkout |
| */ |
| public static boolean validateEdit(Shell shell, IFile file) { |
| return file.getWorkspace().validateEdit(new IFile[] { file }, shell).isOK(); |
| } |
| |
| /** |
| * Request write access to given files. Depending on the version control plug-in opens a confirm checkout dialog. |
| * |
| * @param shell |
| * parent instance for dialogs |
| * @return <code>IFile</code> objects for which user confirmed checkout |
| * @throws CoreException |
| * thrown if project is under version control, but not connected |
| */ |
| public static Set<IFile> validateEdit(Shell shell, List<IFile> files) throws CoreException { |
| Set<IFile> confirmedFiles = new TreeSet<>(getIFileComparator()); |
| if (files.size() == 0) { |
| return confirmedFiles; |
| } |
| IStatus status = files.get(0).getWorkspace().validateEdit(files.toArray(new IFile[files.size()]), shell); |
| if (status.isMultiStatus() && status.getChildren().length > 0) { |
| for (int i = 0; i < status.getChildren().length; i++) { |
| IStatus statusChild = status.getChildren()[i]; |
| if (statusChild.isOK()) { |
| confirmedFiles.add(files.get(i)); |
| } |
| } |
| } else if (status.isOK()) { |
| for (Iterator<IFile> iterator = files.iterator(); iterator.hasNext();) { |
| IFile file = iterator.next(); |
| confirmedFiles.add(file); |
| } |
| } |
| if (status.getSeverity() == IStatus.ERROR) { |
| // not possible to checkout files: not connected to version |
| // control plugin or hijacked files and made read-only, so |
| // collect error messages provided by validator and re-throw |
| StringBuilder message = new StringBuilder(status.getPlugin() + ": " //$NON-NLS-1$ |
| + status.getMessage() + NEWLINE); |
| if (status.isMultiStatus()) { |
| for (int i = 0; i < status.getChildren().length; i++) { |
| IStatus statusChild = status.getChildren()[i]; |
| message.append(statusChild.getMessage() + NEWLINE); |
| } |
| } |
| throw new CoreException(new Status(IStatus.ERROR, AntUIPlugin.PI_ANTUI, 0, message.toString(), null)); |
| } |
| |
| return confirmedFiles; |
| } |
| |
| /** |
| * Check if given classpath is a reference to the default classpath of the project. Ideal for testing if runtime classpath was customized. |
| */ |
| public static boolean isDefaultClasspath(IJavaProject project, EclipseClasspath classpath) { |
| // default classpath contains exactly the JRE and the project reference |
| List<String> list = removeDuplicates(classpath.rawClassPathEntries); |
| if (list.size() != 2) { |
| return false; |
| } |
| String entry1 = list.get(0); |
| String entry2 = list.get(1); |
| if (!EclipseClasspath.isJreReference(entry1)) { |
| return false; |
| } |
| if (EclipseClasspath.isProjectReference(entry2)) { |
| IJavaProject referencedProject = EclipseClasspath.resolveProjectReference(entry2); |
| if (referencedProject == null) { |
| // project was not loaded in workspace |
| return false; |
| } else if (referencedProject.getProject().getName().equals(project.getProject().getName())) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Add variable/value for Eclipse variable. If given string is no variable, nothing is added. |
| * |
| * @param variable2valueMap |
| * property map to add variable/value |
| * @param s |
| * String which may contain Eclipse variables, e.g. ${project_name} |
| */ |
| public static void addVariable(Map<String, String> variable2valueMap, String s, String projectRoot) { |
| if (s == null || s.equals(IAntCoreConstants.EMPTY_STRING)) { |
| return; |
| } |
| Pattern pattern = Pattern.compile("\\$\\{.*?\\}"); // ${var} //$NON-NLS-1$ |
| Matcher matcher = pattern.matcher(s); |
| while (matcher.find()) { |
| String variable = matcher.group(); |
| String value; |
| try { |
| value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(variable); |
| } |
| catch (CoreException e) { |
| // cannot resolve variable |
| value = variable; |
| } |
| variable = removePrefixAndSuffix(variable, "${", "}"); //$NON-NLS-1$ //$NON-NLS-2$ |
| // if it is an environment variable, convert to Ant environment |
| // syntax |
| if (variable.startsWith("env_var:")) //$NON-NLS-1$ |
| { |
| value = "env." + variable.substring("env_var:".length()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| File file = new File(value); |
| if (file.exists()) { |
| value = getRelativePath(file.getAbsolutePath(), projectRoot); |
| } |
| variable2valueMap.put(variable, value); |
| } |
| } |
| |
| /** |
| * Returns a path which is equivalent to the given location relative to the specified base path. |
| */ |
| public static String getRelativePath(String otherLocation, String basePath) { |
| |
| IPath location = new Path(otherLocation); |
| IPath base = new Path(basePath); |
| if ((location.getDevice() != null && !location.getDevice().equalsIgnoreCase(base.getDevice())) || !location.isAbsolute()) { |
| return otherLocation; |
| } |
| int baseCount = base.segmentCount(); |
| int count = base.matchingFirstSegments(location); |
| String temp = IAntCoreConstants.EMPTY_STRING; |
| for (int j = 0; j < baseCount - count; j++) { |
| temp += "../"; //$NON-NLS-1$ |
| } |
| String relative = new Path(temp).append(location.removeFirstSegments(count)).toString(); |
| if (relative.length() == 0) { |
| relative = "."; //$NON-NLS-1$ |
| } |
| |
| return relative; |
| } |
| } |