/******************************************************************************* * 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 * Broadcom Corporation - ongoing development *******************************************************************************/ package org.eclipse.core.internal.resources; import java.io.DataInputStream; import java.io.IOException; 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.resources.IProject; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.runtime.*; /** * Reads version 2 of the workspace tree file format. * * This version differs from version 1 in the amount of information that is persisted * for each builder. Version 1 only stored builder names and trees. Version * 2 stores builder names, project names, trees, and interesting projects for * each builder. * <p> * Since 3.7 support has been added for persisting multiple delta trees for * multi-configuration builders. * </p> * <p> * To achieve backwards compatibility, the new additional information is * appended to the existing workspace tree file. This allows the workspace * to be opened, and function, with older eclipse products. * </p> */ public class WorkspaceTreeReader_2 extends WorkspaceTreeReader_1 { private List<BuilderPersistentInfo> builderInfos; public WorkspaceTreeReader_2(Workspace workspace) { super(workspace); } protected int getVersion() { return ICoreConstants.WORKSPACE_TREE_VERSION_2; } /* * overwritten from WorkspaceTreeReader_1 */ 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++) { BuilderPersistentInfo info = readBuilderInfo(project, input, i); // 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); builders.add(info); } } finally { monitor.done(); } } /** * Read a workspace tree storing information about multiple projects. * Overrides {@link WorkspaceTreeReader_1#readTree(DataInputStream, IProgressMonitor)} */ 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); builderInfos = new ArrayList<BuilderPersistentInfo>(20); // Read the version 2 part of the file, but don't set the builder info in // the projects. Store it in builderInfos instead. 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)); final 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)); // Since 3.7: Read the per-configuration trees if available if (input.available() > 0) { buildersToBeLinked.clear(); readBuildersPersistentInfo(null, input, buildersToBeLinked, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); linkBuildersToTrees(buildersToBeLinked, trees, 0, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100)); for (Iterator<BuilderPersistentInfo> it = builderInfos.iterator(); it.hasNext();) it.next().setConfigName(input.readUTF()); } // Set the builder infos on the projects setBuilderInfos(builderInfos); } catch (IOException e) { message = Messages.resources_readProjectTree; throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, message, e); } finally { monitor.done(); } } /** * Read a workspace tree storing information about a single project. * Overrides {@link WorkspaceTreeReader_2#readTree(IProject, DataInputStream, IProgressMonitor)} */ 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); builderInfos = new ArrayList<BuilderPersistentInfo>(20); // Read the version 2 part of the file, but don't set the builder info in // the projects. It is stored in builderInfos instead. List<BuilderPersistentInfo> buildersToBeLinked = new ArrayList<BuilderPersistentInfo>(20); readBuildersPersistentInfo(project, input, buildersToBeLinked, Policy.subMonitorFor(monitor, 1)); ElementTree[] trees = readTrees(project.getFullPath(), input, Policy.subMonitorFor(monitor, 8)); linkBuildersToTrees(buildersToBeLinked, trees, 0, Policy.subMonitorFor(monitor, 1)); // Since 3.7: Read the additional builder information if (input.available() > 0) { List<BuilderPersistentInfo> infos = new ArrayList<BuilderPersistentInfo>(5); readBuildersPersistentInfo(project, input, infos, Policy.subMonitorFor(monitor, 1)); linkBuildersToTrees(infos, trees, 0, Policy.subMonitorFor(monitor, 1)); for (Iterator<BuilderPersistentInfo> it = builderInfos.iterator(); it.hasNext();) it.next().setConfigName(input.readUTF()); } // Set the builder info on the projects setBuilderInfos(builderInfos); } catch (IOException e) { message = Messages.resources_readProjectTree; throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, null, message, e); } finally { monitor.done(); } } /** * This implementation allows pre-3.7 version 2 and post-3.7 version 2 information to be loaded in separate passes. * Links trees with the given builders, but does not add them to the projects. * Overrides {@link WorkspaceTreeReader_1#linkBuildersToTrees(List, ElementTree[], int, IProgressMonitor)} */ protected void linkBuildersToTrees(List<BuilderPersistentInfo> buildersToBeLinked, ElementTree[] trees, int index, IProgressMonitor monitor) { monitor = Policy.monitorFor(monitor); try { for (int i = 0; i < buildersToBeLinked.size(); i++) { BuilderPersistentInfo info = buildersToBeLinked.get(i); info.setLastBuildTree(trees[index++]); builderInfos.add(info); } } finally { monitor.done(); } } /** * Given a list of builder infos, group them by project and set them on the project. */ private void setBuilderInfos(List<BuilderPersistentInfo> infos) { Map<String, List<BuilderPersistentInfo>> groupedInfos = new HashMap<String, List<BuilderPersistentInfo>>(); for (Iterator<BuilderPersistentInfo> it = infos.iterator(); it.hasNext();) { BuilderPersistentInfo info = it.next(); if (!groupedInfos.containsKey(info.getProjectName())) groupedInfos.put(info.getProjectName(), new ArrayList<BuilderPersistentInfo>()); groupedInfos.get(info.getProjectName()).add(info); } for (Map.Entry<String, List<BuilderPersistentInfo>> entry : groupedInfos.entrySet()) { IProject proj = workspace.getRoot().getProject(entry.getKey()); workspace.getBuildManager().setBuildersPersistentInfo(proj, entry.getValue()); } } }