Line data Source code
1 : // Copyright (C) 2016 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.notedb; 16 : 17 : import static com.google.common.base.Preconditions.checkState; 18 : import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; 19 : 20 : import com.google.common.collect.ImmutableList; 21 : import com.google.gerrit.common.UsedAt; 22 : import java.io.IOException; 23 : import java.util.List; 24 : import org.eclipse.jgit.errors.ConfigInvalidException; 25 : import org.eclipse.jgit.lib.ObjectId; 26 : import org.eclipse.jgit.lib.ObjectReader; 27 : import org.eclipse.jgit.util.MutableInteger; 28 : 29 : /** 30 : * Data stored in a note, parsed on demand. The data type to parse into is a generic list of type T. 31 : * The source of the data is a array of raw bytes 32 : */ 33 : @UsedAt(UsedAt.Project.PLUGIN_CHECKS) 34 : public abstract class RevisionNote<T> { 35 : static final int MAX_NOTE_SZ = 25 << 20; 36 : 37 : protected static void trimLeadingEmptyLines(byte[] bytes, MutableInteger p) { 38 64 : while (p.value < bytes.length && bytes[p.value] == '\n') { 39 0 : p.value++; 40 : } 41 64 : } 42 : 43 : private final ObjectReader reader; 44 : private final ObjectId noteId; 45 : 46 : private byte[] raw; 47 : private ImmutableList<T> entities; 48 : 49 64 : public RevisionNote(ObjectReader reader, ObjectId noteId) { 50 64 : this.reader = reader; 51 64 : this.noteId = noteId; 52 64 : } 53 : 54 : public byte[] getRaw() { 55 28 : checkParsed(); 56 28 : return raw; 57 : } 58 : 59 : @UsedAt(UsedAt.Project.PLUGIN_CHECKS) 60 : public T getOnlyEntity() { 61 0 : checkParsed(); 62 0 : checkState(entities.size() == 1, "expected exactly one entity"); 63 0 : return entities.get(0); 64 : } 65 : 66 : public ImmutableList<T> getEntities() { 67 64 : checkParsed(); 68 64 : return entities; 69 : } 70 : 71 : /** Reads the raw data, and delegates parsing to the {@link #parse(byte[], int)} method. */ 72 : public void parse() throws IOException, ConfigInvalidException { 73 64 : raw = reader.open(noteId, OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ); 74 64 : MutableInteger p = new MutableInteger(); 75 64 : trimLeadingEmptyLines(raw, p); 76 64 : if (p.value >= raw.length) { 77 0 : entities = ImmutableList.of(); 78 0 : return; 79 : } 80 : 81 64 : entities = ImmutableList.copyOf(parse(raw, p.value)); 82 64 : } 83 : 84 : protected abstract List<T> parse(byte[] raw, int offset) 85 : throws IOException, ConfigInvalidException; 86 : 87 : protected void checkParsed() { 88 64 : checkState(raw != null, "revision note not parsed yet"); 89 64 : } 90 : }