package org.okip.service.filing.impl.rfs;
import org.okip.service.filing.api.*;
/**
Copyright (c) 2002 Massachusetts Institute of Technology
This work, including software, documents, or other related items (the
"Software"), is being provided by the copyright holder(s) subject to
the terms of the MIT OKI API Implementation License. By
obtaining, using and/or copying this Software, you agree that you have
read, understand, and will comply with the following terms and
conditions of the MIT OKI API Implementation License:
Permission to use, copy, modify, and distribute this Software and its
documentation, with or without modification, for any purpose and
without fee or royalty is hereby granted, provided that you include
the following on ALL copies of the Software or portions thereof,
including modifications or derivatives, that you make:
* The full text of the MIT OKI API Implementation License in a
location viewable to users of the redistributed or derivative
work.
* Any pre-existing intellectual property disclaimers, notices, or
terms and conditions. If none exist, a short notice similar to the
following should be used within the body of any redistributed or
derivative Software:
"Copyright (c) 2002 Massachusetts Institute of Technology
All Rights Reserved."
* Notice of any changes or modifications to the MIT OKI
Software, including the date the changes were made. Any modified
software must be distributed in such as manner as to avoid any
confusion with the original MIT OKI Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The name and trademarks of copyright holder(s) and/or MIT may NOT be
used in advertising or publicity pertaining to the Software without
specific, written prior permission. Title to copyright in the Software
and any associated documentation will at all times remain with the
copyright holders.
The export of software employing encryption technology may require a
specific license from the United States Government. It is the
responsibility of any person or organization contemplating export to
obtain such a license before exporting this Software.
*/
/*
* $Source: /home/svn/cvs2svn-2.1.1/at-cvs-repo/VUE2/src/oki/old/filing/RfsInputBuffer.java,v $
*/
/**
* RFS Input Buffer. Obtains and holds a chunk of file data,
* either locally or remotely.
* <p>
* Licensed under the {@link org.okip.service.ApiImplementationLicenseMIT MIT OKI API Implementation License}.
*
* @version $Revision: 1.1 $ / $Date: 2003-04-14 20:48:28 $
*/
public class RfsInputBuffer
implements java.io.Serializable
{
private String idStr = null;
private long startPos = -1;
private int maxSize = -1;
private transient RfsFactory factory = null;
private transient java.io.FileInputStream fileInputStream = null;
private transient DataBlock dataBlock;
private transient byte[] buffer;
private transient long openedStart = -1;
protected RfsInputBuffer(RfsFactory factory, String idStr, long startPos, int maxSize)
throws FilingException
{
if (factory == null || idStr == null || startPos < 0 || maxSize <= 0)
throw new FilingException("Create RfsInputBuffer failed: bad argument(s)");
this.factory = factory;
this.idStr = idStr;
this.startPos = startPos;
this.maxSize = maxSize;
}
public void setStartPosition(long startPosition)
{
this.startPos = startPosition;
}
private void getInputStream()
throws FilingException
{
try {
if (this.fileInputStream == null) {
this.fileInputStream = new java.io.FileInputStream(this.idStr);
openedStart = startPos;
if (startPos > 0) {
long skipped;
try {
skipped = this.fileInputStream.skip(startPos);
} catch (java.io.IOException e) {
throw new FilingException(e);
}
if (skipped < startPos)
throw new FilingIOException("skipped " + skipped + " of " + startPos + " bytes");
}
}
} catch (java.io.FileNotFoundException e) {
throw new NotFoundException(e, this.idStr);
}
if (startPos != openedStart)
throw new FilingIOException("RfsInputBuffer internal error: startPos "
+ startPos + " != openedStart " + openedStart);
}
public DataBlock readBuffer()
throws FilingException
{
if (factory != null && factory.getClient() != null)
return (DataBlock) factory.invoke(this, "readBufferRemotely");
else
return readBufferLocally();
}
private DataBlock getDataBlock(int size)
throws FilingException
{
// the way we manage DataBlocks may look a bit
// odd as we're trying to help out the garbage
// collector a little as we're dealing with
// large chunks of memory.
if (buffer == null || size > buffer.length)
buffer = new byte[size];
if (dataBlock != null) {
dataBlock.buf = buffer;
dataBlock.length = size;
} else
dataBlock = new DataBlock(buffer, size);
return dataBlock;
}
public DataBlock readBufferRemotely()
throws FilingException
{
DataBlock dataBlock = readBufferLocally();
/* Closing the stream is going to null out our dataBlock, so
* make a shallow copy here just before returning. */
if (dataBlock != null)
dataBlock = dataBlock.copy();
/* We close the file after each use -- we cannot maintain
* state -- we have to re-initialize again at next RMI call.
* This is a kindness to the server only and could be skipped
* for a miniscule response-time improvement. */
close();
return dataBlock;
}
private DataBlock readBufferLocally()
throws FilingException
{
getInputStream();
try {
int available = this.fileInputStream.available();
int requestSize;
if (available <= 0)
requestSize = this.maxSize;// it's going to block anyway, so just go for it
else
requestSize = available;
if (requestSize > this.maxSize)
requestSize = this.maxSize;
getDataBlock(requestSize);
int got = this.fileInputStream.read(dataBlock.buf, 0, dataBlock.length);
if (got <= 0) {
this.dataBlock.buf = null;
this.dataBlock = null;
} else if (got < requestSize)
this.dataBlock.length = got;
if (got == available) {
// we got all we could -- check to see if we hit EOF
if (startPos + got == RfsEntry.getEntryFile(idStr, false).length())
this.dataBlock.containsEOF = true;
}
return this.dataBlock;
} catch (FilingException fe) {
throw fe;
} catch (Exception e) {
throw new FilingException(e);
}
}
protected void close()
throws FilingException
{
buffer = null;
if (dataBlock != null) {
dataBlock.buf = null;
dataBlock = null;
}
try {
if (fileInputStream != null) {
fileInputStream.close();
fileInputStream = null;
}
} catch (Exception e) {
throw new FilingException(e, "close " + idStr);
}
}
public void finalize()
{
try {
close();
} catch(Exception e) {}
}
public String toString()
{
return "RfsInputBuffer[" + idStr + "] p="+startPos;
}
}