/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.core.journal;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import org.apache.jackrabbit.spi.Name;
import java.io.DataInputStream;
import java.io.IOException;
/**
* Record used for reading.
*/
public class ReadRecord extends AbstractRecord {
/**
* This record's journal id.
*/
private final String journalId;
/**
* This record's producer id.
*/
private final String producerId;
/**
* This record's revision.
*/
private final long revision;
/**
* Underlying data input.
*/
private final DataInputStream dataIn;
/**
* This record's length.
*/
private final int length;
/**
* Flag indicating whether this record was consumed.
*/
private boolean consumed;
/**
* Create a new instance of this class.
*/
public ReadRecord(String journalId, String producerId,
long revision, DataInputStream dataIn, int length,
NamespaceResolver resolver, NamePathResolver npResolver) {
super(resolver, npResolver);
this.journalId = journalId;
this.producerId = producerId;
this.revision = revision;
this.dataIn = dataIn;
this.length = length;
}
/**
* {@inheritDoc}
*/
public String getJournalId() {
return journalId;
}
/**
* {@inheritDoc}
*/
public String getProducerId() {
return producerId;
}
/**
* {@inheritDoc}
*/
public long getRevision() {
return revision;
}
/**
* {@inheritDoc}
*/
public byte readByte() throws JournalException {
consumed = true;
try {
return dataIn.readByte();
} catch (IOException e) {
String msg = "I/O error while reading byte.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public char readChar() throws JournalException {
consumed = true;
try {
return dataIn.readChar();
} catch (IOException e) {
String msg = "I/O error while reading character.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public boolean readBoolean() throws JournalException {
consumed = true;
try {
return dataIn.readBoolean();
} catch (IOException e) {
String msg = "I/O error while reading boolean.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public int readInt() throws JournalException {
consumed = true;
try {
return dataIn.readInt();
} catch (IOException e) {
String msg = "I/O error while reading integer.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public long readLong() throws JournalException {
consumed = true;
try {
return dataIn.readLong();
} catch (IOException e) {
String msg = "I/O error while reading long.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public String readString() throws JournalException {
consumed = true;
try {
boolean isNull = dataIn.readBoolean();
if (isNull) {
return null;
} else {
return dataIn.readUTF();
}
} catch (IOException e) {
String msg = "I/O error while reading string.";
throw new JournalException(msg, e);
}
}
/**
* {@inheritDoc}
*/
public void readFully(byte[] b) throws JournalException {
consumed = true;
try {
dataIn.readFully(b);
} catch (IOException e) {
String msg = "I/O error while reading byte array.";
throw new JournalException(msg, e);
}
}
/**
* Close this record, eventually skipping unconsumed bytes.
*
* @throws IOException if an I/O error occurs
*/
public void close() throws IOException {
if (length != 0) {
if (!consumed) {
skip(length);
}
} else {
dataIn.close();
}
}
/**
* Skip exactly <code>n</code> bytes. Throws if less bytes are skipped.
*
* @param n bytes to skip
* @throws IOException if an I/O error occurs, or less than
* <code>n</code> bytes were skipped.
*/
private void skip(long n) throws IOException {
long skiplen = n;
while (skiplen > 0) {
long skipped = dataIn.skip(skiplen);
if (skipped <= 0) {
break;
}
skiplen -= skipped;
}
if (skiplen != 0) {
String msg = "Should have skipped " + n
+ " bytes, only " + (n - skiplen) + " skipped.";
throw new IOException(msg);
}
}
/**
* Unsupported methods when appending.
*/
public void writeByte(int n) throws JournalException {
throw unsupported();
}
public void writeChar(char c) throws JournalException {
throw unsupported();
}
public void writeBoolean(boolean b) throws JournalException {
throw unsupported();
}
public void writeInt(int n) throws JournalException {
throw unsupported();
}
public void writeLong(long n) throws JournalException {
throw unsupported();
}
public void writeString(String s) throws JournalException {
throw unsupported();
}
public void writeQName(Name name) throws JournalException {
throw unsupported();
}
public void write(byte[] b) throws JournalException {
throw unsupported();
}
public long update() throws JournalException {
throw unsupported();
}
public void cancelUpdate() {
}
private JournalException unsupported() {
String msg = "Record has been opened read-only.";
return new JournalException(msg);
}
}