/******************************************************************************* * 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 * 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 *******************************************************************************/ package org.eclipse.core.internal.dtree; import java.io.DataInput; import java.io.IOException; import org.eclipse.core.internal.utils.Messages; import org.eclipse.core.runtime.*; /** * Class used for reading a single data tree (no parents) from an input stream */ public class DataTreeReader { /** * Callback for reading tree data */ protected IDataFlattener flatener; /** * The stream to read the tree from */ protected DataInput input; /** * Creates a new DeltaTreeReader. */ public DataTreeReader(IDataFlattener f) { flatener = f; } /** * Returns true if the given node type has data. */ protected boolean hasData(int nodeType) { switch (nodeType) { case AbstractDataTreeNode.T_COMPLETE_NODE : case AbstractDataTreeNode.T_DELTA_NODE : return true; case AbstractDataTreeNode.T_DELETED_NODE : case AbstractDataTreeNode.T_NO_DATA_DELTA_NODE : default : return false; } } /** * Reads a node from the given input stream. * If newProjectName is non-empty, use it for the name of * the project (first node under root) in the created node * instead of the name read from the stream. */ protected AbstractDataTreeNode readNode(IPath parentPath, String newProjectName) throws IOException { /* read the node name */ String name = input.readUTF(); /* read the node type */ int nodeType = readNumber(); /* maybe read the data */ IPath path; /* if not the root node */ if (parentPath != null) { if (parentPath.equals(Path.ROOT) && newProjectName.length() > 0 && name.length() > 0) { /* use the supplied name for the project node */ name = newProjectName; } path = parentPath.append(name); } else { path = Path.ROOT; } Object data = null; if (hasData(nodeType)) { /* read flag indicating if the data is null */ int dataFlag = readNumber(); if (dataFlag != 0) { data = flatener.readData(path, input); } } /* read the number of children */ int childCount = readNumber(); /* read the children */ AbstractDataTreeNode[] children; if (childCount == 0) { children = AbstractDataTreeNode.NO_CHILDREN; } else { children = new AbstractDataTreeNode[childCount]; for (int i = 0; i < childCount; i++) { children[i] = readNode(path, newProjectName); } } /* create the appropriate node */ switch (nodeType) { case AbstractDataTreeNode.T_COMPLETE_NODE : return new DataTreeNode(name, data, children); case AbstractDataTreeNode.T_DELTA_NODE : return new DataDeltaNode(name, data, children); case AbstractDataTreeNode.T_DELETED_NODE : return new DeletedNode(name); case AbstractDataTreeNode.T_NO_DATA_DELTA_NODE : return new NoDataDeltaNode(name, children); default : Assert.isTrue(false, Messages.dtree_switchError); return null; } } /** * Reads an integer stored in compact format. Numbers between * 0 and 254 inclusive occupy 1 byte; other numbers occupy 5 bytes, * the first byte being 0xff and the next 4 bytes being the standard * representation of an int. */ protected int readNumber() throws IOException { byte b = input.readByte(); int number = (b & 0xff); // not a no-op! converts unsigned byte to int if (number == 0xff) { // magic escape value number = input.readInt(); } return number; } /** * Reads a DeltaDataTree from the given input stream. * If newProjectName is non-empty, use it for the name of * the project (first node under root) in the returned tree * instead of the name read from the stream. */ public DeltaDataTree readTree(DeltaDataTree parent, DataInput input, String newProjectName) throws IOException { this.input = input; AbstractDataTreeNode root = readNode(Path.ROOT, newProjectName); return new DeltaDataTree(root, parent); } }