Work in progress on bug 21029
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildCommand.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildCommand.java index 99b83ef..24559fc 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildCommand.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildCommand.java
@@ -17,10 +17,17 @@ import org.eclipse.core.resources.ICommand; public class BuildCommand extends ModelObject implements ICommand { protected HashMap arguments; + /** Cached hash code for performance */ + protected int hash = -1; + public BuildCommand() { super(""); //$NON-NLS-1$ this.arguments = new HashMap(0); } +public BuildCommand(String builderName, Map args) { + super(builderName); + this.arguments = args == null ? new HashMap(0) : new HashMap(args); +} public Object clone() { BuildCommand result = null; result = (BuildCommand) super.clone(); @@ -34,10 +41,13 @@ return true; if (!(object instanceof BuildCommand)) return false; + //for performance compare the cached hash value first + if (hashCode() != object.hashCode()) + return false; BuildCommand command = (BuildCommand) object; // equal if same builder name and equal argument tables - return getBuilderName().equals(command.getBuilderName()) && - getArguments(false).equals(command.getArguments(false)); + return (name == null ? command.name == null : name.equals(command.name)) && + (arguments == null ? command.arguments == null : arguments.equals(command.arguments)); } /** * @see ICommand#getArguments @@ -55,8 +65,17 @@ return getName(); } public int hashCode() { - // hash on name alone - return getName().hashCode(); + //lazily compute and cache hashcode + if (hash == -1) { + String name = getName(); + hash = name == null ? 17 : name.hashCode() * 37; + if (arguments != null) + hash += arguments.hashCode(); + //make sure it is never the same as the default value + if (hash == -1) + hash++; + } + return hash; } /** * @see ICommand#setArguments @@ -64,6 +83,7 @@ public void setArguments(Map value) { // copy parameter for safety's sake arguments = value == null ? null : new HashMap(value); + hash = -1; } /** * @see ICommand#setBuilderName @@ -71,5 +91,6 @@ public void setBuilderName(String value) { //don't allow builder name to be null setName(value == null ? "" : value); //$NON-NLS-1$ + hash = -1; } }
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java index 1d1fc20..ed118ff 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java
@@ -26,6 +26,16 @@ //used for debug/trace timing private long timeStamp = -1; + /** + * Persistent information for builders that have not yet been instantiated. + * For closed projects, this contains (IProject -> (List of BuilderPersistentInfo)). + * For open projects: (IProject -> (Map of (ICommand -> BuilderPersistentInfo))) + * This is because the build commands are not yet known for closed projects + * since the project description has not been read from disk. The + * opening() method performs the conversion from one format to the other. + */ + private final Map builderPersistentInfo = new HashMap(); + //the following four fields only apply for the lifetime of //a single builder invocation. protected ElementTree currentTree; @@ -159,11 +169,11 @@ }; Platform.run(code); } -protected void basicBuild(IProject project, int trigger, String builderName, Map args, MultiStatus status, IProgressMonitor monitor) { +protected void basicBuild(IProject project, int trigger, ICommand command, MultiStatus status, IProgressMonitor monitor) { IncrementalProjectBuilder builder = null; try { - builder = getBuilder(builderName, project); - if (!validateNature(builder, builderName)) { + builder = getBuilder(command, project); + if (!validateNature(builder, command.getBuilderName())) { //skip this builder and null its last built tree because it is invalid //if the nature gets added or re-enabled a full build will be triggered ((InternalBuilder)builder).setLastBuiltTree(null); @@ -173,7 +183,7 @@ status.add(e.getStatus()); return; } - basicBuild(trigger, builder, args, status, monitor); + basicBuild(trigger, builder, ((BuildCommand)command).getArguments(false), status, monitor); } protected void basicBuild(IProject project, int trigger, ICommand[] commands, MultiStatus status, IProgressMonitor monitor) { monitor = Policy.monitorFor(monitor); @@ -183,7 +193,7 @@ for (int i = 0; i < commands.length; i++) { IProgressMonitor sub = Policy.subMonitorFor(monitor, 1); BuildCommand command = (BuildCommand) commands[i]; - basicBuild(project, trigger, command.getBuilderName(), command.getArguments(false), status, sub); + basicBuild(project, trigger, command, status, sub); Policy.checkCanceled(monitor); } } finally { @@ -247,7 +257,7 @@ try { building = true; MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Policy.bind("events.errors"), null); //$NON-NLS-1$ - basicBuild(project, kind, builderName, args, status, Policy.subMonitorFor(monitor, 1)); + basicBuild(project, kind, new BuildCommand(builderName, args), status, Policy.subMonitorFor(monitor, 1)); if (!status.isOK()) throw new ResourceException(status); } finally { @@ -266,12 +276,13 @@ public void closing(IProject project) { } /** - * Creates and returns a Map mapping String(builder name) -> BuilderPersistentInfo. - * The table includes entries for all builders that are - * in the builder spec, and that have a last built state, even if they - * have not been instantiated this session. + * Creates and returns a List of BuilderPersistentInfo, or null if there are + * no builders for this project. + * The list includes entries for all builders that are in the builder spec, and + * that have a last built state, even if they have not been instantiated this + * session. */ -public Map createBuildersPersistentInfo(IProject project) throws CoreException { +public List createBuildersPersistentInfo(IProject project) throws CoreException { /* get the old builder map */ Map oldInfos = getBuildersPersistentInfo(project); @@ -280,30 +291,31 @@ return null; /* build the new map */ - Map newInfos = new HashMap(buildCommands.length * 2); - Hashtable instantiatedBuilders = getBuilders(project); + List newInfos = new ArrayList(buildCommands.length); + Map instantiatedBuilders = getBuilders(project); for (int i = 0; i < buildCommands.length; i++) { - String builderName = buildCommands[i].getBuilderName(); + ICommand command = buildCommands[i]; BuilderPersistentInfo info = null; - IncrementalProjectBuilder builder = (IncrementalProjectBuilder) instantiatedBuilders.get(builderName); + InternalBuilder builder = (InternalBuilder) instantiatedBuilders.get(command); if (builder == null) { // if the builder was not instantiated, use the old info if any. if (oldInfos != null) - info = (BuilderPersistentInfo) oldInfos.get(builderName); + info = (BuilderPersistentInfo) oldInfos.get(command); } else if (!(builder instanceof MissingBuilder)) { - ElementTree oldTree = ((InternalBuilder) builder).getLastBuiltTree(); - //don't persist build state for builders that have no last built state + ElementTree oldTree = builder.getLastBuiltTree(); + //don't persist build state for builders that have no last built tree if (oldTree != null) { - // if the builder was instantiated, construct a memento with the important info + // construct a memento with the important info info = new BuilderPersistentInfo(); info.setProjectName(project.getName()); - info.setBuilderName(builderName); + info.setBuilderName(command.getBuilderName()); info.setLastBuildTree(oldTree); - info.setInterestingProjects(((InternalBuilder)builder).getInterestingProjects()); + info.setInterestingProjects(builder.getInterestingProjects()); + info.setBuildSpecPosition(i); } } if (info != null) - newInfos.put(builderName, info); + newInfos.add(info); } return newInfos; } @@ -316,37 +328,42 @@ return currentBuilder.getProject().getFullPath().toString(); } public void deleting(IProject project) { - //make sure the builder persistent info is deleted for the project move case + //make sure the builder persistent info is deleted (move and delete cases) setBuildersPersistentInfo(project, null); } -protected IncrementalProjectBuilder getBuilder(String builderName, IProject project) throws CoreException { - Hashtable builders = getBuilders(project); - IncrementalProjectBuilder result = (IncrementalProjectBuilder) builders.get(builderName); +protected IncrementalProjectBuilder getBuilder(ICommand command, IProject project) throws CoreException { + Map builders = getBuilders(project); + IncrementalProjectBuilder result = (IncrementalProjectBuilder) builders.get(command); if (result != null) return result; - result = initializeBuilder(builderName, project); - builders.put(builderName, result); + result = initializeBuilder(command, project); + builders.put(command, result); ((InternalBuilder) result).setProject(project); result.startupOnInitialize(); return result; } /** - * Returns a hashtable of all instantiated builders for the given project. - * This hashtable maps String(builder name) -> Builder. + * Returns a map of all instantiated builders for the given project. + * This hashtable maps ICommand -> Builder. */ -protected Hashtable getBuilders(IProject project) { +protected Map getBuilders(IProject project) { ProjectInfo info = (ProjectInfo) workspace.getResourceInfo(project.getFullPath(), false, false); Assert.isNotNull(info, Policy.bind("events.noProject", project.getName())); //$NON-NLS-1$ return info.getBuilders(); } /** - * Returns a Map mapping String(builder name) -> BuilderPersistentInfo. + * Returns a Map mapping ICommand -> BuilderPersistentInfo, or + * null if there is no persistent info for this project. * The map includes entries for all builders that are in the builder spec, - * and that have a last built state, even if they have not been instantiated + * and that have a last built state, but have not been instantiated * this session. */ public Map getBuildersPersistentInfo(IProject project) throws CoreException { - return (Map) project.getSessionProperty(K_BUILD_MAP); + Object result = builderPersistentInfo.get(project); + //for closed projects this will be a List + if (result instanceof Map) + return (Map)result; + return null; } protected IResourceDelta getDelta(IProject project) { if (currentTree == null) { @@ -436,8 +453,9 @@ * prevent trying to instantiate it every time a build is run. * This method NEVER returns null. */ -protected IncrementalProjectBuilder initializeBuilder(String builderName, IProject project) throws CoreException { +protected IncrementalProjectBuilder initializeBuilder(ICommand command, IProject project) throws CoreException { try { + String builderName = command.getBuilderName(); IncrementalProjectBuilder builder = instantiateBuilder(builderName); if (builder == null) { //unable to create the builder, so create a placeholder to fill in for it @@ -446,7 +464,7 @@ // get the map of builders to get the last built tree Map infos = getBuildersPersistentInfo(project); if (infos != null) { - BuilderPersistentInfo info = (BuilderPersistentInfo) infos.remove(builderName); + BuilderPersistentInfo info = (BuilderPersistentInfo) infos.remove(command); if (info != null) { ElementTree tree = info.getLastBuiltTree(); if (tree != null) @@ -455,7 +473,7 @@ } // delete the build map if it's now empty if (infos.size() == 0) - setBuildersPersistentInfo(project, null); + builderPersistentInfo.remove(project); } return builder; } catch (CoreException e) { @@ -540,6 +558,36 @@ return false; } public void opening(IProject project) { + //a project is being opened. link builder persistent info to appropriate + //command in the build spec + List infoList = (List)builderPersistentInfo.remove(project); + if (infoList == null || infoList.size() == 0) + return;//no builders for this project + + ProjectDescription description = ((Project)project).internalGetDescription(); + if (description != null) { + ICommand[] commands = description.getBuildSpec(false); + //create map of ICommand->BuilderPersistentInfo + HashMap infoMap = new HashMap(commands.length * 2 + 1); + for (Iterator it = infoList.iterator(); it.hasNext();) { + BuilderPersistentInfo info = (BuilderPersistentInfo) it.next(); + int position = info.getBuildSpecPosition(); + if (position >= 0 && position < commands.length) + infoMap.put(commands[position], info); + else { + //backwards compatibility -- build spec position wasn't previously stored + //find a build command with matching builder name + String builderName = info.getBuilderName(); + for (int i = 0; i < commands.length; i++) { + if (commands[i].getBuilderName().equals(builderName)) { + infoMap.put(commands[i], info); + break; + } + } + } + } + builderPersistentInfo.put(project, infoMap); + } } /** * Removes all builders with the given ID from the build spec. @@ -572,21 +620,14 @@ } /** - * Sets the builder map for the given project. The builder map is - * a Map mapping String(builder name) -> BuilderPersistentInfo. - * The map includes entries for all builders that are - * in the builder spec, and that have a last built state, even if they - * have not been instantiated this session. + * Supplies the list of BuilderPersistentInfo objects that was serialized + * on shutdown. This list includes entries for all builders that are + * in the builder spec, have a last built state, but have not been instantiated + * yest this session. Infos should only ever be supplied on startup, as this + * information depends on the current ordering of the project's build spec. */ -public void setBuildersPersistentInfo(IProject project, Map map) { - try { - project.setSessionProperty(K_BUILD_MAP, map); - } catch (CoreException e) { - //project is missing -- build state will be lost - //can't throw an exception because this happens on startup - IStatus error = new ResourceStatus(IStatus.ERROR, 1, project.getFullPath(), "Project missing in setBuildersPersistentInfo", null); - ResourcesPlugin.getPlugin().getLog().log(error); - } +public void setBuildersPersistentInfo(IProject project, List infoList) { + builderPersistentInfo.put(project, infoList); } public void shutdown(IProgressMonitor monitor) { }
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuilderPersistentInfo.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuilderPersistentInfo.java index a80590a..b2a9ec0 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuilderPersistentInfo.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuilderPersistentInfo.java
@@ -19,18 +19,13 @@ protected String builderName; protected ElementTree lastBuildTree; protected IProject[] interestingProjects = ICoreConstants.EMPTY_PROJECT_ARRAY; - -public void setProjectName(String name) { - projectName = name; + /** Offset of this builder in the build spec */ + protected int buildSpecPosition = -1; + +public BuilderPersistentInfo() { } -public void setBuilderName(String name) { - builderName = name; -} -public void setLastBuildTree(ElementTree tree) { - lastBuildTree = tree; -} -public void setInterestingProjects(IProject[] projects) { - interestingProjects = projects; +public int getBuildSpecPosition() { + return buildSpecPosition; } public String getProjectName() { return projectName; @@ -44,4 +39,19 @@ public IProject[] getInterestingProjects() { return interestingProjects; } +public void setProjectName(String name) { + projectName = name; +} +public void setBuilderName(String name) { + builderName = name; +} +public void setBuildSpecPosition(int buildSpecPosition) { + this.buildSpecPosition = buildSpecPosition; +} +public void setLastBuildTree(ElementTree tree) { + lastBuildTree = tree; +} +public void setInterestingProjects(IProject[] projects) { + interestingProjects = projects; +} } \ No newline at end of file
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ICoreConstants.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ICoreConstants.java index c64d337..73f4d79 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ICoreConstants.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ICoreConstants.java
@@ -16,8 +16,6 @@ public interface ICoreConstants { // Standard resource SessionProperties - /** map of builders to their last built state. */ - public static final QualifiedName K_BUILD_MAP = new QualifiedName(ResourcesPlugin.PI_RESOURCES, "BuildMap"); //$NON-NLS-1$ // resource info constants static final long I_UNKNOWN_SYNC_INFO = -2; @@ -63,6 +61,7 @@ public static final int WORKSPACE_TREE_VERSION_1 = 67305985; public static final int WORKSPACE_TREE_VERSION_2 = 67305986; + public static final int WORKSPACE_TREE_VERSION_3 = 67305987; // helper constants for empty structures public static final IProject[] EMPTY_PROJECT_ARRAY = new IProject[0];
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java index e1bc292..29419ce 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java
@@ -460,7 +460,7 @@ //clear instantiated builders and natures because they reference the project handle ProjectInfo info = (ProjectInfo) ((Resource)destination).getResourceInfo(false, true); - info.setBuilders(null); + info.clearBuilders(); info.clearNatures(); //clear session properties and markers for the new project, because they shouldn't be copied.
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectInfo.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectInfo.java index 53ee9c6..db8a092 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectInfo.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectInfo.java
@@ -10,14 +10,15 @@ ******************************************************************************/ package org.eclipse.core.internal.resources; -import org.eclipse.core.resources.IProjectNature; -import org.eclipse.core.internal.properties.PropertyStore; import java.util.HashMap; -import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.core.internal.properties.PropertyStore; +import org.eclipse.core.resources.IProjectNature; public class ProjectInfo extends ResourceInfo { /** The list of builders for this project */ - protected Hashtable builders = null; + protected HashMap builders = null; /** The property store for this resource */ protected PropertyStore propertyStore = null; @@ -27,12 +28,19 @@ /** The list of natures for this project */ protected HashMap natures = null; +public void clearBuilders() { + builders = null; +} public synchronized void clearNatures() { natures = null; } -public Hashtable getBuilders() { +/** + * Returns a map, ICommand->IncrementalProjectBuilder, of all builders + * that have been instantiated for this project during this session. + */ +public Map getBuilders() { if (builders == null) - builders = new Hashtable(5); + builders = new HashMap(5); return builders; } /** @@ -54,9 +62,6 @@ public PropertyStore getPropertyStore() { return propertyStore; } -public void setBuilders(Hashtable value) { - builders = value; -} /** * Sets the description associated with this info. The value may be null. */
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ResourceTree.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ResourceTree.java index 8fe4c53..8e45da3 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ResourceTree.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ResourceTree.java
@@ -215,7 +215,7 @@ // Clear the natures and builders on the destination project. ProjectInfo info = (ProjectInfo) destination.getResourceInfo(false, true); info.clearNatures(); - info.setBuilders(null); + info.clearBuilders(); // Generate marker deltas. try {
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java index 928874d..76ae085 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java
@@ -26,8 +26,7 @@ protected Properties masterTable; protected ElementTree lastSnap; protected int operationCount = 0; - protected boolean snapshotRequested; - + protected boolean snapshotRequested; protected DelayedSnapshotRunnable snapshotRunnable; @@ -173,9 +172,9 @@ for (int i = 0; i < projects.length; i++) { IProject project = projects[i]; if (project.isOpen()) { - Map builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); + List builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); if (builderInfos != null) { - for (Iterator it = builderInfos.values().iterator(); it.hasNext();) { + for (Iterator it = builderInfos.iterator(); it.hasNext();) { BuilderPersistentInfo info = (BuilderPersistentInfo) it.next(); trees.add(info.getLastBuiltTree()); } @@ -765,7 +764,8 @@ workspace.getMetaArea().write(description); IProject[] roots = workspace.getRoot().getProjects(); for (int i = 0; i < roots.length; i++) - saveMetaInfo((Project) roots[i], null); + if (roots[i].isAccessible()) + saveMetaInfo((Project) roots[i], null); } /** * Writes the current state of the entire workspace tree to disk. @@ -779,7 +779,7 @@ IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation); DataOutputStream output = new DataOutputStream(new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString())); try { - output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); + output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_3); writeTree(computeStatesToSave(contexts, workspace.getElementTree()), output, monitor); } finally { output.close(); @@ -869,7 +869,7 @@ SafeChunkyOutputStream safeStream = new SafeChunkyOutputStream(localFile); DataOutputStream out = new DataOutputStream(safeStream); try { - out.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); + out.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_3); writeWorkspaceFields(out, monitor); writer.writeDelta(tree, lastSnap, Path.ROOT, writer.D_INFINITE, out, ResourceComparator.getComparator()); safeStream.succeed(); @@ -979,16 +979,16 @@ // add builders' trees IProject[] projects = workspace.getRoot().getProjects(); - List builders = new ArrayList(projects.length * 2); + List builderInfos = new ArrayList(projects.length * 2); for (int i = 0; i < projects.length; i++) { IProject project = projects[i]; if (project.isOpen()) { - Map infos = workspace.getBuildManager().createBuildersPersistentInfo(project); + List infos = workspace.getBuildManager().createBuildersPersistentInfo(project); if (infos != null) - builders.addAll(infos.values()); + builderInfos.addAll(infos); } } - writeBuilderPersistentInfo(output, builders, trees, Policy.subMonitorFor(monitor, Policy.totalWork * 10 / 100)); + writeBuilderPersistentInfo(output, builderInfos, trees, Policy.subMonitorFor(monitor, Policy.totalWork * 10 / 100)); // add the current tree in the list as the last element trees.add(current); @@ -1013,7 +1013,7 @@ SafeFileOutputStream safe = new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString()); try { DataOutputStream output = new DataOutputStream(safe); - output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); + output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_3); writeTree(project, output, null); } finally { safe.close(); @@ -1036,13 +1036,13 @@ boolean wasImmutable = false; try { /** - * Obtain a table of String(builder name) -> BuilderPersistentInfo. + * Obtain a List of BuilderPersistentInfo for this project * This includes builders that have never been instantiated * but already had a last built state. */ - Map builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); - List builders = builderInfos == null ? new ArrayList(5) : new ArrayList(builderInfos.values()); - List trees = new ArrayList(builders.size() + 1); + List builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); + int numBuilders = builderInfos == null ? 0 : builderInfos.size(); + List trees = new ArrayList(numBuilders + 1); monitor.worked(1); /* Make sure the most recent tree is in the array */ @@ -1051,7 +1051,7 @@ current.immutable(); /* add the tree for each builder to the array */ - writeBuilderPersistentInfo(output, builders, trees, Policy.subMonitorFor(monitor, 1)); + writeBuilderPersistentInfo(output, builderInfos, trees, Policy.subMonitorFor(monitor, 1)); trees.add(current); /* save the forest! */ @@ -1425,13 +1425,14 @@ for (int i = 0; i < projects.length; i++) visitAndSnap(projects[i]); } -protected void writeBuilderPersistentInfo(DataOutputStream output, List builders, List trees, IProgressMonitor monitor) throws IOException { +protected void writeBuilderPersistentInfo(DataOutputStream output, List builderInfos, List trees, IProgressMonitor monitor) throws IOException { monitor = Policy.monitorFor(monitor); try { // write the number of builders we are saving - output.writeInt(builders.size()); - for (int i = 0; i < builders.size(); i++) { - BuilderPersistentInfo info = (BuilderPersistentInfo) builders.get(i); + int numBuilders = builderInfos == null ? 0 : builderInfos.size(); + output.writeInt(numBuilders); + for (int i = 0; i < numBuilders; i++) { + BuilderPersistentInfo info = (BuilderPersistentInfo) builderInfos.get(i); output.writeUTF(info.getProjectName()); output.writeUTF(info.getBuilderName()); // write interesting projects @@ -1439,6 +1440,8 @@ output.writeInt(interestingProjects.length); for (int j = 0; j < interestingProjects.length; j++) output.writeUTF(interestingProjects[j].getName()); + //write build spec position + output.writeInt(info.getBuildSpecPosition()); ElementTree last = info.getLastBuiltTree(); if (last ==null) { //try to be resilient if a builder has no last built tree
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader.java index d8fedf4..e1b2428 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader.java
@@ -81,7 +81,7 @@ monitor.done(); } } -protected void readBuildersPersistentInfo(DataInputStream input, List builders, IProgressMonitor monitor) throws IOException, CoreException { +protected void readBuildersPersistentInfo(DataInputStream input, List builders, IProgressMonitor monitor) throws IOException { monitor = Policy.monitorFor(monitor); try { int builderCount = input.readInt(); @@ -139,7 +139,7 @@ protected void linkBuildersToTrees(List buildersToBeLinked, ElementTree[] trees, int index, IProgressMonitor monitor) throws CoreException { monitor = Policy.monitorFor(monitor); try { - HashMap infos = null; + ArrayList infos = null; String projectName = null; for (int i = 0; i < buildersToBeLinked.size(); i++) { BuilderPersistentInfo info = (BuilderPersistentInfo) buildersToBeLinked.get(i); @@ -149,10 +149,10 @@ workspace.getBuildManager().setBuildersPersistentInfo(project, infos); } projectName = info.getProjectName(); - infos = new HashMap(5); + infos = new ArrayList(5); } info.setLastBuildTree(trees[index++]); - infos.put(info.getBuilderName(), info); + infos.add(info); } if (infos != null) { IProject project = workspace.getRoot().getProject(projectName); @@ -195,6 +195,8 @@ return new WorkspaceTreeReader(workspace); case ICoreConstants.WORKSPACE_TREE_VERSION_2: return new WorkspaceTreeReader_2(workspace); + case ICoreConstants.WORKSPACE_TREE_VERSION_3: + return new WorkspaceTreeReader_3(workspace); default: // The following class should be // removed soon. See comments in WorkspaceTreeReader_0. @@ -226,13 +228,13 @@ /* map builder names to trees */ if (numBuilders > 0) { - Map infos = new HashMap(trees.length * 2 + 1); + List infos = new ArrayList(numBuilders); for (int i = 0; i < numBuilders; i++) { BuilderPersistentInfo info = new BuilderPersistentInfo(); info.setBuilderName(builderNames[i]); info.setProjectName(project.getName()); info.setLastBuildTree(trees[i]); - infos.put(builderNames[i], info); + infos.add(info); } workspace.getBuildManager().setBuildersPersistentInfo(project, infos); }
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader_3.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader_3.java new file mode 100644 index 0000000..d3ecf23 --- /dev/null +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkspaceTreeReader_3.java
@@ -0,0 +1,55 @@ +/********************************************************************** + * Copyright (c) 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.core.internal.resources; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.List; + +import org.eclipse.core.internal.events.BuilderPersistentInfo; +import org.eclipse.core.internal.utils.Policy; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Reads .tree files in format version 3. + */ +public class WorkspaceTreeReader_3 extends WorkspaceTreeReader_2 { +public WorkspaceTreeReader_3(Workspace workspace) { + super(workspace); +} +protected int getVersion() { + return ICoreConstants.WORKSPACE_TREE_VERSION_3; +} +protected void readBuildersPersistentInfo(DataInputStream input, List builders, IProgressMonitor monitor) throws IOException { + monitor = Policy.monitorFor(monitor); + try { + int builderCount = input.readInt(); + for (int i = 0; i < builderCount; i++) { + BuilderPersistentInfo info = new BuilderPersistentInfo(); + info.setProjectName(input.readUTF()); + info.setBuilderName(input.readUTF()); + // read interesting projects + int n = input.readInt(); + IProject[] projects = new IProject[n]; + for (int j = 0; j < n; j++) + projects[j] = workspace.getRoot().getProject(input.readUTF()); + info.setInterestingProjects(projects); + //read build spec position + info.setBuildSpecPosition(input.readInt()); + builders.add(info); + } + } finally { + monitor.done(); + } +} +} \ No newline at end of file