Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  jDTAUS Core Utilities
   *  Copyright (c) 2005 Christian Schulte
   *
   *  Christian Schulte, Haldener Strasse 72, 58095 Hagen, Germany
   *  <cs@jdtaus.org> (+49 2331 3543887)
   *
   *  This library is free software; you can redistribute it and/or
   *  modify it under the terms of the GNU Lesser General Public
  *  License as published by the Free Software Foundation; either
  *  version 2.1 of the License, or any later version.
  *
  *  This library is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  *  Lesser General Public License for more details.
  *
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this library; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
 package org.jdtaus.core.io.util;
 
 import  org.jdtaus.core.container.ContainerFactory;
 import  org.jdtaus.core.container.ContextFactory;
 import  org.jdtaus.core.container.ContextInitializer;
 import  org.jdtaus.core.container.Implementation;
 import  org.jdtaus.core.container.ModelFactory;
 import  org.jdtaus.core.container.Properties;
 import  org.jdtaus.core.container.Property;
 import  org.jdtaus.core.container.PropertyException;
 import  org.jdtaus.core.io.FileOperations;
 import  org.jdtaus.core.lang.spi.MemoryManager;

Read-ahead FileOperations cache.

This implementation implements a read-ahead cache for FileOperations implementations. The cache is controlled by configuration property cacheSize holding the number of bytes to read-ahead. By default property cacheSize is initialized to 16384 leading to a cache size of 16 kB. All memory is allocated during instantiation so that an OutOfMemoryError may be thrown when constructing the cache but not when working with the instance.

Note:
This implementation is not thread-safe and concurrent changes to the underlying FileOperations implementation are not supported.

