| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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 |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Francis Lynch (Wind River) - [305718] Allow reading snapshot into renamed project |
| * James Blackburn (Broadcom Corp.) - ongoing development |
| * Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427 |
| *******************************************************************************/ |
| package org.eclipse.core.internal.resources; |
| |
| import java.io.*; |
| import java.util.*; |
| import org.eclipse.core.internal.events.BuilderPersistentInfo; |
| import org.eclipse.core.internal.utils.Messages; |
| import org.eclipse.core.internal.utils.Policy; |
| import org.eclipse.core.internal.watson.ElementTree; |
| import org.eclipse.core.internal.watson.ElementTreeReader; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResourceStatus; |
| import org.eclipse.core.runtime.*; |
| |
| /** |
| * Reads version 1 of the workspace tree file format. |
| */ |
| public class WorkspaceTreeReader_1 extends WorkspaceTreeReader { |
| protected Workspace workspace; |
| |
| public WorkspaceTreeReader_1(Workspace workspace) { |
| this.workspace = workspace; |
| } |
| |
| protected int getVersion() { |
| return ICoreConstants.WORKSPACE_TREE_VERSION_1; |
| } |
| |
| protected void linkBuildersToTrees(List<BuilderPersistentInfo> buildersToBeLinked, ElementTree[] trees, int index, IProgressMonitor monitor) { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| ArrayList<BuilderPersistentInfo> infos = null; |
| String projectName = null; |
| for (int i = 0; i < buildersToBeLinked.size(); i++) { |
| BuilderPersistentInfo info = buildersToBeLinked.get(i); |
| if (!info.getProjectName().equals(projectName)) { |
| if (infos != null) { // if it is not the first iteration |
| IProject project = workspace.getRoot().getProject(projectName); |
| workspace.getBuildManager().setBuildersPersistentInfo(project, infos); |
| } |
| projectName = info.getProjectName(); |
| infos = new ArrayList<>(5); |
| } |
| info.setLastBuildTree(trees[index++]); |
| infos.add(info); |
| } |
| if (infos != null) { |
| IProject project = workspace.getRoot().getProject(projectName); |
| workspace.getBuildManager().setBuildersPersistentInfo(project, infos); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| protected void linkPluginsSavedStateToTrees(List<SavedState> states, ElementTree[] trees, IProgressMonitor monitor) { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| for (int i = 0; i < states.size(); i++) { |
| SavedState state = states.get(i); |
| // If the tree is too old (depends on the policy), the plug-in should not |
| // get it back as a delta. It is expensive to maintain this information too long. |
| final SaveManager saveManager = workspace.getSaveManager(); |
| if (!saveManager.isOldPluginTree(state.pluginId)) { |
| state.oldTree = trees[i]; |
| } else { |
| //clear information for this plugin from master table |
| saveManager.clearDeltaExpiration(state.pluginId); |
| } |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| protected BuilderPersistentInfo readBuilderInfo(IProject project, DataInputStream input, int index) throws IOException { |
| //read the project name |
| String projectName = input.readUTF(); |
| //use the name of the project handle if available |
| if (project != null) |
| projectName = project.getName(); |
| String builderName = input.readUTF(); |
| return new BuilderPersistentInfo(projectName, builderName, index); |
| } |
| |
| protected void readBuildersPersistentInfo(IProject project, DataInputStream input, List<BuilderPersistentInfo> builders, IProgressMonitor monitor) throws IOException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| int builderCount = input.readInt(); |
| for (int i = 0; i < builderCount; i++) |
| builders.add(readBuilderInfo(project, input, i)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| protected void readPluginsSavedStates(DataInputStream input, HashMap<String, SavedState> savedStates, List<SavedState> plugins, IProgressMonitor monitor) throws IOException, CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| int stateCount = input.readInt(); |
| for (int i = 0; i < stateCount; i++) { |
| String pluginId = input.readUTF(); |
| SavedState state = new SavedState(workspace, pluginId, null, null); |
| savedStates.put(pluginId, state); |
| plugins.add(state); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| @Override |
| public ElementTree readSnapshotTree(DataInputStream input, ElementTree complete, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| String message; |
| try { |
| message = Messages.resources_readingSnap; |
| monitor.beginTask(message, Policy.totalWork); |
| ElementTreeReader reader = new ElementTreeReader(workspace.getSaveManager()); |
| while (input.available() > 0) { |
| readWorkspaceFields(input, Policy.subMonitorFor(monitor, Policy.totalWork / 2)); |
| complete = reader.readDelta(complete, input); |
| try { |
| // make sure each snapshot is read by the correct reader |
| int version = input.readInt(); |
| if (version != getVersion()) |
| return WorkspaceTreeReader.getReader(workspace, version).readSnapshotTree(input, complete, monitor); |
| } catch (EOFException e) { |
| break; |
| } |
| } |
| return complete; |
| } catch (IOException e) { |
| message = Messages.resources_readWorkspaceSnap; |
| throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, message, e); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| @Override |
| public void readTree(DataInputStream input, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| String message; |
| try { |
| message = Messages.resources_reading; |
| monitor.beginTask(message, Policy.totalWork); |
| readWorkspaceFields(input, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100)); |
| |
| HashMap<String, SavedState> savedStates = new HashMap<>(20); |
| List<SavedState> pluginsToBeLinked = new ArrayList<>(20); |
| readPluginsSavedStates(input, savedStates, pluginsToBeLinked, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); |
| workspace.getSaveManager().setPluginsSavedState(savedStates); |
| |
| List<BuilderPersistentInfo> buildersToBeLinked = new ArrayList<>(20); |
| readBuildersPersistentInfo(null, input, buildersToBeLinked, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); |
| |
| ElementTree[] trees = readTrees(Path.ROOT, input, Policy.subMonitorFor(monitor, Policy.opWork * 40 / 100)); |
| linkPluginsSavedStateToTrees(pluginsToBeLinked, trees, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); |
| linkBuildersToTrees(buildersToBeLinked, trees, pluginsToBeLinked.size(), Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); |
| |
| } catch (IOException e) { |
| message = Messages.resources_readWorkspaceTree; |
| throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, message, e); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| @Override |
| public void readTree(IProject project, DataInputStream input, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| String message; |
| try { |
| message = Messages.resources_reading; |
| monitor.beginTask(message, 10); |
| /* read the number of builders */ |
| int numBuilders = input.readInt(); |
| |
| /* read in the list of builder names */ |
| String[] builderNames = new String[numBuilders]; |
| for (int i = 0; i < numBuilders; i++) { |
| String builderName = input.readUTF(); |
| builderNames[i] = builderName; |
| } |
| monitor.worked(1); |
| |
| /* read and link the trees */ |
| ElementTree[] trees = readTrees(project.getFullPath(), input, Policy.subMonitorFor(monitor, 8)); |
| |
| /* map builder names to trees */ |
| if (numBuilders > 0) { |
| ArrayList<BuilderPersistentInfo> infos = new ArrayList<>(trees.length * 2 + 1); |
| for (int i = 0; i < numBuilders; i++) { |
| BuilderPersistentInfo info = new BuilderPersistentInfo(project.getName(), builderNames[i], -1); |
| info.setLastBuildTree(trees[i]); |
| infos.add(info); |
| } |
| workspace.getBuildManager().setBuildersPersistentInfo(project, infos); |
| } |
| monitor.worked(1); |
| |
| } catch (IOException e) { |
| message = Messages.resources_readProjectTree; |
| throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, message, e); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Read trees from disk and link them to the workspace tree. |
| */ |
| protected ElementTree[] readTrees(IPath root, DataInputStream input, IProgressMonitor monitor) throws IOException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Messages.resources_reading; |
| monitor.beginTask(message, 4); |
| ElementTreeReader treeReader = new ElementTreeReader(workspace.getSaveManager()); |
| String newProjectName = ""; //$NON-NLS-1$ |
| if (renameProjectNode) { |
| //have the existing project name (path to import into) take precedence over what we read |
| newProjectName = root.segment(0); |
| } |
| ElementTree[] trees = treeReader.readDeltaChain(input, newProjectName); |
| monitor.worked(3); |
| if (root.isRoot()) { |
| //Don't need to link because we're reading the whole workspace. |
| //The last tree in the chain is the complete tree. |
| ElementTree newTree = trees[trees.length - 1]; |
| newTree.setTreeData(workspace.tree.getTreeData()); |
| workspace.tree = newTree; |
| } else { |
| //splice the restored tree into the current set of trees |
| workspace.linkTrees(root, trees); |
| } |
| monitor.worked(1); |
| return trees; |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| protected void readWorkspaceFields(DataInputStream input, IProgressMonitor monitor) throws IOException, CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| // read the node id |
| workspace.nextNodeId = input.readLong(); |
| // read the modification stamp (no longer used) |
| input.readLong(); |
| // read the next marker id |
| workspace.nextMarkerId = input.readLong(); |
| // read the synchronizer's registered sync partners |
| ((Synchronizer) workspace.getSynchronizer()).readPartners(input); |
| } finally { |
| monitor.done(); |
| } |
| } |
| } |