### Eclipse Workspace Patch 1.0
#P org.eclipse.core.resources
Index: src/org/eclipse/core/internal/resources/LocalMetaArea.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/LocalMetaArea.java,v
retrieving revision 1.41
diff -u -r1.41 LocalMetaArea.java
--- src/org/eclipse/core/internal/resources/LocalMetaArea.java 3 Jun 2008 12:34:50 -0000 1.41
+++ src/org/eclipse/core/internal/resources/LocalMetaArea.java 4 Mar 2010 05:37:13 -0000
@@ -31,6 +31,7 @@
/* package */static final String F_PROJECT_LOCATION = ".location"; //$NON-NLS-1$
/* package */static final String F_PROJECTS = ".projects"; //$NON-NLS-1$
/* package */static final String F_PROPERTIES = ".properties"; //$NON-NLS-1$
+ /* package */static final String F_REFRESH = ".refresh"; //$NON-NLS-1$
/* package */static final String F_ROOT = ".root"; //$NON-NLS-1$
/* package */static final String F_SAFE_TABLE = ".safetable"; //$NON-NLS-1$
/* package */static final String F_SNAP = ".snap"; //$NON-NLS-1$
@@ -62,6 +63,13 @@
Workspace.clear(getOldDescriptionLocationFor(target).toFile());
}
+ /**
+ * Delete the refresh snapshot once it has been used to open a new project.
+ */
+ public void clearRefresh(IProject target) {
+ Workspace.clear(getRefreshLocationFor(target).toFile());
+ }
+
public void create(IProject target) {
java.io.File file = locationFor(target).toFile();
//make sure area is empty
@@ -147,6 +155,15 @@
return locationFor(resource).append(F_PROPERTIES);
}
+ /**
+ * Returns the path of the file in which to save the refresh snapshot for
+ * the given project.
+ */
+ public IPath getRefreshLocationFor(IProject project) {
+ Assert.isNotNull(project);
+ return locationFor(project).append(F_REFRESH);
+ }
+
public IPath getSafeTableLocationFor(String pluginId) {
IPath prefix = metaAreaLocation.append(F_SAFE_TABLE);
// if the plugin is the resources plugin, we return the master table
Index: src/org/eclipse/core/internal/resources/Project.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java,v
retrieving revision 1.165
diff -u -r1.165 Project.java
--- src/org/eclipse/core/internal/resources/Project.java 25 Jan 2010 14:08:43 -0000 1.165
+++ src/org/eclipse/core/internal/resources/Project.java 4 Mar 2010 05:37:14 -0000
@@ -9,9 +9,12 @@
* IBM Corporation - initial API and implementation
* Serge Beauchamp (Freescale Semiconductor) - [229633] Project Path Variable Support
* Anton Leherbauer (Wind River) - [198591] Allow Builder to specify scheduling rule
+ * Francis Lynch (Wind River) - [301563] Save and load refresh information snapshots
*******************************************************************************/
package org.eclipse.core.internal.resources;
+import org.eclipse.core.runtime.IPath;
+
import java.net.URI;
import java.util.*;
import org.eclipse.core.filesystem.*;
@@ -820,6 +823,25 @@
}
/* (non-Javadoc)
+ * @see IProject#loadSnapshot(int, URI, IProgressMonitor)
+ */
+ public void loadSnapshot(int options, URI snapshotLocation,
+ IProgressMonitor monitor) throws CoreException {
+ if ((options & SNAPSHOT_TREE) != 0) {
+ // load a snapshot of refresh information when project is opened
+ if (isOpen()) {
+ String message = Messages.resources_projectMustNotBeOpen;
+ MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
+ throw new CoreException(status);
+ }
+ // copy the snapshot from the URI into the project metadata
+ IPath snapshotPath = workspace.getMetaArea().getRefreshLocationFor(this);
+ IFileStore snapshotFileStore = EFS.getStore(org.eclipse.core.filesystem.URIUtil.toURI(snapshotPath));
+ snapshotFileStore.delete(EFS.NONE, monitor);
+ EFS.getStore(snapshotLocation).copy(snapshotFileStore, options, monitor);
+ }
+ }
+ /* (non-Javadoc)
* @see IProject#move(IProjectDescription, boolean, IProgressMonitor)
*/
public void move(IProjectDescription destination, boolean force, IProgressMonitor monitor) throws CoreException {
@@ -921,14 +943,24 @@
}
startup();
//request a refresh if the project is new and has unknown members on disk
- // or restore of the project is not fully succesfull
+ // or restore of the project is not fully successful
if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
+ boolean refreshed = false;
+ if (!used) {
+ refreshed = workspace.getSaveManager().restoreFromRefreshSnapshot(
+ this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
+ if (refreshed) { // account for the refresh work
+ monitor.worked(Policy.opWork * 60 / 100);
+ }
+ }
//refresh either in background or foreground
- if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
- workspace.refreshManager.refresh(this);
- monitor.worked(Policy.opWork * 80 / 100);
- } else {
- refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 80 / 100));
+ if (!refreshed) {
+ if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
+ workspace.refreshManager.refresh(this);
+ monitor.worked(Policy.opWork * 60 / 100);
+ } else {
+ refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100));
+ }
}
}
//creation of this project may affect overlapping resources
@@ -1036,6 +1068,31 @@
}
/* (non-Javadoc)
+ * @see IProject#saveSnapshot(int, URI, IProgressMonitor)
+ */
+ public void saveSnapshot(int options, URI snapshotLocation,
+ IProgressMonitor monitor) throws CoreException {
+ if ((options & SNAPSHOT_TREE) != 0) {
+ // write a snapshot of refresh information
+ monitor = Policy.monitorFor(monitor);
+ try {
+ String msg = NLS.bind(Messages.resources_copying, getName());
+ monitor.beginTask(msg, Policy.totalWork);
+ try {
+ IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
+ workspace.getSaveManager().saveRefreshSnapshot(
+ this, snapshotLocation, sub);
+ monitor.worked(Policy.opWork / 2);
+ } catch (OperationCanceledException e) {
+ workspace.getWorkManager().operationCanceled();
+ throw e;
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ }
+ /* (non-Javadoc)
* @see IProject#setDescription(IProjectDescription, int, IProgressMonitor)
*/
public void setDescription(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
Index: src/org/eclipse/core/internal/resources/SaveManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java,v
retrieving revision 1.102
diff -u -r1.102 SaveManager.java
--- src/org/eclipse/core/internal/resources/SaveManager.java 2 Nov 2009 10:12:59 -0000 1.102
+++ src/org/eclipse/core/internal/resources/SaveManager.java 4 Mar 2010 05:37:16 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,11 +7,19 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Francis Lynch (Wind River) - add support for snapshot of project tree
*******************************************************************************/
package org.eclipse.core.internal.resources;
+import org.eclipse.core.filesystem.IFileStore;
+
+import org.eclipse.core.filesystem.EFS;
+
+import java.net.URI;
+
import java.io.*;
import java.util.*;
+import java.util.zip.*;
import org.eclipse.core.internal.events.*;
import org.eclipse.core.internal.localstore.*;
import org.eclipse.core.internal.utils.*;
@@ -708,6 +716,43 @@
}
/**
+ * Restores the contents of this project from a refresh snapshot, if possible.
+ * Throws an exception if the snapshot is found but an error occurs when reading
+ * the file.
+ * @return
@@ -621,13 +656,19 @@
* of its resources from information stored on disk.
*
- * The true
if the project data was restored successfully,
+ * and false
if the refresh snapshot was not found or could not be opened.
+ * @exception CoreException if an error occurred reading the snapshot file.
+ */
+ protected boolean restoreFromRefreshSnapshot(Project project,
+ IProgressMonitor monitor) throws CoreException {
+ boolean status = true;
+ IPath snapshotPath = workspace.getMetaArea().getRefreshLocationFor(project);
+ java.io.File snapshotFile = snapshotPath.toFile();
+ if (!snapshotFile.exists())
+ return false;
+ if (Policy.DEBUG_RESTORE)
+ System.out.println("Restore project " + project.getFullPath() + ": starting..."); //$NON-NLS-1$ //$NON-NLS-2$
+ long start = System.currentTimeMillis();
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask("", 40); //$NON-NLS-1$
+ status = restoreTreeFromRefreshSnapshot(project,
+ snapshotFile, Policy.subMonitorFor(monitor, 40));
+ if (status) {
+ // load the project description and set internal description
+ ProjectDescription description = workspace.getFileSystemManager().read(project, true);
+ project.internalSetDescription(description, false);
+ workspace.getMetaArea().clearRefresh(project);
+ }
+ } finally {
+ monitor.done();
+ }
+ if (Policy.DEBUG_RESTORE)
+ System.out.println("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return status;
+ }
+
+ /**
* Reads the markers which were originally saved
* for the tree rooted by the given resource.
*/
@@ -970,6 +1015,47 @@
return true;
}
+ /**
+ * Restores a tree saved as a refresh snapshot to a specified URI.
+ * @return true
if the snapshot exists, false
otherwise.
+ * @exception CoreException if the project could not be restored.
+ */
+ protected boolean restoreTreeFromRefreshSnapshot(Project project,
+ java.io.File snapshotFile, IProgressMonitor monitor) throws CoreException {
+ long start = System.currentTimeMillis();
+ monitor = Policy.monitorFor(monitor);
+ String message;
+ IPath snapshotPath = null;
+ try {
+ monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
+ InputStream snapIn = new FileInputStream(snapshotFile);
+ ZipInputStream zip = new ZipInputStream(snapIn);
+ ZipEntry treeEntry = zip.getNextEntry();
+ if (treeEntry == null || !treeEntry.getName().equals("resource-index.tree")) { //$NON-NLS-1$
+ zip.close();
+ return false;
+ }
+ DataInputStream input = new DataInputStream(zip);
+ try {
+ WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt());
+ reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork));
+ } finally {
+ input.close();
+ zip.close();
+ }
+ } catch (IOException e) {
+ snapshotPath = new Path(snapshotFile.getPath());
+ message = NLS.bind(Messages.resources_readMeta, snapshotPath);
+ throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, snapshotPath, message, e);
+ } finally {
+ monitor.done();
+ }
+ if (Policy.DEBUG_RESTORE_TREE) {
+ System.out.println("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ return true;
+ }
+
class InternalMonitorWrapper extends ProgressMonitorWrapper{
private boolean ignoreCancel;
@@ -1162,6 +1248,58 @@
}
/**
+ * Writes a snapshot of project refresh information to the specified
+ * location.
+ * @param project the project to write a refresh snapshot for
+ * @param monitor progress monitor
+ * @exception CoreException if there is a problem writing the snapshot.
+ */
+ public void saveRefreshSnapshot(Project project, URI snapshotLocation,
+ IProgressMonitor monitor) throws CoreException {
+ IFileStore store = EFS.getStore(snapshotLocation);
+ IPath snapshotPath = new Path(snapshotLocation.getPath());
+ OutputStream snapOut = store.openOutputStream(EFS.NONE, monitor);
+ java.io.File tmpTree = null;
+ try {
+ tmpTree = java.io.File.createTempFile("tmp", ".tree"); //$NON-NLS-1$//$NON-NLS-2$
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL,
+ snapshotPath, Messages.resources_copyProblem, e);
+ }
+ ZipOutputStream out = null;
+ try {
+ FileOutputStream fis = new FileOutputStream(tmpTree);
+ DataOutputStream output = new DataOutputStream(fis);
+ try {
+ output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
+ writeTree(project, output, monitor);
+ } finally {
+ output.close();
+ }
+ out = new ZipOutputStream(snapOut);
+ out.setLevel(Deflater.BEST_COMPRESSION);
+ ZipEntry e = new ZipEntry("resource-index.tree"); //$NON-NLS-1$
+ out.putNextEntry(e);
+ int read = 0;
+ byte[] buffer = new byte[4096];
+ InputStream in = new FileInputStream(tmpTree);
+ try {
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ }
+ out.closeEntry();
+ } finally {
+ in.close();
+ }
+ out.close();
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotPath, Messages.resources_copyProblem, e);
+ } finally {
+ tmpTree.delete();
+ }
+ }
+
+ /**
* Writes the current state of the entire workspace tree to disk.
* This is used during workspace save. saveTree(Project)
* is used to save the state of an individual project.
Index: src/org/eclipse/core/internal/utils/Messages.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/Messages.java,v
retrieving revision 1.41
diff -u -r1.41 Messages.java
--- src/org/eclipse/core/internal/utils/Messages.java 25 Jan 2010 14:08:44 -0000 1.41
+++ src/org/eclipse/core/internal/utils/Messages.java 4 Mar 2010 05:37:17 -0000
@@ -247,6 +247,7 @@
public static String resources_pathNull;
public static String resources_projectDesc;
public static String resources_projectDescSync;
+ public static String resources_projectMustNotBeOpen;
public static String resources_projectPath;
public static String resources_pruningHistory;
public static String resources_reading;
Index: src/org/eclipse/core/internal/utils/messages.properties
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/messages.properties,v
retrieving revision 1.139
diff -u -r1.139 messages.properties
--- src/org/eclipse/core/internal/utils/messages.properties 25 Jan 2010 14:08:44 -0000 1.139
+++ src/org/eclipse/core/internal/utils/messages.properties 4 Mar 2010 05:37:18 -0000
@@ -9,6 +9,7 @@
# IBM Corporation - initial API and implementation
# Serge Beauchamp (Freescale Semiconductor) - [252996] add resource filtering
# Serge Beauchamp (Freescale Semiconductor) - [229633] Group and Project Path Variable Support
+# Francis Lynch (Wind River) - [301563] project refresh snapshots
###############################################################################
### Resources plugin messages.
@@ -243,6 +244,7 @@
resources_pathNull = Paths must not be null.
resources_projectDesc = Problems encountered while setting project description.
resources_projectDescSync = Could not set the project description for ''{0}'' because the project description file (.project) is out of sync with the file system.
+resources_projectMustNotBeOpen = Project must not be open.
resources_projectPath = Path for project must have only one segment.
resources_pruningHistory = Pruning history.
resources_reading = Reading.
Index: src/org/eclipse/core/resources/IProject.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IProject.java,v
retrieving revision 1.47
diff -u -r1.47 IProject.java
--- src/org/eclipse/core/resources/IProject.java 25 Jan 2010 14:08:44 -0000 1.47
+++ src/org/eclipse/core/resources/IProject.java 4 Mar 2010 05:37:19 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,9 +7,12 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Francis Lynch (Wind River) - added loadSnapshot/saveSnapshot
*******************************************************************************/
package org.eclipse.core.resources;
+import java.net.URI;
+
import java.util.Map;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeMatcher;
@@ -42,6 +45,15 @@
*/
public interface IProject extends IContainer, IAdaptable {
/**
+ * Option constant (value 1) indicating that the snapshot to be
+ * loaded or saved contains refresh information.
+ * @see #loadSnapshot(int, URI, IProgressMonitor)
+ * @see #saveSnapshot(int, URI, IProgressMonitor)
+ * @since 3.6
+ */
+ public static final int SNAPSHOT_TREE = 1;
+
+ /**
* Invokes the build
method of the specified builder
* for this project. Does nothing if this project is closed. If this project
* has multiple builders on its build spec matching the given name, only
@@ -569,6 +581,29 @@
public boolean isOpen();
/**
+ * Loads a snapshot of project meta-data from the given location URI.
+ * Must be called after the project has been created, but before it is
+ * opened. The options constant controls what kind of snapshot information
+ * to load. Valid option values include:
+ *
+ *
+ * @param options kind of snapshot information to load
+ * @param snapshotLocation URI for the snapshot information
+ * @param monitor a progress monitor, or null
if progress
+ * reporting is not desired
+ * @exception CoreException if this method fails. Reasons include:
+ *
+ *
+ * @exception OperationCanceledException if the operation is canceled.
+ * @see #saveSnapshot(int, URI, IProgressMonitor)
+ * @since 3.6
+ */
+ public void loadSnapshot(int options, URI snapshotLocation,
+ IProgressMonitor monitor) throws CoreException;
+
+ /**
* Renames this project so that it is located at the name in
* the given description.
* BACKGROUND_REFRESH
update flag controls how
- * this method behaves when a project is opened for the first time on a location
- * that has existing resources on disk. If this flag is specified, resources on disk
- * will be added to the project in the background after this method returns.
- * Child resources of the project may not be available until this background
- * refresh completes. If this flag is not specified, resources on disk are added
- * to the project in the foreground before this method returns.
+ * When a project is opened for the first time, initial information about the
+ * project's existing resources can be obtained in the following ways:
+ *
+ *
*
null
if progress
+ * reporting is not desired
+ * @exception CoreException if this method fails. Reasons include:
+ * @@ -852,4 +915,5 @@ * @since 3.6 */ public IPathVariableManager getPathVariableManager(); + }