Author(s):
Christian Schulte
Version:
$Id: ReadAheadFileOperations.java 5034 2008-07-04 11:04:09Z schulte2005 $
 
 public final class ReadAheadFileOperations implements FlushableFileOperations
 {
     //--Implementation----------------------------------------------------------
 
 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausImplementation
     // This section is managed by jdtaus-container-mojo.
 
    
Meta-data describing the implementation.
 
     private static final Implementation META =
         ModelFactory.getModel().getModules().
         getImplementation(ReadAheadFileOperations.class.getName());
 // </editor-fold>//GEN-END:jdtausImplementation
 
     //----------------------------------------------------------Implementation--
     //--Constructors------------------------------------------------------------
 
 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors
     // This section is managed by jdtaus-container-mojo.
 
    
Initializes the properties of the instance.

Parameters:
meta the property values to initialize the instance with.
Throws:
NullPointerException if meta is null.
 
     private void initializeProperties(final Properties meta)
     {
         Property p;
 
         if(meta == null)
         {
             throw new NullPointerException("meta");
         }
 
         p = meta.getProperty("cacheSize");
         this. = ((java.lang.Integerp.getValue()).intValue();
 
     }
 // </editor-fold>//GEN-END:jdtausConstructors
 
     //------------------------------------------------------------Constructors--
     //--Dependencies------------------------------------------------------------
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
    // This section is managed by jdtaus-container-mojo.

    
Configured MemoryManager implementation.
    private transient MemoryManager dMemoryManager;

    
Gets the configured MemoryManager implementation.

Returns:
the configured MemoryManager implementation.
    private MemoryManager getMemoryManager()
    {
        MemoryManager ret = null;
        if(this. != null)
        {
            ret = this.;
        }
        else
        {
            ret = (MemoryManager) ContainerFactory.getContainer().
                getDependency(ReadAheadFileOperations.class,
                "MemoryManager");
            if(ModelFactory.getModel().getModules().
                getImplementation(ReadAheadFileOperations.class.getName()).
                getDependencies().getDependency("MemoryManager").
                isBound())
            {
                this. = ret;
            }
        }
        if(ret instanceof ContextInitializer && !((ContextInitializer) ret).
            isInitialized(ContextFactory.getContext()))
        {
            ((ContextInitializer) ret).initialize(ContextFactory.getContext());
        }
        return ret;
    }
// </editor-fold>//GEN-END:jdtausDependencies
    //------------------------------------------------------------Dependencies--
    //--Properties--------------------------------------------------------------
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
    // This section is managed by jdtaus-container-mojo.

    
Property cacheSize.

Serial:
    private int pCacheSize;

    
Gets the value of property cacheSize.

Returns:
the value of property cacheSize.
    public int getCacheSize()
    {
        return this.;
    }
// </editor-fold>//GEN-END:jdtausProperties
    //--------------------------------------------------------------Properties--
    //--FileOperations----------------------------------------------------------
    public long getLength() throws IOException
    {
        this.assertNotClosed();
        return this..getLength();
    }
    public void setLengthfinal long newLength ) throws IOException
    {
        this.assertNotClosed();
        final long oldLength = this.getLength();
        this..setLength( newLength );
        if ( this. > newLength )
        {
            this. = newLength;
        }
        if ( oldLength > newLength && this. !=  &&
            this. + this. >= newLength )
        { // Discard the end of file cache.
            this. = ;
        }
    }
    public long getFilePointer() throws IOException
    {
        this.assertNotClosed();
        return this.;
    }
    public void setFilePointerfinal long pos ) throws IOException
    {
        this.assertNotClosed();
        this. = pos;
    }
    public int readfinal byte[] bufint offint len )
        throws IOException
    {
        if ( buf == null )
        {
            throw new NullPointerException"buf" );
        }
        if ( off < 0 )
        {
            throw new IndexOutOfBoundsException( Integer.toStringoff ) );
        }
        if ( len < 0 )
        {
            throw new IndexOutOfBoundsException( Integer.toStringlen ) );
        }
        if ( off + len > buf.length )
        {
            throw new IndexOutOfBoundsException( Integer.toStringoff + len ) );
        }
        this.assertNotClosed();
        int read = FileOperations.EOF;
        final long fileLength = this.getLength();
        if ( len == 0 )
        {
            read = 0;
        }
        else if ( this. < fileLength )
        {
            if ( this. ==  ||
                !( this. >= this. &&
                this. < this. + this. ) )
            { // Cache not initialized or file pointer outside the cached area.
                this.fillCache();
            }
            final long cacheStart = this. - this.;
            assert cacheStart <= . :
                "Unexpected implementation limit reached.";
            final int cachedLength = len > this. -
                ( int ) cacheStart
                ? this. - ( int ) cacheStart
                : len;
            System.arraycopythis., ( int ) cacheStartbufoff,
                              cachedLength );
            len -= cachedLength;
            off += cachedLength;
            read = cachedLength;
            this. += cachedLength;
        }
        return read;
    }
    public void writefinal byte[] buffinal int offfinal int len )
        throws IOException
    {
        if ( buf == null )
        {
            throw new NullPointerException"buf" );
        }
        if ( off < 0 )
        {
            throw new IndexOutOfBoundsException( Integer.toStringoff ) );
        }
        if ( len < 0 )
        {
            throw new IndexOutOfBoundsException( Integer.toStringlen ) );
        }
        if ( off + len > buf.length )
        {
            throw new IndexOutOfBoundsException( Integer.toStringoff + len ) );
        }
        this.assertNotClosed();
        if ( this. !=  &&
            this. >= this. &&
            this. < this. + this. )
        { // Cache needs updating.
            final long cacheStart = this. - this.;
            assert cacheStart <= . :
                "Unexpected implementation limit reached.";
            final int cachedLength = len > this. -
                ( int ) cacheStart
                ? this. - ( int ) cacheStart
                : len;
            System.arraycopybufoffthis., ( int ) cacheStart,
                              cachedLength );
        }
        this..setFilePointer( this. );
        this..write( bufofflen );
        this. += len;
    }
    public void readfinal OutputStream out ) throws IOException
    {
        this.assertNotClosed();
        this..read( out );
        this. = this..getFilePointer();
    }
    public void writefinal InputStream in ) throws IOException
    {
        this.assertNotClosed();
        this..write( in );
        this. = this..getFilePointer();
    }

    
Flushes the cache and closes the FileOperations implementation backing the instance.

