/***************************************************************************** * 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.cvspkg.internal; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.regex.Pattern; import org.eclipse.buckminster.core.helpers.FileHandle; import org.eclipse.buckminster.core.reader.AbstractCatalogReader; import org.eclipse.buckminster.core.reader.IReaderType; import org.eclipse.buckminster.core.reader.IStreamConsumer; import org.eclipse.buckminster.core.version.ProviderMatch; import org.eclipse.buckminster.cvspkg.Messages; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.IOUtils; import org.eclipse.buckminster.runtime.MonitorUtils; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.osgi.util.NLS; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile; import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.resources.RemoteFolder; import org.eclipse.team.internal.ccvs.core.resources.UpdateContentCachingService; /** * @author Thomas Hallgren */ @SuppressWarnings("restriction") public class CVSReader extends AbstractCatalogReader { // We need to synchronize this on something static. // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=197301 // static synchronized Date getTagDate(CVSTag tag) { return tag.asDate(); } private final CVSTag fixed; private final CVSSession session; private RepositoryMetaData metaData; private RemoteFolder flatRoot; public CVSReader(IReaderType readerType, ProviderMatch rInfo) throws CoreException { super(readerType, rInfo); session = new CVSSession(rInfo.getRepositoryURI()); fixed = CVSReaderType.getCVSTag(rInfo.getVersionMatch()); } @Override public void close() { session.close(); } @Override public void innerMaterialize(IPath destination, IProgressMonitor monitor) throws CoreException { monitor.beginTask(null, 100); CVSRepositoryLocation cvsLocation = (CVSRepositoryLocation) session.getLocation(); // We avoid using the date if it is the last date known for // the repository. // CVSTag tag = null; if (fixed.getType() == CVSTag.DATE) { Date fixedDate = getTagDate(fixed); if (getMetaData(MonitorUtils.subMonitor(monitor, 20)).getLastModification().compareTo(fixedDate) > 0) tag = fixed; } else { tag = fixed; MonitorUtils.worked(monitor, 20); } MonitorUtils.testCancelStatus(monitor); ICVSFolder root = new RemoteFolder(null, cvsLocation, session.getModuleName(), tag); try { ICVSFolder folder = UpdateContentCachingService.buildRemoteTree(cvsLocation, root, tag, IResource.DEPTH_INFINITE, MonitorUtils .subMonitor(monitor, 90)); if (folder == null) throw new FileNotFoundException(toString()); FileSystemCopier copier = new FileSystemCopier(folder, destination, MonitorUtils.subMonitor(monitor, 80)); try { folder.accept(copier, true); } finally { copier.done(); monitor.done(); } } catch (IOException e) { throw BuckminsterException.wrap(e); } } @Override public String toString() { return session.getRepository() + ',' + fixed.getName(); } @Override protected boolean innerExists(String fileName, IProgressMonitor monitor) throws CoreException { InputStream input = null; try { getCVSRemoteFile(fileName, monitor); return true; } catch (FileNotFoundException e) { return false; } finally { IOUtils.close(input); } } @Override protected FileHandle innerGetContents(String fileName, IProgressMonitor monitor) throws CoreException, IOException { // Build the local options // monitor.beginTask(null, 1000); monitor.subTask(NLS.bind(Messages.retrieving_0, fileName)); InputStream in = null; OutputStream out = null; File tempFile = null; try { ICVSRemoteFile cvsFile = getCVSRemoteFile(fileName, MonitorUtils.subMonitor(monitor, 500)); in = cvsFile.getContents(MonitorUtils.subMonitor(monitor, 250)); tempFile = createTempFile(); out = new BufferedOutputStream(new FileOutputStream(tempFile)); IOUtils.copy(in, out, MonitorUtils.subMonitor(monitor, 250)); FileHandle fh = new FileHandle(fileName, tempFile, true); tempFile = null; return fh; } finally { IOUtils.close(out); IOUtils.close(in); if (tempFile != null) tempFile.delete(); monitor.done(); } } @Override protected void innerGetMatchingRootFiles(Pattern pattern, List<FileHandle> files, IProgressMonitor monitor) throws CoreException, IOException { monitor.beginTask(null, 1000 + (flatRoot == null ? 500 : 0)); try { if (flatRoot == null) getFlatRoot(MonitorUtils.subMonitor(monitor, 500)); ArrayList<String> matching = null; for (ICVSRemoteResource child : flatRoot.getChildren()) { String name = child.getName(); if (pattern.matcher(name).matches()) { if (matching == null) matching = new ArrayList<String>(); matching.add(name); } } if (matching == null) return; int ticksPerMatch = 1000 / matching.size(); for (String name : matching) files.add(innerGetContents(name, MonitorUtils.subMonitor(monitor, ticksPerMatch))); } finally { monitor.done(); } } @Override protected void innerList(List<String> files, IProgressMonitor monitor) throws CoreException { monitor.beginTask(null, 1000 + (flatRoot == null ? 500 : 0)); try { if (flatRoot == null) getFlatRoot(MonitorUtils.subMonitor(monitor, 500)); for (ICVSRemoteResource child : flatRoot.getChildren()) { String name = child.getName(); if (child.isFolder() && !name.endsWith("/")) //$NON-NLS-1$ name = name + "/"; //$NON-NLS-1$ files.add(child.getName()); } } finally { monitor.done(); } } @Override protected <T> T innerReadFile(String fileName, IStreamConsumer<T> consumer, IProgressMonitor monitor) throws CoreException, IOException { // Build the local options // monitor.beginTask(null, 1000); monitor.subTask(NLS.bind(Messages.retrieving_0, fileName)); InputStream in = null; try { ICVSRemoteFile cvsFile = getCVSRemoteFile(fileName, MonitorUtils.subMonitor(monitor, 500)); in = cvsFile.getContents(MonitorUtils.subMonitor(monitor, 250)); return consumer.consumeStream(this, fileName, in, MonitorUtils.subMonitor(monitor, 250)); } finally { IOUtils.close(in); monitor.done(); } } private ICVSRemoteFile getCVSRemoteFile(String fileName, IProgressMonitor monitor) throws CoreException, FileNotFoundException { IPath filePath = Path.fromPortableString(fileName); RemoteFolder folder = flatRoot; if (filePath.segmentCount() > 1) { IPath parentPath = Path.fromPortableString(session.getModuleName()).append(filePath.removeLastSegments(1)); CVSRepositoryLocation cvsLocation = (CVSRepositoryLocation) session.getLocation(); folder = new RemoteFolder(null, cvsLocation, parentPath.toPortableString(), fixed); folder = UpdateContentCachingService.buildRemoteTree(cvsLocation, folder, fixed, IResource.DEPTH_ONE, monitor); } else { if (flatRoot == null) getFlatRoot(monitor); else MonitorUtils.complete(monitor); folder = flatRoot; } if (folder == null) throw new FileNotFoundException(toString()); ICVSResource cvsFile; try { cvsFile = folder.getChild(filePath.lastSegment()); } catch (CVSException e) { throw new FileNotFoundException(e.getMessage()); } if (!(cvsFile instanceof ICVSRemoteFile)) throw new FileNotFoundException(NLS.bind(Messages.file_0_appears_to_be_folder, fileName)); return (ICVSRemoteFile) cvsFile; } private void getFlatRoot(IProgressMonitor monitor) throws CoreException { if (flatRoot == null) { CVSRepositoryLocation cvsLocation = (CVSRepositoryLocation) session.getLocation(); RemoteFolder root = new RemoteFolder(null, cvsLocation, session.getModuleName(), fixed); flatRoot = UpdateContentCachingService.buildRemoteTree(cvsLocation, root, fixed, IResource.DEPTH_ONE, monitor); } else MonitorUtils.complete(monitor); } private synchronized RepositoryMetaData getMetaData(IProgressMonitor monitor) throws CoreException { if (metaData == null) { CVSTag tag = (fixed.getType() == CVSTag.DATE) ? null : fixed; metaData = RepositoryMetaData.getMetaData(session, tag, monitor); } else MonitorUtils.complete(monitor); return metaData; } }