/***************************************************************************** * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. *****************************************************************************/ package org.eclipse.buckminster.core.cspec; import java.io.File; import java.util.Map; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.mspec.ConflictResolution; import org.eclipse.buckminster.runtime.MonitorUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; /** * @author Thomas Hallgren */ public class PathGroup { public static final PathGroup[] EMPTY_ARRAY = new PathGroup[0]; private final IPath base; private final IPath[] paths; public PathGroup(IPath base, IPath[] paths) { if (base == null) throw new IllegalArgumentException(Messages.Base_cannot_be_null); this.base = base; this.paths = paths; } public void appendRelativeFiles(Map<String, Long> fileNames) { int idx = paths.length; if (idx == 0) { // We don't have any paths. Use everything below base // FileUtils.appendRelativeFiles(base.toFile(), fileNames); return; } File baseDir = base.toFile(); while (--idx >= 0) FileUtils.appendRelativeFiles(baseDir, paths[idx].toFile(), fileNames); } public boolean containsPath(IPath path) { if (path == null) return false; // We consider the completely empty path to be a prefix of // all other paths. // boolean isCompletelyEmpty = (base.isEmpty() && base.getDevice() == null); boolean isPrefix = isCompletelyEmpty || base.isPrefixOf(path); if (!isPrefix) return false; IPath relPath = path; if (!isCompletelyEmpty) relPath = path.removeFirstSegments(base.segmentCount()).setDevice(null); // Check for exact matches or for directories that are parents to // the given path. // for (IPath rel : paths) { IPath cmpPath = rel.isAbsolute() ? path : relPath; if (rel.equals(cmpPath) || rel.hasTrailingSeparator() && rel.isPrefixOf(cmpPath)) return true; } return false; } public void copyPathTo(IPath path, IPath destination, IProgressMonitor monitor) throws CoreException { File destDir = destination.toFile().getAbsoluteFile(); File basedDestDir = null; if (!path.hasTrailingSeparator()) { // Path denotes a file // String fileName = path.lastSegment(); if (path.isAbsolute() || path.segmentCount() == 1) { basedDestDir = destDir; if (!path.isAbsolute()) path = base.append(path); } else basedDestDir = destination.append(path.removeLastSegments(1)).toFile(); File sourceFile = path.toFile(); if (sourceFile.exists()) { MonitorUtils.begin(monitor, 100); FileUtils.prepareDestination(basedDestDir, ConflictResolution.UPDATE, MonitorUtils.subMonitor(monitor, 20)); FileUtils.copyFile(sourceFile, basedDestDir, fileName, MonitorUtils.subMonitor(monitor, 80)); MonitorUtils.done(monitor); } else { MonitorUtils.complete(monitor); } } else { if (path.isAbsolute()) basedDestDir = destDir; else { basedDestDir = destination.append(path).toFile(); path = base.append(path); } File sourceDir = path.toFile(); if (sourceDir.exists()) FileUtils.deepCopy(sourceDir, basedDestDir, ConflictResolution.UPDATE, monitor); else MonitorUtils.complete(monitor); } } public void copyTo(IPath destination, IProgressMonitor monitor) throws CoreException { if (!destination.isAbsolute()) throw new IllegalArgumentException(Messages.Destination_must_be_absolute); if (!base.isAbsolute()) throw new IllegalArgumentException(Messages.Source_must_be_absolute); int idx = paths.length; if (idx == 0) { // We don't have any paths. Use everything below base // File baseDir = base.toFile().getAbsoluteFile(); if (baseDir.isDirectory()) FileUtils.deepCopy(baseDir, destination.toFile().getAbsoluteFile(), ConflictResolution.UPDATE, monitor); else MonitorUtils.complete(monitor); return; } monitor.beginTask(null, idx * 100); while (--idx >= 0) copyPathTo(paths[idx], destination, MonitorUtils.subMonitor(monitor, 100)); monitor.done(); } public final IPath getBase() { return base; } public long getFirstModified(int expectedCount, int[] fileCount) { int idx = paths.length; if (idx == 0) // // We don't have any paths. Use everything below base // return FileUtils.getFirstModified(base.toFile(), expectedCount, fileCount); if (idx > 1 && expectedCount > 0) expectedCount = -1; long firstMod = Long.MAX_VALUE; while (--idx >= 0) { IPath absPath = paths[idx]; if (!absPath.isAbsolute()) absPath = base.append(absPath); long modTime = FileUtils.getFirstModified(absPath.toFile(), expectedCount, fileCount); if (modTime < firstMod) { firstMod = modTime; if (modTime == 0) break; } } return firstMod; } public long getLastModified(long threshold, int[] fileCount) { int idx = paths.length; if (idx == 0) // // We don't have any paths. Use everything below base // return FileUtils.getLastModified(base.toFile(), threshold, fileCount); long lastMod = 0; int count = 0; int[] countBin = new int[1]; while (--idx >= 0) { IPath absPath = paths[idx]; if (!absPath.isAbsolute()) absPath = base.append(absPath); countBin[0] = 0; long modTime = FileUtils.getLastModified(absPath.toFile(), threshold, countBin); count += countBin[0]; if (modTime > lastMod) { lastMod = modTime; if (modTime > threshold) break; } } fileCount[0] = count; return lastMod; } public final IPath[] getPaths() { return paths; } @Override public String toString() { StringBuilder bld = new StringBuilder(); bld.append(base.toPortableString()); bld.append('{'); int top = paths.length; if (top > 0) { bld.append(paths[0]); for (int idx = 1; idx < top; ++idx) { bld.append(','); bld.append(paths[idx]); } } bld.append('}'); return bld.toString(); } }