Throws:
IOException if closing the FileOperations implementation backing the instance fails or if the instance already is closed.
    public void close() throws IOException
    {
        this.assertNotClosed();
        this.flush();
        this.getFileOperations().close();
        this. = true;
    }
    //----------------------------------------------------------FileOperations--
    //--FlushableFileOperations-------------------------------------------------

    
This method calls the flush() method of an underlying FlushableFileOperations implementation, if any.
    public void flush() throws IOException
    {
        this.assertNotClosed();
        if ( this. instanceof FlushableFileOperations )
        {
            ( ( FlushableFileOperations ) this. ).flush();
        }
    }
    //-------------------------------------------------FlushableFileOperations--
    //--ReadAheadFileOperations-------------------------------------------------

    
The FileOperations backing the instance.
    private final FileOperations fileOperations;

    
Cached bytes.
    private final byte[] cache;

    
Position in the file cache starts.
    private long cachePosition;
    private static final long NO_CACHEPOSITION = .;

    
Length of the cached data.
    private int cacheLength;

    
File pointer value.
    private long filePointer;

    
Flags the instance as beeing closed.
    private boolean closed;

    
Creates a new ReadAheadFileOperations instance taking the FileOperations backing the instance.

Parameters:
fileOperations the FileOperations backing the instance.
Throws:
NullPointerException if fileOperations is null.
IOException if reading fails.
    public ReadAheadFileOperationsfinal FileOperations fileOperations )
        throws IOException
    {
        super();
        if ( fileOperations == null )
        {
            throw new NullPointerException"fileOperations" );
        }
        this.initializeProperties.getProperties() );
        this.assertValidProperties();
        this. = fileOperations;
        this. = fileOperations.getFilePointer();
        // Pre-allocate the cache.
        this. =
            this.getMemoryManager().allocateBytes( this.getCacheSize() );
    }

    
Creates a new ReadAheadFileOperations instance taking the FileOperations backing the instance and the size of the cache.

Parameters:
fileOperations the FileOperations backing the instance.
cacheSize the number of bytes to read-ahead.
Throws:
NullPointerException if fileOperations is null.
PropertyException if cacheSize is negative or zero.
IOException if reading fails.
    public ReadAheadFileOperationsfinal FileOperations fileOperations,
                                     final int cacheSize ) throws IOException
    {
        super();
        if ( fileOperations == null )
        {
            throw new NullPointerException"fileOperations" );
        }
        this.initializeProperties.getProperties() );
        this. = cacheSize;
        this.assertValidProperties();
        this. = fileOperations;
        this. = fileOperations.getFilePointer();
        // Pre-allocate the cache.
        this. =
            this.getMemoryManager().allocateBytes( this.getCacheSize() );
    }

    
Gets the FileOperations implementation operations are performed with.

Returns:
the FileOperations implementation operations are performed with.
    public FileOperations getFileOperations()
    {
        return this.;
    }

    
Checks configured properties.

Throws:
PropertyException for illegal property values.
    private void assertValidProperties()
    {
        if ( this.getCacheSize() <= 0 )
        {
            throw new PropertyException(
                "cacheSize",
                Integer.toStringthis.getCacheSize() ) );
        }
    }

    
Checks that the instance is not closed.

Throws:
IOException if the instance is closed.
    private void assertNotClosed() throws IOException
    {
        if ( this. )
        {
            throw new IOException( ReadAheadFileOperationsBundle.getInstance().
                                   getAlreadyClosedText( Locale.getDefault() ) );
        }
    }

    
Fills the cache starting at the current file pointer value.

Throws:
IOException if reading fails.
    private void fillCache() throws IOException
    {
        final long delta = this.getLength() - this.;
        final int toRead = delta > this..length
            ? this..length
            : ( int ) delta;
        this. = this.;
        int totalRead = 0;
        int readLength = toRead;
        do
        {
            this..setFilePointer( this. );
            final int read = this..read(
                this.totalReadreadLength );
            assert read != FileOperations.EOF : "Unexpected end of file.";
            totalRead += read;
            readLength -= read;
        }
        while ( totalRead < toRead );
        this. = toRead;
    }
    //-------------------------------------------------ReadAheadFileOperations--
New to GrepCode? Check out our FAQ X