Package org.fjank.jcache.persistence

Source Code of org.fjank.jcache.persistence.CacheFileAdapter

/*   Open Source Java Caching Service
*    Copyright (C) 2002 Frank Karlstr�m
*    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 (at your option) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*    The author can be contacted by email: fjankk@users.sourceforge.net
*/
package org.fjank.jcache.persistence;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import javax.util.jcache.DiskCacheException;
import org.fjank.jcache.CacheObject;
import org.fjank.jcache.DiskCacheObject;


/**
* Provides thread safe access to the underlying random access file.
*/
public class CacheFileAdapter {
    /** the path to the files */
    private final String filepath;

    /** an accessor to the file */
    private RandomAccessFile raf;
  
    /**
     * Creates a new CacheFileAdapter object.
     *
     * @param file the file to adapt to
     *
     * @throws DiskCacheException if any exceptioins occur.
     */
    public CacheFileAdapter(final File file) {
        this.filepath = file.getAbsolutePath();
        try {
            raf = new RandomAccessFile(filepath, "rw");
        } catch (FileNotFoundException e) {
            throw new IllegalStateException(
                "The disk cache could not be initialized.");
        }
    }

    /**
     * returns a String representation of this object.
     *
     * @return a String representation of this object.
     */
    public String toString() {
        return getClass().getName() + ", file:" + filepath;
    }
    /**
     * reads from the diskfile, and return the raw bytes
     * contained at that pos. Its up to the client to deSerialize.
     * @param pos the position to start at.
     * @return a byte[] containing the raw bytes for the object.
     */
    public byte[] read(long pos) {
        byte[] data = null;
        boolean corrupted = false;
        try {
            synchronized (this) {
                raf.seek(pos);
                int datalen = raf.readInt();
                if (datalen > raf.length()) {
                    corrupted = true;
                } else {
                    raf.readFully(data = new byte[datalen]);
                }
            }
            if (corrupted) {
                throw new IllegalStateException("The Cache file is corrupted.");
            }
            return data;
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }
   
    /**
     * reads an object starting at the position,.
     *
     * @param pos the position to start at
     *
     * @return a Serializable object read from the diskcache.
     * @throws DiskCacheException
     *
     * @throws DiskCacheException if any exceptions occur.
     */
    public Serializable readObject(long pos) throws DiskCacheException {
        byte[] data = read(pos);
        return deSerialize(data);
        
    }

   

    public synchronized void append(byte[] data) throws DiskCacheException {
        try {
            write(data, raf.length());
        } catch (IOException e) {
            throw new DiskCacheException(e);
        }
    }

    public synchronized void write(byte[] data, long pos) {
        try {
            raf.seek(pos);
            raf.writeInt(data.length);
            raf.write(data);
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    /**
     * writes an object down to the cachefile
     *
     * @param obj the object to write
     * @param pos the position to start at.
     *
     * @throws DiskCacheException if any exception occur.
     */
    public void writeObject(final Serializable obj, final long pos) {
        write(serialize(obj), pos);
    }

    /**
     * adds an object to the diskcache.
     *
     * @param obj the object to add.
     *
     * @return a disk element descriptor used to locate the object
     *
     * @throws DiskCacheException if any exceptions occur.
     */
    public DiskElementDescriptor appendObject(CacheObject obj) {
        long pos = -1;
        DiskElementDescriptor ded = new DiskElementDescriptor();
        byte[] data = serialize((Serializable) obj);
        synchronized (this) {
            pos = length();
            ded.init(pos, data);
            write(data, pos);
        }
        return ded;
    }

    public synchronized long length() {
        try {
            return raf.length();
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    public synchronized void close() {
        try {
            raf.close();
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    public synchronized void reset() {
        close();
        File f = new File(filepath);
        //boolean deleted = f.delete();
        int retries=10;

        while (!f.delete()) {
            retries--;
            if(retries<=0) {
              throw new IllegalStateException("Failed to delete " + f.getName());
            }
            // todo busy wait.
            try {
        Thread.sleep(100);
      } catch (InterruptedException e1) {
        //interrupted.
      }
        }
        try {
            raf = new RandomAccessFile(filepath, "rw");
        } catch (FileNotFoundException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    public static byte[] serialize(Serializable obj) {
        ObjectOutputStream oos = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            return baos.toByteArray();
        } catch (NotSerializableException e) {
            throw new IllegalStateException(e.getMessage());
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    throw new IllegalStateException(
                        "Failed to close stream to DiskCache, "
                        + "cache may be corrupted. Reason: " + e.getMessage());
                }
            }
        }
    }
    public static DiskCacheObject deSerialize(byte[] data) throws DiskCacheException {
        ObjectInputStream ois = null;
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(data);
            BufferedInputStream bis = new BufferedInputStream(bais);
            ois=new ObjectInputStream(bis);
            DiskCacheObject obj = (DiskCacheObject) ois.readObject();
            obj.getCacheObject().resetRefCount();
            return obj;
        } catch (IOException e) {
            throw new IllegalStateException("An exception occured when reading from the disk cache." +
                " Reason: " + e.getMessage());
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("A class could not be found when deSerializing." +
                " Reason: " + e.getMessage());
        } finally {
          if (ois != null) {
              try {
                  ois.close();
              } catch (IOException e) {
                  throw new IllegalStateException(
                      "Failed to close stream to DiskCache, "
                      + "cache may be corrupted. Reason: " + e.getMessage());
              }
          }
        }
    }
}
TOP

Related Classes of org.fjank.jcache.persistence.CacheFileAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.