/*
* 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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.DataInputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.NoSuchElementException;
/**
* RecordIterator interface.
*/
class DatabaseRecordIterator implements RecordIterator {
/**
* Logger.
*/
private static Logger log = LoggerFactory.getLogger(DatabaseRecordIterator.class);
/**
* Underlying result set.
*/
private final ResultSet rs;
/**
* Namespace resolver.
*/
private final NamespaceResolver resolver;
/**
* Name and Path resolver.
*/
private final NamePathResolver npResolver;
/**
* Current record.
*/
private ReadRecord record;
/**
* Last record returned.
*/
private ReadRecord lastRecord;
/**
* Flag indicating whether EOF was reached.
*/
private boolean isEOF;
/**
* Create a new instance of this class.
*/
public DatabaseRecordIterator(ResultSet rs, NamespaceResolver resolver, NamePathResolver npResolver) {
this.rs = rs;
this.resolver = resolver;
this.npResolver = npResolver;
}
/**
* {@inheritDoc}
*/
public boolean hasNext() {
try {
if (!isEOF && record == null) {
fetchRecord();
}
return !isEOF;
} catch (SQLException e) {
String msg = "Error while moving to next record.";
log.error(msg, e);
return false;
}
}
/**
* Return the next record. If there are no more records, throws
* a <code>NoSuchElementException</code>. If an error occurs,
* throws a <code>JournalException</code>.
*
* @return next record
* @throws java.util.NoSuchElementException if there are no more records
* @throws JournalException if another error occurs
*/
public Record nextRecord() throws NoSuchElementException, JournalException {
if (!hasNext()) {
String msg = "No current record.";
throw new NoSuchElementException(msg);
}
close(lastRecord);
lastRecord = record;
record = null;
return lastRecord;
}
/**
* {@inheritDoc}
*/
public void close() {
if (lastRecord != null) {
close(lastRecord);
lastRecord = null;
}
try {
rs.close();
} catch (SQLException e) {
String msg = "Error while closing result set: " + e.getMessage();
log.warn(msg);
}
}
/**
* Fetch the next record.
*/
private void fetchRecord() throws SQLException {
if (rs.next()) {
long revision = rs.getLong(1);
String journalId = rs.getString(2);
String producerId = rs.getString(3);
DataInputStream dataIn = new DataInputStream(rs.getBinaryStream(4));
record = new ReadRecord(journalId, producerId, revision, dataIn, 0, resolver, npResolver);
} else {
isEOF = true;
}
}
/**
* Close a record.
*
* @param record record
*/
private static void close(ReadRecord record) {
if (record != null) {
try {
record.close();
} catch (IOException e) {
String msg = "Error while closing record.";
log.warn(msg, e);
}
}
}
}