/*
 * Copyright (C) 2010, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.notes;

import java.io.IOException;
import java.util.Iterator;

import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;

Index of notes from a note branch. This class is not thread-safe, and relies on an ObjectReader that it borrows/shares with the caller. The reader can be used during any call, and is not released by this class. The caller should arrange for releasing the shared ObjectReader at the proper times.
/** * Index of notes from a note branch. * * This class is not thread-safe, and relies on an * {@link org.eclipse.jgit.lib.ObjectReader} that it borrows/shares with the * caller. The reader can be used during any call, and is not released by this * class. The caller should arrange for releasing the shared * {@code ObjectReader} at the proper times. */
public class NoteMap implements Iterable<Note> {
Construct a new empty note map.
Returns:an empty note map.
/** * Construct a new empty note map. * * @return an empty note map. */
public static NoteMap newEmptyMap() { NoteMap r = new NoteMap(null /* no reader */); r.root = new LeafBucket(0); return r; }
Shorten the note ref name by trimming off the Constants.R_NOTES prefix if it exists.
Params:
  • noteRefName – a String object.
Returns:a more user friendly note name
/** * Shorten the note ref name by trimming off the * {@link org.eclipse.jgit.lib.Constants#R_NOTES} prefix if it exists. * * @param noteRefName * a {@link java.lang.String} object. * @return a more user friendly note name */
public static String shortenRefName(String noteRefName) { if (noteRefName.startsWith(Constants.R_NOTES)) return noteRefName.substring(Constants.R_NOTES.length()); return noteRefName; }
Load a collection of notes from a branch.
Params:
  • reader – reader to scan the note branch with. This reader may be retained by the NoteMap for the life of the map in order to support lazy loading of entries.
  • commit – the revision of the note branch to read.
Throws:
Returns:the note map read from the commit.
/** * Load a collection of notes from a branch. * * @param reader * reader to scan the note branch with. This reader may be * retained by the NoteMap for the life of the map in order to * support lazy loading of entries. * @param commit * the revision of the note branch to read. * @return the note map read from the commit. * @throws java.io.IOException * the repository cannot be accessed through the reader. * @throws org.eclipse.jgit.errors.CorruptObjectException * a tree object is corrupt and cannot be read. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException * a tree object wasn't actually a tree. * @throws org.eclipse.jgit.errors.MissingObjectException * a reference tree object doesn't exist. */
public static NoteMap read(ObjectReader reader, RevCommit commit) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { return read(reader, commit.getTree()); }
Load a collection of notes from a tree.
Params:
  • reader – reader to scan the note branch with. This reader may be retained by the NoteMap for the life of the map in order to support lazy loading of entries.
  • tree – the note tree to read.
Throws:
Returns:the note map read from the tree.
/** * Load a collection of notes from a tree. * * @param reader * reader to scan the note branch with. This reader may be * retained by the NoteMap for the life of the map in order to * support lazy loading of entries. * @param tree * the note tree to read. * @return the note map read from the tree. * @throws java.io.IOException * the repository cannot be accessed through the reader. * @throws org.eclipse.jgit.errors.CorruptObjectException * a tree object is corrupt and cannot be read. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException * a tree object wasn't actually a tree. * @throws org.eclipse.jgit.errors.MissingObjectException * a reference tree object doesn't exist. */
public static NoteMap read(ObjectReader reader, RevTree tree) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { return readTree(reader, tree); }
Load a collection of notes from a tree.
Params:
  • reader – reader to scan the note branch with. This reader may be retained by the NoteMap for the life of the map in order to support lazy loading of entries.
  • treeId – the note tree to read.
Throws:
Returns:the note map read from the tree.
/** * Load a collection of notes from a tree. * * @param reader * reader to scan the note branch with. This reader may be * retained by the NoteMap for the life of the map in order to * support lazy loading of entries. * @param treeId * the note tree to read. * @return the note map read from the tree. * @throws java.io.IOException * the repository cannot be accessed through the reader. * @throws org.eclipse.jgit.errors.CorruptObjectException * a tree object is corrupt and cannot be read. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException * a tree object wasn't actually a tree. * @throws org.eclipse.jgit.errors.MissingObjectException * a reference tree object doesn't exist. */
public static NoteMap readTree(ObjectReader reader, ObjectId treeId) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { NoteMap map = new NoteMap(reader); map.load(treeId); return map; }
Construct a new note map from an existing note bucket.
Params:
  • root – the root bucket of this note map
  • reader – reader to scan the note branch with. This reader may be retained by the NoteMap for the life of the map in order to support lazy loading of entries.
Returns:the note map built from the note bucket
/** * Construct a new note map from an existing note bucket. * * @param root * the root bucket of this note map * @param reader * reader to scan the note branch with. This reader may be * retained by the NoteMap for the life of the map in order to * support lazy loading of entries. * @return the note map built from the note bucket */
static NoteMap newMap(InMemoryNoteBucket root, ObjectReader reader) { NoteMap map = new NoteMap(reader); map.root = root; return map; }
Borrowed reader to access the repository.
/** Borrowed reader to access the repository. */
private final ObjectReader reader;
All of the notes that have been loaded.
/** All of the notes that have been loaded. */
private InMemoryNoteBucket root; private NoteMap(ObjectReader reader) { this.reader = reader; }
{@inheritDoc}
/** {@inheritDoc} */
@Override public Iterator<Note> iterator() { try { return root.iterator(new MutableObjectId(), reader); } catch (IOException e) { throw new RuntimeException(e); } }
Lookup a note for a specific ObjectId.
Params:
  • id – the object to look for.
Throws:
  • IOException – a portion of the note space is not accessible.
Returns:the note's blob ObjectId, or null if no note exists.
/** * Lookup a note for a specific ObjectId. * * @param id * the object to look for. * @return the note's blob ObjectId, or null if no note exists. * @throws java.io.IOException * a portion of the note space is not accessible. */
public ObjectId get(AnyObjectId id) throws IOException { Note n = root.getNote(id, reader); return n == null ? null : n.getData(); }
Lookup a note for a specific ObjectId.
Params:
  • id – the object to look for.
Throws:
  • IOException – a portion of the note space is not accessible.
Returns:the note for the given object id, or null if no note exists.
/** * Lookup a note for a specific ObjectId. * * @param id * the object to look for. * @return the note for the given object id, or null if no note exists. * @throws java.io.IOException * a portion of the note space is not accessible. */
public Note getNote(AnyObjectId id) throws IOException { return root.getNote(id, reader); }
Determine if a note exists for the specified ObjectId.
Params:
  • id – the object to look for.
Throws:
  • IOException – a portion of the note space is not accessible.
Returns:true if a note exists; false if there is no note.
/** * Determine if a note exists for the specified ObjectId. * * @param id * the object to look for. * @return true if a note exists; false if there is no note. * @throws java.io.IOException * a portion of the note space is not accessible. */
public boolean contains(AnyObjectId id) throws IOException { return get(id) != null; }
Open and return the content of an object's note. This method assumes the note is fairly small and can be accessed efficiently. Larger notes should be accessed by streaming:
ObjectId dataId = thisMap.get(id);
if (dataId != null)
	reader.open(dataId).openStream();
Params:
  • id – object to lookup the note of.
  • sizeLimit – maximum number of bytes to return. If the note data size is larger than this limit, LargeObjectException will be thrown.
Throws:
Returns:if a note is defined for id, the note content. If no note is defined, null.
/** * Open and return the content of an object's note. * * This method assumes the note is fairly small and can be accessed * efficiently. Larger notes should be accessed by streaming: * * <pre> * ObjectId dataId = thisMap.get(id); * if (dataId != null) * reader.open(dataId).openStream(); * </pre> * * @param id * object to lookup the note of. * @param sizeLimit * maximum number of bytes to return. If the note data size is * larger than this limit, LargeObjectException will be thrown. * @return if a note is defined for {@code id}, the note content. If no note * is defined, null. * @throws org.eclipse.jgit.errors.LargeObjectException * the note data is larger than {@code sizeLimit}. * @throws org.eclipse.jgit.errors.MissingObjectException * the note's blob does not exist in the repository. * @throws java.io.IOException * the note's blob cannot be read from the repository */
public byte[] getCachedBytes(AnyObjectId id, int sizeLimit) throws LargeObjectException, MissingObjectException, IOException { ObjectId dataId = get(id); if (dataId != null) return reader.open(dataId).getCachedBytes(sizeLimit); else return null; }
Attach (or remove) a note on an object. If no note exists, a new note is stored. If a note already exists for the given object, it is replaced (or removed). This method only updates the map in memory. If the caller wants to attach a UTF-8 encoded string message to an object, set(AnyObjectId, String, ObjectInserter) is a convenient way to encode and update a note in one step.
Params:
  • noteOn – the object to attach the note to. This same ObjectId can later be used as an argument to get(AnyObjectId) or getCachedBytes(AnyObjectId, int) to read back the noteData.
  • noteData – data to associate with the note. This must be the ObjectId of a blob that already exists in the repository. If null the note will be deleted, if present.
Throws:
  • IOException – a portion of the note space is not accessible.
/** * Attach (or remove) a note on an object. * * If no note exists, a new note is stored. If a note already exists for the * given object, it is replaced (or removed). * * This method only updates the map in memory. * * If the caller wants to attach a UTF-8 encoded string message to an * object, {@link #set(AnyObjectId, String, ObjectInserter)} is a convenient * way to encode and update a note in one step. * * @param noteOn * the object to attach the note to. This same ObjectId can later * be used as an argument to {@link #get(AnyObjectId)} or * {@link #getCachedBytes(AnyObjectId, int)} to read back the * {@code noteData}. * @param noteData * data to associate with the note. This must be the ObjectId of * a blob that already exists in the repository. If null the note * will be deleted, if present. * @throws java.io.IOException * a portion of the note space is not accessible. */
public void set(AnyObjectId noteOn, ObjectId noteData) throws IOException { InMemoryNoteBucket newRoot = root.set(noteOn, noteData, reader); if (newRoot == null) { newRoot = new LeafBucket(0); newRoot.nonNotes = root.nonNotes; } root = newRoot; }
Attach a note to an object. If no note exists, a new note is stored. If a note already exists for the given object, it is replaced (or removed).
Params:
  • noteOn – the object to attach the note to. This same ObjectId can later be used as an argument to get(AnyObjectId) or getCachedBytes(AnyObjectId, int) to read back the noteData.
  • noteData – text to store in the note. The text will be UTF-8 encoded when stored in the repository. If null the note will be deleted, if the empty string a note with the empty string will be stored.
  • ins – inserter to write the encoded noteData out as a blob. The caller must ensure the inserter is flushed before the updated note map is made available for reading.
Throws:
  • IOException – the note data could not be stored in the repository.
/** * Attach a note to an object. * * If no note exists, a new note is stored. If a note already exists for the * given object, it is replaced (or removed). * * @param noteOn * the object to attach the note to. This same ObjectId can later * be used as an argument to {@link #get(AnyObjectId)} or * {@link #getCachedBytes(AnyObjectId, int)} to read back the * {@code noteData}. * @param noteData * text to store in the note. The text will be UTF-8 encoded when * stored in the repository. If null the note will be deleted, if * the empty string a note with the empty string will be stored. * @param ins * inserter to write the encoded {@code noteData} out as a blob. * The caller must ensure the inserter is flushed before the * updated note map is made available for reading. * @throws java.io.IOException * the note data could not be stored in the repository. */
public void set(AnyObjectId noteOn, String noteData, ObjectInserter ins) throws IOException { ObjectId dataId; if (noteData != null) { byte[] dataUTF8 = Constants.encode(noteData); dataId = ins.insert(Constants.OBJ_BLOB, dataUTF8); } else { dataId = null; } set(noteOn, dataId); }
Remove a note from an object. If no note exists, no action is performed. This method only updates the map in memory.
Params:
  • noteOn – the object to remove the note from.
Throws:
  • IOException – a portion of the note space is not accessible.
/** * Remove a note from an object. * * If no note exists, no action is performed. * * This method only updates the map in memory. * * @param noteOn * the object to remove the note from. * @throws java.io.IOException * a portion of the note space is not accessible. */
public void remove(AnyObjectId noteOn) throws IOException { set(noteOn, null); }
Write this note map as a tree.
Params:
  • inserter – inserter to use when writing trees to the object database. Caller is responsible for flushing the inserter before trying to read the objects, or exposing them through a reference.
Throws:
Returns:the top level tree.
/** * Write this note map as a tree. * * @param inserter * inserter to use when writing trees to the object database. * Caller is responsible for flushing the inserter before trying * to read the objects, or exposing them through a reference. * @return the top level tree. * @throws java.io.IOException * a tree could not be written. */
public ObjectId writeTree(ObjectInserter inserter) throws IOException { return root.writeTree(inserter); }
Returns:the root note bucket
/** @return the root note bucket */
InMemoryNoteBucket getRoot() { return root; } private void load(ObjectId rootTree) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { AbbreviatedObjectId none = AbbreviatedObjectId.fromString(""); //$NON-NLS-1$ root = NoteParser.parse(none, rootTree, reader); } }