ChunkContainerReaderpublic abstract class ChunkContainerReader extends Object implements ChunkReaderThis class represents a reader implementation, which is able to read ASF
objects (chunks) which store other objects (chunks) within them.
|
Fields Summary |
---|
protected static final Logger | LOGGERLogger | public static final int | READ_LIMITWithin this range, a {@link ChunkReader} should be aware if it fails. | protected final boolean | eachChunkOnceIf true each chunk type will only be read once.
| protected boolean | hasFailingReadersIf true due to a {@linkplain #register(Class) registered}
chunk reader, all {@link InputStream} objects passed to
{@link #read(GUID, InputStream, long)} must support mark/reset. | protected final Map | readerMapRegisters GUIDs to their reader classes.
|
Constructors Summary |
---|
protected ChunkContainerReader(List toRegister, boolean readChunkOnce)Creates a reader instance, which only utilizes the given list of chunk
readers.
this.eachChunkOnce = readChunkOnce;
for (final Class<? extends ChunkReader> curr : toRegister) {
register(curr);
}
|
Methods Summary |
---|
protected void | checkStream(java.io.InputStream stream)Checks for the constraints of this class.
if (this.hasFailingReaders && !stream.markSupported()) {
throw new IllegalArgumentException(
"Stream has to support mark/reset.");
}
| protected abstract ChunkType | createContainer(long streamPosition, java.math.BigInteger chunkLength, java.io.InputStream stream)This method is called by {@link #read(GUID, InputStream, long)} in order
to create the resulting object. Implementations of this class should now
return a new instance of their implementation specific result AND
all data should be read, until the list of chunks starts. (The
{@link ChunkContainer#getChunkEnd()} must return a sane result, too)
| protected ChunkReader | getReader(org.jaudiotagger.audio.asf.data.GUID guid)Gets a configured {@linkplain ChunkReader reader} instance for ASF
objects (chunks) with the specified guid .
return this.readerMap.get(guid);
| protected boolean | isReaderAvailable(org.jaudiotagger.audio.asf.data.GUID guid)Tests whether {@link #getReader(GUID)} won't return null .
return this.readerMap.containsKey(guid);
| public ChunkType | read(org.jaudiotagger.audio.asf.data.GUID guid, java.io.InputStream stream, long chunkStart)This Method implements the reading of a chunk container.
checkStream(stream);
final CountingInputStream cis = new CountingInputStream(stream);
if (!Arrays.asList(getApplyingIds()).contains(guid)) {
throw new IllegalArgumentException(
"provided GUID is not supported by this reader.");
}
// For Know the file pointer pointed to an ASF header chunk.
final BigInteger chunkLen = Utils.readBig64(cis);
/*
* now read implementation specific information until the chunk
* collection starts and create the resulting object.
*/
final ChunkType result = createContainer(chunkStart, chunkLen, cis);
// 16 bytes have already been for providing the GUID
long currentPosition = chunkStart + cis.getReadCount() + 16;
final HashSet<GUID> alreadyRead = new HashSet<GUID>();
/*
* Now reading header of chuncks.
*/
while (currentPosition < result.getChunkEnd()) {
final GUID currentGUID = Utils.readGUID(cis);
final boolean skip = this.eachChunkOnce
&& (!isReaderAvailable(currentGUID) || !alreadyRead
.add(currentGUID));
Chunk chunk;
/*
* If one reader tells it could fail (new method), then check the
* input stream for mark/reset. And use it if failed.
*/
if (!skip && isReaderAvailable(currentGUID)) {
final ChunkReader reader = getReader(currentGUID);
if (reader.canFail()) {
cis.mark(READ_LIMIT);
}
chunk = getReader(currentGUID).read(currentGUID, cis,
currentPosition);
} else {
chunk = ChunkHeaderReader.getInstance().read(currentGUID, cis,
currentPosition);
}
if (chunk == null) {
/*
* Reader failed
*/
cis.reset();
} else {
if (!skip) {
result.addChunk(chunk);
}
currentPosition = chunk.getChunkEnd();
// Always take into account, that 16 bytes have been read prior
// to calling this method
assert cis.getReadCount() + chunkStart + 16 == currentPosition;
}
}
return result;
| private void | register(java.lang.Class toRegister)Registers the given reader.
try {
final T reader = toRegister.newInstance();
for (final GUID curr : reader.getApplyingIds()) {
this.readerMap.put(curr, reader);
}
} catch (InstantiationException e) {
LOGGER.severe(e.getMessage());
} catch (IllegalAccessException e) {
LOGGER.severe(e.getMessage());
}
|
|