/******************************************************************************* * 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 * James Blackburn (Broadcom Corp.) - ongoing development *******************************************************************************/ package org.eclipse.core.internal.resources; import java.io.DataOutputStream; import java.io.IOException; import java.util.*; import org.eclipse.core.internal.watson.IPathRequestor; // public class MarkerWriter { protected MarkerManager manager; // version numbers public static final int MARKERS_SAVE_VERSION = 3; public static final int MARKERS_SNAP_VERSION = 2; // type constants public static final byte INDEX = 1; public static final byte QNAME = 2; // marker attribute types public static final byte ATTRIBUTE_NULL = 0; public static final byte ATTRIBUTE_BOOLEAN = 1; public static final byte ATTRIBUTE_INTEGER = 2; public static final byte ATTRIBUTE_STRING = 3; public MarkerWriter(MarkerManager manager) { super(); this.manager = manager; } /** * Returns an Object array of length 2. The first element is an Integer which is the number * of persistent markers found. The second element is an array of boolean values, with a * value of true meaning that the marker at that index is to be persisted. */ private Object[] filterMarkers(IMarkerSetElement[] markers) { Object[] result = new Object[2]; boolean[] isPersistent = new boolean[markers.length]; int count = 0; for (int i = 0; i < markers.length; i++) { MarkerInfo info = (MarkerInfo) markers[i]; if (manager.isPersistent(info)) { isPersistent[i] = true; count++; } } result[0] = new Integer(count); result[1] = isPersistent; return result; } /** * SAVE_FILE -> VERSION_ID RESOURCE+ * VERSION_ID -> int * RESOURCE -> RESOURCE_PATH MARKERS_SIZE MARKER+ * RESOURCE_PATH -> String * MARKERS_SIZE -> int * MARKER -> MARKER_ID TYPE ATTRIBUTES_SIZE ATTRIBUTE* CREATION_TIME * MARKER_ID -> long * TYPE -> INDEX | QNAME * INDEX -> byte int * QNAME -> byte String * ATTRIBUTES_SIZE -> short * ATTRIBUTE -> ATTRIBUTE_KEY ATTRIBUTE_VALUE * ATTRIBUTE_KEY -> String * ATTRIBUTE_VALUE -> INTEGER_VALUE | BOOLEAN_VALUE | STRING_VALUE | NULL_VALUE * INTEGER_VALUE -> byte int * BOOLEAN_VALUE -> byte boolean * STRING_VALUE -> byte String * NULL_VALUE -> byte * CREATION_TIME -> long * */ public void save(ResourceInfo info, IPathRequestor requestor, DataOutputStream output, List<String> writtenTypes) throws IOException { // phantom resources don't have markers if (info.isSet(ICoreConstants.M_PHANTOM)) return; MarkerSet markers = info.getMarkers(false); if (markers == null) return; IMarkerSetElement[] elements = markers.elements(); // filter out the markers...determine if there are any persistent ones Object[] result = filterMarkers(elements); int count = ((Integer) result[0]).intValue(); if (count == 0) return; // if this is the first set of markers that we have written, then // write the version id for the file. if (output.size() == 0) output.writeInt(MARKERS_SAVE_VERSION); boolean[] isPersistent = (boolean[]) result[1]; output.writeUTF(requestor.requestPath().toString()); output.writeInt(count); for (int i = 0; i < elements.length; i++) if (isPersistent[i]) write((MarkerInfo) elements[i], output, writtenTypes); } /** * Snapshot the markers for the specified resource to the given output stream. * * SNAP_FILE -> [VERSION_ID RESOURCE]* * VERSION_ID -> int (used for backwards compatibiliy) * RESOURCE -> RESOURCE_PATH MARKER_SIZE MARKER+ * RESOURCE_PATH -> String * MARKER_SIZE -> int * MARKER -> MARKER_ID TYPE ATTRIBUTES_SIZE ATTRIBUTE* CREATION_TIME * MARKER_ID -> long * TYPE -> INDEX | QNAME * INDEX -> byte int * QNAME -> byte String * ATTRIBUTES_SIZE -> short * ATTRIBUTE -> ATTRIBUTE_KEY ATTRIBUTE_VALUE * ATTRIBUTE_KEY -> String * ATTRIBUTE_VALUE -> BOOLEAN_VALUE | INTEGER_VALUE | STRING_VALUE | NULL_VALUE * BOOLEAN_VALUE -> byte boolean * INTEGER_VALUE -> byte int * STRING_VALUE -> byte String * NULL_VALUE -> byte * CREATION_TIME -> long */ public void snap(ResourceInfo info, IPathRequestor requestor, DataOutputStream output) throws IOException { // phantom resources don't have markers if (info.isSet(ICoreConstants.M_PHANTOM)) return; if (!info.isSet(ICoreConstants.M_MARKERS_SNAP_DIRTY)) return; MarkerSet markers = info.getMarkers(false); if (markers == null) return; IMarkerSetElement[] elements = markers.elements(); // filter out the markers...determine if there are any persistent ones Object[] result = filterMarkers(elements); int count = ((Integer) result[0]).intValue(); // write the version id for the snapshot. output.writeInt(MARKERS_SNAP_VERSION); boolean[] isPersistent = (boolean[]) result[1]; output.writeUTF(requestor.requestPath().toString()); // always write out the count...even if its zero. this will help // use pick up marker deletions from our snapshot. output.writeInt(count); List<String> writtenTypes = new ArrayList<String>(); for (int i = 0; i < elements.length; i++) if (isPersistent[i]) write((MarkerInfo) elements[i], output, writtenTypes); info.clear(ICoreConstants.M_MARKERS_SNAP_DIRTY); } /* * Write out the given marker attributes to the given output stream. */ private void write(Map<String, Object> attributes, DataOutputStream output) throws IOException { output.writeShort(attributes.size()); for (Map.Entry<String, Object> e : attributes.entrySet()) { String key = e.getKey(); output.writeUTF(key); Object value = e.getValue(); if (value instanceof Integer) { output.writeByte(ATTRIBUTE_INTEGER); output.writeInt(((Integer) value).intValue()); continue; } if (value instanceof Boolean) { output.writeByte(ATTRIBUTE_BOOLEAN); output.writeBoolean(((Boolean) value).booleanValue()); continue; } if (value instanceof String) { output.writeByte(ATTRIBUTE_STRING); output.writeUTF((String) value); continue; } // otherwise we came across an attribute of an unknown type // so just write out null since we don't know how to marshal it. output.writeByte(ATTRIBUTE_NULL); } } private void write(MarkerInfo info, DataOutputStream output, List<String> writtenTypes) throws IOException { output.writeLong(info.getId()); // if we have already written the type once, then write an integer // constant to represent it instead to remove duplication String type = info.getType(); int index = writtenTypes.indexOf(type); if (index == -1) { output.writeByte(QNAME); output.writeUTF(type); writtenTypes.add(type); } else { output.writeByte(INDEX); output.writeInt(index); } // write out the size of the attribute table and // then each attribute. if (info.getAttributes(false) == null) { output.writeShort(0); } else write(info.getAttributes(false), output); // write out the creation time output.writeLong(info.getCreationTime()); } }