/******************************************************************************* * Copyright (c) 2000, 2011 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 *******************************************************************************/ 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<BuilderPersistentInfo>(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(); } } 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(); } } 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<String, SavedState>(20); List<SavedState> pluginsToBeLinked = new ArrayList<SavedState>(20); readPluginsSavedStates(input, savedStates, pluginsToBeLinked, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); workspace.getSaveManager().setPluginsSavedState(savedStates); List<BuilderPersistentInfo> buildersToBeLinked = new ArrayList<BuilderPersistentInfo>(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(); } } 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<BuilderPersistentInfo>(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(); } } }