/******************************************************************************* * Copyright (c) 2004, 2006 * Thomas Hallgren, Kenneth Olwing, Mitch Sonies * Pontus Rydin, Nils Unden, Peer Torngren * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the individual * copyright holders listed above, as Initial Contributors under such license. * The text of such license is available at www.eclipse.org. *******************************************************************************/ package org.eclipse.buckminster.core.reader; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.eclipse.buckminster.core.CorePlugin; import org.eclipse.buckminster.core.Messages; import org.eclipse.buckminster.core.helpers.FileHandle; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.materializer.MaterializationContext; import org.eclipse.buckminster.core.metadata.model.Resolution; import org.eclipse.buckminster.core.mspec.ConflictResolution; import org.eclipse.buckminster.core.version.ProviderMatch; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.IOUtils; import org.eclipse.buckminster.runtime.Logger; import org.eclipse.buckminster.runtime.MonitorUtils; import org.eclipse.buckminster.runtime.URLUtils; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.preferences.IEclipsePreferences; /** * @author Thomas Hallgren */ public abstract class AbstractCatalogReader extends AbstractReader implements ICatalogReader { private boolean prefStateKnown = false; private IEclipsePreferences preferences; protected AbstractCatalogReader(IReaderType readerType, ProviderMatch providerMatch) { super(readerType, providerMatch); } @Override public final boolean exists(String fileName, IProgressMonitor monitor) throws CoreException { monitor.beginTask(null, 100); try { File addOnFolder = getOverlayFolder(MonitorUtils.subMonitor(monitor, 10)); if (addOnFolder != null && new File(addOnFolder, fileName).exists()) { MonitorUtils.worked(monitor, 90); return true; } return innerExists(fileName, MonitorUtils.subMonitor(monitor, 90)); } finally { monitor.done(); } } @Override public final FileHandle getContents(String fileName, IProgressMonitor monitor) throws CoreException, IOException { ProviderMatch ri = getProviderMatch(); Logger logger = CorePlugin.getLogger(); monitor.beginTask(null, 100); try { File addOnFolder = getOverlayFolder(MonitorUtils.subMonitor(monitor, 10)); if (addOnFolder != null) { File addOnFile = new File(addOnFolder, fileName); if (addOnFile.exists()) { logger.debug( "Provider %s(%s): getContents will use overlay %s for file = %s", getReaderType().getId(), ri.getRepositoryURI(), addOnFile, fileName); //$NON-NLS-1$ MonitorUtils.worked(monitor, 90); return new FileHandle(fileName, addOnFile, false); } } return innerGetContents(fileName, MonitorUtils.subMonitor(monitor, 90)); } finally { monitor.done(); } } @Override public final List<FileHandle> getRootFiles(Pattern matchPattern, IProgressMonitor monitor) throws CoreException, IOException { ArrayList<FileHandle> files = new ArrayList<FileHandle>(); monitor.beginTask(null, 100); File addOnFolder = getOverlayFolder(MonitorUtils.subMonitor(monitor, 10)); if (addOnFolder != null) { String[] names = addOnFolder.list(); if (names != null) { for (String name : names) { if (matchPattern.matcher(name).matches()) files.add(new FileHandle(name, new File(addOnFolder, name), false)); } } } innerGetMatchingRootFiles(matchPattern, files, MonitorUtils.subMonitor(monitor, 90)); return files; } @Override public final List<String> list(IProgressMonitor monitor) throws CoreException { ArrayList<String> files = new ArrayList<String>(); innerList(files, monitor); return files; } @Override public final void materialize(IPath location, Resolution resolution, MaterializationContext ctx, IProgressMonitor monitor) throws CoreException { ProviderMatch pm = this.getProviderMatch(); CorePlugin.getLogger().debug("Provider %s(%s): materializing to %s", getReaderType().getId(), pm.getRepositoryURI(), location); //$NON-NLS-1$ monitor.beginTask(null, 100); try { innerMaterialize(location, MonitorUtils.subMonitor(monitor, 80)); copyOverlay(location, MonitorUtils.subMonitor(monitor, 10)); } finally { monitor.done(); } } @Override public synchronized IEclipsePreferences readBuckminsterPreferences(IProgressMonitor monitor) throws CoreException { if (prefStateKnown) { MonitorUtils.complete(monitor); return preferences; } try { preferences = readFile(EclipsePreferencesReader.BUCKMINSTER_PROJECT_PREFS_PATH, EclipsePreferencesReader.INSTANCE, monitor); return preferences; } catch (FileNotFoundException e) { return null; } catch (IOException e) { throw BuckminsterException.wrap(e); } finally { prefStateKnown = true; } } @Override public final <T> T readFile(String fileName, IStreamConsumer<T> consumer, IProgressMonitor monitor) throws CoreException, IOException { MonitorUtils.begin(monitor, 100); try { File addOnFolder = getOverlayFolder(MonitorUtils.subMonitor(monitor, 10)); if (addOnFolder == null) return innerReadFile(fileName, consumer, MonitorUtils.subMonitor(monitor, 90)); InputStream tmp = null; IProgressMonitor overlayReadMon = MonitorUtils.subMonitor(monitor, 10); try { File file = new File(addOnFolder, fileName); tmp = new BufferedInputStream(new FileInputStream(file)); return consumer.consumeStream(this, file.getAbsolutePath(), tmp, overlayReadMon); } catch (FileNotFoundException e) { // This is OK, just continue with the innerReadFile MonitorUtils.complete(overlayReadMon); } finally { IOUtils.close(tmp); } return innerReadFile(fileName, consumer, MonitorUtils.subMonitor(monitor, 80)); } finally { MonitorUtils.done(monitor); } } @Override protected void copyOverlay(IPath destination, IProgressMonitor monitor) throws CoreException { monitor.beginTask(null, 100); try { File addOnFolder = getOverlayFolder(MonitorUtils.subMonitor(monitor, 50)); if (addOnFolder != null) { // Copy the addOnFolder. Overwrite is always OK for addOnFolders // File destDir = destination.toFile(); destDir.mkdirs(); FileUtils.deepCopyUnchecked(addOnFolder, destDir, MonitorUtils.subMonitor(monitor, 50)); } else MonitorUtils.worked(monitor, 50); } finally { monitor.done(); } } protected File getOverlayFolder(IProgressMonitor monitor) throws CoreException { URL overlay = getNodeQuery().getOverlayFolder(); if (overlay == null) { MonitorUtils.complete(monitor); return null; } File fileOverlay; try { fileOverlay = FileUtils.getFile(FileLocator.toFileURL(overlay)); if (fileOverlay == null) return obtainRemoteOverlayFolder(overlay, monitor); if (!fileOverlay.isAbsolute()) { // Relative overlays are relative to the workspace root so that // they // can reside in other projects residing in the workspace from // which // prototyping takes place. // IPath wsRoot = ResourcesPlugin.getWorkspace().getRoot().getLocation(); fileOverlay = wsRoot.append(new Path(fileOverlay.toString())).toFile(); } String fos = fileOverlay.toString(); if (fos.endsWith(".zip") || fos.endsWith(".jar")) //$NON-NLS-1$ //$NON-NLS-2$ { File dest = FileUtils.createTempFolder("bmovl", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$ FileUtils.unzip(URLUtils.normalizeToURL(fos), getConnectContext(), null, dest, ConflictResolution.REPLACE, monitor); return dest; } if (!fileOverlay.isDirectory()) throw new IllegalOverlayException(Messages.Only_folders_zip_and_jar_archives_allowed); // Monitor was not used for anything so make it complete // MonitorUtils.complete(monitor); return fileOverlay; } catch (IOException e) { throw BuckminsterException.wrap(e); } } protected abstract boolean innerExists(String fileName, IProgressMonitor monitor) throws CoreException; protected FileHandle innerGetContents(String fileName, IProgressMonitor monitor) throws CoreException, IOException { OutputStream tmp = null; File tempFile = null; try { tempFile = createTempFile(); tmp = new FileOutputStream(tempFile); final OutputStream out = tmp; readFile(fileName, new IStreamConsumer<Object>() { @Override public Object consumeStream(IComponentReader reader, String streamName, InputStream stream, IProgressMonitor mon) throws IOException { FileUtils.copyFile(stream, out, mon); return null; } }, monitor); FileHandle fh = new FileHandle(fileName, tempFile, true); tempFile = null; return fh; } catch (FileNotFoundException e) { throw BuckminsterException.wrap(e); } finally { IOUtils.close(tmp); if (tempFile != null) tempFile.delete(); } } protected void innerGetMatchingRootFiles(Pattern pattern, List<FileHandle> files, IProgressMonitor monitor) throws CoreException, IOException { if (!isFileSystemReader()) return; File source = getLocation(); String[] rootFiles = source.list(); if (rootFiles == null) return; for (String rootFile : rootFiles) { if (pattern.matcher(rootFile).matches()) { File f = new File(source, rootFile); if (f.isFile() && f.canRead()) files.add(new FileHandle(rootFile, f, false)); } } } protected void innerList(List<String> files, IProgressMonitor monitor) throws CoreException { if (!isFileSystemReader()) return; File source = getLocation(); File[] rootFiles = source.listFiles(); if (rootFiles == null) return; for (File rootFile : rootFiles) { String name = rootFile.getName(); if (rootFile.isDirectory()) name += "/"; //$NON-NLS-1$ files.add(name); } } protected abstract <T> T innerReadFile(String fileName, IStreamConsumer<T> consumer, IProgressMonitor monitor) throws CoreException, IOException; private File obtainRemoteOverlayFolder(URL url, IProgressMonitor monitor) throws CoreException { String path = url.getPath(); if (!(path.endsWith(".zip") || path.endsWith(".jar"))) //$NON-NLS-1$ //$NON-NLS-2$ throw new IllegalOverlayException(Messages.Only_zip_and_jar_archives_allowed_for_remote_overlays); File dest = FileUtils.createTempFolder("bmovl", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$ FileUtils.unzip(url, getConnectContext(), null, dest, ConflictResolution.REPLACE, monitor); return dest; } }