giacomo     02/01/06 09:18:26

  Modified:    src/scratchpad/src/org/apache/cocoon/jispstore
                        FilesystemQueueImpl.java JispFilesystemStore.java
                        JispStringKey.java MRUMemoryStore.java
  Log:
  fixed EOL encoding
  
  Revision  Changes    Path
  1.3       +241 -1    
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/FilesystemQueueImpl.java
  
  Index: FilesystemQueueImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/FilesystemQueueImpl.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- FilesystemQueueImpl.java  6 Jan 2002 14:28:10 -0000       1.2
  +++ FilesystemQueueImpl.java  6 Jan 2002 17:18:25 -0000       1.3
  @@ -1 +1,241 @@
  
-/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/

package org.apache.cocoon.jispstore;

import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.store.FilesystemQueue;
import org.apache.cocoon.components.store.FilesystemQueueObject;
import org.apache.cocoon.components.store.Store;
import org.apache.cocoon.util.IOUtils;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.NoSuchElementException;



/**
 *  This class provides a asynchron queue for storing objects on the filesystem.
 *  Every store component can uses this component to store object in the
 *  configured cache directory.
 *
 * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">Gerhard 
Froehlich</a>
 */

public final class FilesystemQueueImpl
extends AbstractLoggable

implements FilesystemQueue,
           Configurable,
           Runnable,
           ThreadSafe,
           Composable,
           Disposable,
           Startable {

    private static boolean doRun = false;
    private int handlerinterval;
    private int threadpriority;
    private int maxobjects;
    private LinkedList linkedList;
    private Store fsstore;
    private Thread fsQueueHandler;
    private ComponentManager manager;

    /**
     *  Test if queue is empty.
     *
     * @return    true if queue is empty else false.
     */

    public boolean isEmpty() {
        return (this.linkedList.size() == 0);
    }

    /**
     *  Get components of the ComponentManager
     *
     * @param  manager                 Description of Parameter
     * @exception  ComponentException  Description of Exception
     */

    public void compose(ComponentManager manager)
        throws ComponentException {

        this.manager = manager;
        if (this.getLogger().isDebugEnabled() == true) {
            getLogger().debug("Looking up " + Store.ROLE + 
"/JispFilesystemStore");
        }
        this.fsstore = (Store) manager.lookup(Store.ROLE + 
"/JispFilesystemStore");
    }

    /**
     *  Dispose the component
     */
    public void dispose() {
        if (this.manager != null) {
            this.manager.release(this.fsstore);
            this.fsstore = null;
        }
    }

    /**
     *  Configure the Filesystem Queue:
     *  <UL>
     *    <LI> handlerinterval = Interval of the Queue Handler Thread</LI>
     *    <LI> threadpriority = Priority of the Queue Handler Thread</LI> >LI>
     *    maxobjects = Defines the max. numbers of Objects in the queue</LI>
     *
     *  </UL>
     *
     *
     * @param  conf                        Description of Parameter
     * @exception  ConfigurationException  Description of Exception
     */

    public void configure(Configuration conf)
        throws ConfigurationException {

        Parameters params = Parameters.fromConfiguration(conf);
        this.handlerinterval = params.getParameterAsInteger("handlerinterval", 
10);
        this.threadpriority = params.getParameterAsInteger("threadpriority", 5);
        this.maxobjects = params.getParameterAsInteger("maxobjects", 100);

        if (this.getLogger().isDebugEnabled() == true) {
            this.getLogger().debug("Configure Filesystem Queue");
            this.getLogger().debug("handlerinterval=" + handlerinterval);
            this.getLogger().debug("threadpriority=" + threadpriority);
        }
        this.linkedList = new LinkedList();
    }

    /**
     *  Starts the Queue Handler Thread
     */
    public void start() {
        doRun = true;
        this.fsQueueHandler = new Thread(this);
        this.fsQueueHandler.setDaemon(true);
        this.fsQueueHandler.setPriority(this.threadpriority);
        this.fsQueueHandler.setName("fsQueueHandler");
        this.fsQueueHandler.start();
    }

    /**
     *  Stops the Queue Handler Thread
     */
    public void stop() {
        doRun = false;
    }

    /**
     *  Main processing method for the FilesystemQueueImpl object
     */
    public void run() {
        while (doRun) {
            while (!this.isEmpty()) {
                FilesystemQueueObject filesystemQueueObject = 
(FilesystemQueueObject) this.pop();
                try {
                    this.fsstore.store(filesystemQueueObject.getKey(),
                            filesystemQueueObject.getObject()
                            );
                } catch (IOException e) {
                    this.getLogger().error("Error in fsQueueHandler", e);
                }
            } try {
                Thread.currentThread().sleep(this.handlerinterval * 1000);
            } catch (InterruptedException ignore) {;}
        }
    }

    /**
     *  Clear all elements from queue.
     */
    public void clear() {
        if (this.getLogger().isDebugEnabled() == true) {
            this.getLogger().debug("Clearing the FilesystemQueue");
        }

        ListIterator listIterator = linkedList.listIterator(0);
        while (listIterator.hasNext()) {
            this.linkedList.remove(listIterator.nextIndex());
        }
    }

    /**
     *  Insert an element into queue.
     *
     * @param  element  the element to be inserted
     */
    public void insert(Object element) {

        if (this.linkedList.size() < maxobjects) {
            if (this.getLogger().isDebugEnabled() == true) {
                this.getLogger().debug("Insert Element in FilesystemQueue");
            }
            this.linkedList.addFirst(element);
            this.reportSize();
        } else {
            this.getLogger().warn("Filesystem Queue full!");
        }
    }

    /**
     *  Return element on top of heap but don't remove it.
     *
     * @return  the element at top of heap
     * @exception  NoSuchElementException  if isEmpty() == true
     */
    public Object peek()
        throws NoSuchElementException {
        if (this.getLogger().isDebugEnabled() == true) {
            this.getLogger().debug("Peek Element in FilesystemQueue");
        }

        return (Comparable) linkedList.getLast();
    }

    /**
     *  Return element on top of heap and remove it.
     *
     * @return the element at top of heap
     * @exception  NoSuchElementException  if isEmpty() == true
     */
    public Object pop()
        throws NoSuchElementException {
        if (this.getLogger().isDebugEnabled() == true) {
            this.getLogger().debug("Pop Element in FilesystemQueue");
        }
        return (Comparable) linkedList.removeLast();
    }

    private void reportSize() {
        if (this.getLogger().isDebugEnabled() == true) {
            this.getLogger().debug("Size of FilesystemQueue=" 
                + this.linkedList.size());
        }
    }
}



  \ No newline at end of file
  
+/*****************************************************************************
  + * Copyright (C) The Apache Software Foundation. All rights reserved.        
*
  + * ------------------------------------------------------------------------- 
*
  + * This software is published under the terms of the Apache Software License 
*
  + * version 1.1, a copy of which has been included  with this distribution in 
*
  + * the LICENSE file.                                                         
*
  + 
*****************************************************************************/
  +
  +package org.apache.cocoon.jispstore;
  +
  +import org.apache.avalon.framework.activity.Disposable;
  +import org.apache.avalon.framework.activity.Startable;
  +import org.apache.avalon.framework.component.ComponentException;
  +import org.apache.avalon.framework.component.ComponentManager;
  +import org.apache.avalon.framework.component.Composable;
  +import org.apache.avalon.framework.configuration.Configurable;
  +import org.apache.avalon.framework.configuration.Configuration;
  +import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.logger.AbstractLoggable;
  +import org.apache.avalon.framework.parameters.Parameters;
  +import org.apache.avalon.framework.thread.ThreadSafe;
  +import org.apache.cocoon.Constants;
  +import org.apache.cocoon.components.store.FilesystemQueue;
  +import org.apache.cocoon.components.store.FilesystemQueueObject;
  +import org.apache.cocoon.components.store.Store;
  +import org.apache.cocoon.util.IOUtils;
  +
  +import java.io.File;
  +import java.io.IOException;
  +import java.net.URLEncoder;
  +import java.util.LinkedList;
  +import java.util.ListIterator;
  +import java.util.NoSuchElementException;
  +
  +
  +
  +/**
  + *  This class provides a asynchron queue for storing objects on the 
filesystem.
  + *  Every store component can uses this component to store object in the
  + *  configured cache directory.
  + *
  + * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">Gerhard 
Froehlich</a>
  + */
  +
  +public final class FilesystemQueueImpl
  +extends AbstractLoggable
  +
  +implements FilesystemQueue,
  +           Configurable,
  +           Runnable,
  +           ThreadSafe,
  +           Composable,
  +           Disposable,
  +           Startable {
  +
  +    private static boolean doRun = false;
  +    private int handlerinterval;
  +    private int threadpriority;
  +    private int maxobjects;
  +    private LinkedList linkedList;
  +    private Store fsstore;
  +    private Thread fsQueueHandler;
  +    private ComponentManager manager;
  +
  +    /**
  +     *  Test if queue is empty.
  +     *
  +     * @return    true if queue is empty else false.
  +     */
  +
  +    public boolean isEmpty() {
  +        return (this.linkedList.size() == 0);
  +    }
  +
  +    /**
  +     *  Get components of the ComponentManager
  +     *
  +     * @param  manager                 Description of Parameter
  +     * @exception  ComponentException  Description of Exception
  +     */
  +
  +    public void compose(ComponentManager manager)
  +        throws ComponentException {
  +
  +        this.manager = manager;
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            getLogger().debug("Looking up " + Store.ROLE + 
"/JispFilesystemStore");
  +        }
  +        this.fsstore = (Store) manager.lookup(Store.ROLE + 
"/JispFilesystemStore");
  +    }
  +
  +    /**
  +     *  Dispose the component
  +     */
  +    public void dispose() {
  +        if (this.manager != null) {
  +            this.manager.release(this.fsstore);
  +            this.fsstore = null;
  +        }
  +    }
  +
  +    /**
  +     *  Configure the Filesystem Queue:
  +     *  <UL>
  +     *    <LI> handlerinterval = Interval of the Queue Handler Thread</LI>
  +     *    <LI> threadpriority = Priority of the Queue Handler Thread</LI> 
>LI>
  +     *    maxobjects = Defines the max. numbers of Objects in the queue</LI>
  +     *
  +     *  </UL>
  +     *
  +     *
  +     * @param  conf                        Description of Parameter
  +     * @exception  ConfigurationException  Description of Exception
  +     */
  +
  +    public void configure(Configuration conf)
  +        throws ConfigurationException {
  +
  +        Parameters params = Parameters.fromConfiguration(conf);
  +        this.handlerinterval = 
params.getParameterAsInteger("handlerinterval", 10);
  +        this.threadpriority = params.getParameterAsInteger("threadpriority", 
5);
  +        this.maxobjects = params.getParameterAsInteger("maxobjects", 100);
  +
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            this.getLogger().debug("Configure Filesystem Queue");
  +            this.getLogger().debug("handlerinterval=" + handlerinterval);
  +            this.getLogger().debug("threadpriority=" + threadpriority);
  +        }
  +        this.linkedList = new LinkedList();
  +    }
  +
  +    /**
  +     *  Starts the Queue Handler Thread
  +     */
  +    public void start() {
  +        doRun = true;
  +        this.fsQueueHandler = new Thread(this);
  +        this.fsQueueHandler.setDaemon(true);
  +        this.fsQueueHandler.setPriority(this.threadpriority);
  +        this.fsQueueHandler.setName("fsQueueHandler");
  +        this.fsQueueHandler.start();
  +    }
  +
  +    /**
  +     *  Stops the Queue Handler Thread
  +     */
  +    public void stop() {
  +        doRun = false;
  +    }
  +
  +    /**
  +     *  Main processing method for the FilesystemQueueImpl object
  +     */
  +    public void run() {
  +        while (doRun) {
  +            while (!this.isEmpty()) {
  +                FilesystemQueueObject filesystemQueueObject = 
(FilesystemQueueObject) this.pop();
  +                try {
  +                    this.fsstore.store(filesystemQueueObject.getKey(),
  +                            filesystemQueueObject.getObject()
  +                            );
  +                } catch (IOException e) {
  +                    this.getLogger().error("Error in fsQueueHandler", e);
  +                }
  +            } try {
  +                Thread.currentThread().sleep(this.handlerinterval * 1000);
  +            } catch (InterruptedException ignore) {;}
  +        }
  +    }
  +
  +    /**
  +     *  Clear all elements from queue.
  +     */
  +    public void clear() {
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            this.getLogger().debug("Clearing the FilesystemQueue");
  +        }
  +
  +        ListIterator listIterator = linkedList.listIterator(0);
  +        while (listIterator.hasNext()) {
  +            this.linkedList.remove(listIterator.nextIndex());
  +        }
  +    }
  +
  +    /**
  +     *  Insert an element into queue.
  +     *
  +     * @param  element  the element to be inserted
  +     */
  +    public void insert(Object element) {
  +
  +        if (this.linkedList.size() < maxobjects) {
  +            if (this.getLogger().isDebugEnabled() == true) {
  +                this.getLogger().debug("Insert Element in FilesystemQueue");
  +            }
  +            this.linkedList.addFirst(element);
  +            this.reportSize();
  +        } else {
  +            this.getLogger().warn("Filesystem Queue full!");
  +        }
  +    }
  +
  +    /**
  +     *  Return element on top of heap but don't remove it.
  +     *
  +     * @return  the element at top of heap
  +     * @exception  NoSuchElementException  if isEmpty() == true
  +     */
  +    public Object peek()
  +        throws NoSuchElementException {
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            this.getLogger().debug("Peek Element in FilesystemQueue");
  +        }
  +
  +        return (Comparable) linkedList.getLast();
  +    }
  +
  +    /**
  +     *  Return element on top of heap and remove it.
  +     *
  +     * @return the element at top of heap
  +     * @exception  NoSuchElementException  if isEmpty() == true
  +     */
  +    public Object pop()
  +        throws NoSuchElementException {
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            this.getLogger().debug("Pop Element in FilesystemQueue");
  +        }
  +        return (Comparable) linkedList.removeLast();
  +    }
  +
  +    private void reportSize() {
  +        if (this.getLogger().isDebugEnabled() == true) {
  +            this.getLogger().debug("Size of FilesystemQueue=" 
  +                + this.linkedList.size());
  +        }
  +    }
  +}
  +
  +
  +
  
  
  
  1.3       +357 -1    
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispFilesystemStore.java
  
  Index: JispFilesystemStore.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispFilesystemStore.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JispFilesystemStore.java  6 Jan 2002 14:28:10 -0000       1.2
  +++ JispFilesystemStore.java  6 Jan 2002 17:18:26 -0000       1.3
  @@ -1 +1,357 @@
  -/**
 *  Copyright (C) The Apache Software Foundation. All rights reserved. *
 *  ------------------------------------------------------------------------- *
 *  This software is published under the terms of the Apache Software License *
 *  version 1.1, a copy of which has been included with this distribution in *
 *  the LICENSE file. *
 */
package org.apache.cocoon.jispstore;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.store.Store;
import org.apache.cocoon.util.IOUtils;

import com.coyotegulch.jisp.BTreeIndex;
import com.coyotegulch.jisp.IndexedObjectDatabase;
import com.coyotegulch.jisp.KeyNotFound;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;

/**
 * This store is based on the Jisp library 
 * (http://www.coyotegulch.com/jisp/index.html). This store uses B-Tree indexes
 *  to access variable-length serialized data stored in files.
 *
 * @author Gerhard Froehlich 
 *  <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a>
 */

public final class JispFilesystemStore
extends AbstractLoggable
implements Store,
           Contextualizable,
           ThreadSafe,
           Initializable,
           Parameterizable {

    /**
     *  The directory repository
     */
    protected File mDirectoryFile;

    /**
     *  Description of the Field
     */
    protected volatile String mDirectoryPath;



    /**
     *  The database
     */
    private String mDatabaseName;
    private String mIndexName;
    private int mOrder;
    private IndexedObjectDatabase mDatabase;
    private BTreeIndex mIndex;

    /**
     *  Sets the repository's location
     *
     * @param  the new directory value
     * @exception  IOException
     */
    public void setDirectory(final String directory)
        throws IOException {
        this.setDirectory(new File(directory));
    }

    /**
     *  Sets the repository's location
     *
     * @param  the new directory value
     * @exception  IOException
     */

    public void setDirectory(final File directory)
        throws IOException {
        this.mDirectoryFile = directory;

        /*
         *  Save directory path prefix
         */
        this.mDirectoryPath = IOUtils.getFullFilename(this.mDirectoryFile);
        this.mDirectoryPath += File.separator;

        /*
         *  Does directory exist?
         */
        if (!this.mDirectoryFile.exists()) {
            /*
             *  Create it anew
             */
            if (!this.mDirectoryFile.mkdir()) {
                throw new IOException(
                        "Error creating store directory '" 
                        + this.mDirectoryPath + "': ");
            }
        }

        /*
         *  Is given file actually a directory?
         */
        if (!this.mDirectoryFile.isDirectory()) {
            throw new IOException("'" + this.mDirectoryPath 
                                  + "' is not a directory");
        }

        /*
         *  Is directory readable and writable?
         */
        if (!(this.mDirectoryFile.canRead()
              && this.mDirectoryFile.canWrite())) {
            throw new IOException(
                    "Directory '" + this.mDirectoryPath 
                    + "' is not readable/writable"
                    );
        }
    }

    /**
     *  Returns the repository's full pathname
     *
     * @return the directory as String
     */
    public String getDirectoryPath() {
        return this.mDirectoryPath;
    }

    /**
     *  Returns a Object from the store associated with the Key Object
     *
     * @param the Key object
     * @return the Object associated with Key Object
     */
    public Object get(Object key) {
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("get(): Get file with key: " + 
key.toString());
        }
        Object readObj = null;

        try {
            readObj = mDatabase.read(new JispStringKey(key.toString()), mIndex);
            if (getLogger().isDebugEnabled()) {
                if (readObj != null) {
                    this.getLogger().debug("get(): FOUND!!= " + readObj);
                } else {
                    this.getLogger().debug("get(): NOT_FOUND!!");
                }
            }
        } catch (Exception e) {
            getLogger().error("get(..): Exception", e);
        }
        return readObj;
    }

    /**
     *  Contextualize the Component
     *
     * @param  the Context of the Application
     * @exception  ContextException
     */
    public void contextualize(final Context context)
        throws ContextException {
        try {
            setDirectory((File) context.get(Constants.CONTEXT_WORK_DIR));
        } catch (Exception e) {
            // ignore
        }
    }

    /**
     *  Initialize the Component
     */
    public void initialize() {
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("initialize() JispFilesystemStore");
        }

        try {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("initialize(): Path to Datafile=" 
                + this.getDirectoryPath() + mDatabaseName);
            }
            File myFile = new File(this.getDirectoryPath() + mDatabaseName);
            if (myFile.exists()) {
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("initialize(): Datafile exists");
                }
                mDatabase = new IndexedObjectDatabase(getDirectoryPath() 
                                + mDatabaseName, false);
                mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName);
                mDatabase.attachIndex(mIndex);
                mIndex.dumpTree();
            } else {
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("initialize(): Datafile not exists");
                }
                mDatabase = new IndexedObjectDatabase(getDirectoryPath() 
                            + mDatabaseName, false);
                mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName,
                        mOrder, new JispStringKey(), false);
                mDatabase.attachIndex(mIndex);
                mIndex.dumpTree();
            }
        } catch (KeyNotFound ignore) {
        } catch (Exception e) {
            getLogger().error("initialize(..) Exception", e);
        }
    }

    /**
     *  Configure the Component. A few options can be used :
     *  <UL>
     *    <LI> mDatabaseName = the name of the data file (Default: cocoon.dat)
     *    </LI>
     *    <LI> mIndexName = the name of the index file (Default: cocoon.idx)
     *    </LI>
     *    <LI> mOrder = The page size of the B-Tree</LI>
     *  </UL>
     *
     *
     * @param The Configuration Paramter  
     * @exception  ParameterException
     */
    public void parameterize(Parameters params)
        throws ParameterException {
        mDatabaseName = params.getParameter("datafile", "cocoon.dat");
        mIndexName = params.getParameter("indexfile", "cocoon.idx");
        mOrder = params.getParameterAsInteger("order", 1001);

        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("parameterize(..): mDatabaseName=" 
                                    + mDatabaseName);
            this.getLogger().debug("parameterize(..): mIndexName=" 
                                    + mIndexName);
            this.getLogger().debug("parameterize(..): mOrder=" + mOrder);
        }
    }

    /**
     *  Store the given Object in the indexed data file.
     *
     * @param  the Key Object
     * @param  the Value Object 
     * @exception  IOException
     */
    public void store(Object key, Object value)
        throws IOException {
        
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("store(): Store file with key: " 
                                  + key.toString());
        }

        if (value instanceof Serializable) {
            try {
                JispStringKey[] keyArray = new JispStringKey[1];
                keyArray[0] = new JispStringKey(key.toString());
                mDatabase.write(keyArray, (Serializable) value);
            } catch (Exception e) {
                this.getLogger().error("store(..): Exception", e);
            }
        } else {
            throw new IOException("Object not Serializable");
        }
    }

    /**
     *  Holds the given Object in the indexed data file.
     *
     * @param  the Key Object
     * @param  the Value Object 
     * @exception  IOException
     */
    public void hold(Object key, Object value)
        throws IOException {
        this.store(key, value);
    }

    /**
     *  Frees some values of the data file
     */
    public void free() { 
       //TODO: implementation
    }

    /**
     *  Removes a value from the data file with the given key.
     *
     * @param the Key Object
     */
    public void remove(Object key) {
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("remove(..) Remove item");
        }

        try {
            JispStringKey[] keyArray = new JispStringKey[1];
            keyArray[0] = new JispStringKey(key.toString());
            mDatabase.remove(keyArray);
        } catch (KeyNotFound ignore) {
        } catch (Exception e) {
            this.getLogger().error("remove(..): Exception", e);
        }
    }

    /**
     *  Test if the the index file contains the given key
     *
     * @param the Key Object
     * @return true if Key exists and false if not
     */
    public boolean containsKey(Object key) {
        long res = -1;

        try {
            res = mIndex.findKey(new JispStringKey(key.toString()));
            if (getLogger().isDebugEnabled()) {
                this.getLogger().debug("containsKey(..): res=" + res);
            }
        } catch (KeyNotFound ignore) {
        } catch (Exception e) {
            this.getLogger().error("containsKey(..): Exception", e);
        }

        if (res > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     *  Returns a Enumeration of all Keys in the indexed file
     *
     * @return  Enumeration Object with all existing keys
     */
    public Enumeration keys() {
        //TODO: Implementation
        return null;
    }
}



  \ No newline at end of file
  +/**
  + *  Copyright (C) The Apache Software Foundation. All rights reserved. *
  + *  
------------------------------------------------------------------------- *
  + *  This software is published under the terms of the Apache Software 
License *
  + *  version 1.1, a copy of which has been included with this distribution in 
*
  + *  the LICENSE file. *
  + */
  +package org.apache.cocoon.jispstore;
  +
  +import org.apache.avalon.framework.activity.Initializable;
  +import org.apache.avalon.framework.context.Context;
  +import org.apache.avalon.framework.context.ContextException;
  +import org.apache.avalon.framework.context.Contextualizable;
  +import org.apache.avalon.framework.logger.AbstractLoggable;
  +import org.apache.avalon.framework.parameters.ParameterException;
  +import org.apache.avalon.framework.parameters.Parameterizable;
  +import org.apache.avalon.framework.parameters.Parameters;
  +import org.apache.avalon.framework.thread.ThreadSafe;
  +import org.apache.cocoon.Constants;
  +import org.apache.cocoon.components.store.Store;
  +import org.apache.cocoon.util.IOUtils;
  +
  +import com.coyotegulch.jisp.BTreeIndex;
  +import com.coyotegulch.jisp.IndexedObjectDatabase;
  +import com.coyotegulch.jisp.KeyNotFound;
  +
  +import java.io.File;
  +import java.io.IOException;
  +import java.io.Serializable;
  +import java.util.Enumeration;
  +
  +/**
  + * This store is based on the Jisp library 
  + * (http://www.coyotegulch.com/jisp/index.html). This store uses B-Tree 
indexes
  + *  to access variable-length serialized data stored in files.
  + *
  + * @author Gerhard Froehlich 
  + *  <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a>
  + */
  +
  +public final class JispFilesystemStore
  +extends AbstractLoggable
  +implements Store,
  +           Contextualizable,
  +           ThreadSafe,
  +           Initializable,
  +           Parameterizable {
  +
  +    /**
  +     *  The directory repository
  +     */
  +    protected File mDirectoryFile;
  +
  +    /**
  +     *  Description of the Field
  +     */
  +    protected volatile String mDirectoryPath;
  +
  +
  +
  +    /**
  +     *  The database
  +     */
  +    private String mDatabaseName;
  +    private String mIndexName;
  +    private int mOrder;
  +    private IndexedObjectDatabase mDatabase;
  +    private BTreeIndex mIndex;
  +
  +    /**
  +     *  Sets the repository's location
  +     *
  +     * @param  the new directory value
  +     * @exception  IOException
  +     */
  +    public void setDirectory(final String directory)
  +        throws IOException {
  +        this.setDirectory(new File(directory));
  +    }
  +
  +    /**
  +     *  Sets the repository's location
  +     *
  +     * @param  the new directory value
  +     * @exception  IOException
  +     */
  +
  +    public void setDirectory(final File directory)
  +        throws IOException {
  +        this.mDirectoryFile = directory;
  +
  +        /*
  +         *  Save directory path prefix
  +         */
  +        this.mDirectoryPath = IOUtils.getFullFilename(this.mDirectoryFile);
  +        this.mDirectoryPath += File.separator;
  +
  +        /*
  +         *  Does directory exist?
  +         */
  +        if (!this.mDirectoryFile.exists()) {
  +            /*
  +             *  Create it anew
  +             */
  +            if (!this.mDirectoryFile.mkdir()) {
  +                throw new IOException(
  +                        "Error creating store directory '" 
  +                        + this.mDirectoryPath + "': ");
  +            }
  +        }
  +
  +        /*
  +         *  Is given file actually a directory?
  +         */
  +        if (!this.mDirectoryFile.isDirectory()) {
  +            throw new IOException("'" + this.mDirectoryPath 
  +                                  + "' is not a directory");
  +        }
  +
  +        /*
  +         *  Is directory readable and writable?
  +         */
  +        if (!(this.mDirectoryFile.canRead()
  +              && this.mDirectoryFile.canWrite())) {
  +            throw new IOException(
  +                    "Directory '" + this.mDirectoryPath 
  +                    + "' is not readable/writable"
  +                    );
  +        }
  +    }
  +
  +    /**
  +     *  Returns the repository's full pathname
  +     *
  +     * @return the directory as String
  +     */
  +    public String getDirectoryPath() {
  +        return this.mDirectoryPath;
  +    }
  +
  +    /**
  +     *  Returns a Object from the store associated with the Key Object
  +     *
  +     * @param the Key object
  +     * @return the Object associated with Key Object
  +     */
  +    public Object get(Object key) {
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("get(): Get file with key: " + 
key.toString());
  +        }
  +        Object readObj = null;
  +
  +        try {
  +            readObj = mDatabase.read(new JispStringKey(key.toString()), 
mIndex);
  +            if (getLogger().isDebugEnabled()) {
  +                if (readObj != null) {
  +                    this.getLogger().debug("get(): FOUND!!= " + readObj);
  +                } else {
  +                    this.getLogger().debug("get(): NOT_FOUND!!");
  +                }
  +            }
  +        } catch (Exception e) {
  +            getLogger().error("get(..): Exception", e);
  +        }
  +        return readObj;
  +    }
  +
  +    /**
  +     *  Contextualize the Component
  +     *
  +     * @param  the Context of the Application
  +     * @exception  ContextException
  +     */
  +    public void contextualize(final Context context)
  +        throws ContextException {
  +        try {
  +            setDirectory((File) context.get(Constants.CONTEXT_WORK_DIR));
  +        } catch (Exception e) {
  +            // ignore
  +        }
  +    }
  +
  +    /**
  +     *  Initialize the Component
  +     */
  +    public void initialize() {
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("initialize() JispFilesystemStore");
  +        }
  +
  +        try {
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("initialize(): Path to Datafile=" 
  +                + this.getDirectoryPath() + mDatabaseName);
  +            }
  +            File myFile = new File(this.getDirectoryPath() + mDatabaseName);
  +            if (myFile.exists()) {
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("initialize(): Datafile exists");
  +                }
  +                mDatabase = new IndexedObjectDatabase(getDirectoryPath() 
  +                                + mDatabaseName, false);
  +                mIndex = new BTreeIndex(this.getDirectoryPath() + 
mIndexName);
  +                mDatabase.attachIndex(mIndex);
  +                mIndex.dumpTree();
  +            } else {
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("initialize(): Datafile not 
exists");
  +                }
  +                mDatabase = new IndexedObjectDatabase(getDirectoryPath() 
  +                            + mDatabaseName, false);
  +                mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName,
  +                        mOrder, new JispStringKey(), false);
  +                mDatabase.attachIndex(mIndex);
  +                mIndex.dumpTree();
  +            }
  +        } catch (KeyNotFound ignore) {
  +        } catch (Exception e) {
  +            getLogger().error("initialize(..) Exception", e);
  +        }
  +    }
  +
  +    /**
  +     *  Configure the Component. A few options can be used :
  +     *  <UL>
  +     *    <LI> mDatabaseName = the name of the data file (Default: 
cocoon.dat)
  +     *    </LI>
  +     *    <LI> mIndexName = the name of the index file (Default: cocoon.idx)
  +     *    </LI>
  +     *    <LI> mOrder = The page size of the B-Tree</LI>
  +     *  </UL>
  +     *
  +     *
  +     * @param The Configuration Paramter  
  +     * @exception  ParameterException
  +     */
  +    public void parameterize(Parameters params)
  +        throws ParameterException {
  +        mDatabaseName = params.getParameter("datafile", "cocoon.dat");
  +        mIndexName = params.getParameter("indexfile", "cocoon.idx");
  +        mOrder = params.getParameterAsInteger("order", 1001);
  +
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("parameterize(..): mDatabaseName=" 
  +                                    + mDatabaseName);
  +            this.getLogger().debug("parameterize(..): mIndexName=" 
  +                                    + mIndexName);
  +            this.getLogger().debug("parameterize(..): mOrder=" + mOrder);
  +        }
  +    }
  +
  +    /**
  +     *  Store the given Object in the indexed data file.
  +     *
  +     * @param  the Key Object
  +     * @param  the Value Object 
  +     * @exception  IOException
  +     */
  +    public void store(Object key, Object value)
  +        throws IOException {
  +        
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("store(): Store file with key: " 
  +                                  + key.toString());
  +        }
  +
  +        if (value instanceof Serializable) {
  +            try {
  +                JispStringKey[] keyArray = new JispStringKey[1];
  +                keyArray[0] = new JispStringKey(key.toString());
  +                mDatabase.write(keyArray, (Serializable) value);
  +            } catch (Exception e) {
  +                this.getLogger().error("store(..): Exception", e);
  +            }
  +        } else {
  +            throw new IOException("Object not Serializable");
  +        }
  +    }
  +
  +    /**
  +     *  Holds the given Object in the indexed data file.
  +     *
  +     * @param  the Key Object
  +     * @param  the Value Object 
  +     * @exception  IOException
  +     */
  +    public void hold(Object key, Object value)
  +        throws IOException {
  +        this.store(key, value);
  +    }
  +
  +    /**
  +     *  Frees some values of the data file
  +     */
  +    public void free() { 
  +       //TODO: implementation
  +    }
  +
  +    /**
  +     *  Removes a value from the data file with the given key.
  +     *
  +     * @param the Key Object
  +     */
  +    public void remove(Object key) {
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("remove(..) Remove item");
  +        }
  +
  +        try {
  +            JispStringKey[] keyArray = new JispStringKey[1];
  +            keyArray[0] = new JispStringKey(key.toString());
  +            mDatabase.remove(keyArray);
  +        } catch (KeyNotFound ignore) {
  +        } catch (Exception e) {
  +            this.getLogger().error("remove(..): Exception", e);
  +        }
  +    }
  +
  +    /**
  +     *  Test if the the index file contains the given key
  +     *
  +     * @param the Key Object
  +     * @return true if Key exists and false if not
  +     */
  +    public boolean containsKey(Object key) {
  +        long res = -1;
  +
  +        try {
  +            res = mIndex.findKey(new JispStringKey(key.toString()));
  +            if (getLogger().isDebugEnabled()) {
  +                this.getLogger().debug("containsKey(..): res=" + res);
  +            }
  +        } catch (KeyNotFound ignore) {
  +        } catch (Exception e) {
  +            this.getLogger().error("containsKey(..): Exception", e);
  +        }
  +
  +        if (res > 0) {
  +            return true;
  +        } else {
  +            return false;
  +        }
  +    }
  +
  +    /**
  +     *  Returns a Enumeration of all Keys in the indexed file
  +     *
  +     * @return  Enumeration Object with all existing keys
  +     */
  +    public Enumeration keys() {
  +        //TODO: Implementation
  +        return null;
  +    }
  +}
  +
  +
  +
  
  
  
  1.3       +114 -1    
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispStringKey.java
  
  Index: JispStringKey.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispStringKey.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JispStringKey.java        6 Jan 2002 14:28:10 -0000       1.2
  +++ JispStringKey.java        6 Jan 2002 17:18:26 -0000       1.3
  @@ -1 +1,114 @@
  
-/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/

package org.apache.cocoon.jispstore;

import com.coyotegulch.jisp.KeyObject;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

/**
 *  Wrapper class to make our cache Key compatible with the Jisp KeyObject NOTE:
 *  This Wrapper is only for String Keys.
 *
 * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">
 *      [EMAIL PROTECTED]</a>
 */

final class JispStringKey extends KeyObject {
    final static long serialVersionUID = -6894793231339165076L;
    private String mKey;

    /**
     *  Constructor for the JispStringKey object
     */
    public JispStringKey() {
        mKey = new String("");
    }

    /**
     *  Constructor for the JispStringKey object
     *
     * @param  the Value of the Key as String
     */
    public JispStringKey(String keyValue) {
        mKey = keyValue;
    }

    /**
     *  Compares two Keys
     *
     * @param  the KeyObject to be compared
     * @return 0 if equal, 1 if greater, -1 if less
     */

    public int compareTo(KeyObject key) {
        if (key instanceof JispStringKey) {
            int comp = mKey.trim().compareTo(((JispStringKey) key).mKey.trim());
            if (comp == 0) {
                return KEY_EQUAL;
            } else {
                if (comp < 0) {
                    return KEY_LESS;
                } else {
                    return KEY_MORE;
                }
            }
        } else {
            return KEY_ERROR;
        }
    }

    /**
     *  Composes a null Kewy
     *
     * @return a null Key 
     */
    public KeyObject makeNullKey() {
        return new JispStringKey();
    }

    /**
     *
     *
     * @param  out              Description of Parameter
     * @exception  IOException  Description of Exception
     */
    public void writeExternal(ObjectOutput out)
        throws IOException {
        String outKey;
        outKey = new String(mKey);
        out.writeUTF(outKey);
    }

    /**
     * Description of the Method
     *
     * @param  in                          Description of Parameter
     * @exception  IOException             Description of Exception
     * @exception  ClassNotFoundException  Description of Exception
     */

    public void readExternal(ObjectInput in)
        throws IOException, ClassNotFoundException {
        mKey = in.readUTF();
    }

    /**
     *  Overrides the toString() method
     *
     * @return the Key as String
     */
    public String toString() {
        return mKey;
    }
}



  \ No newline at end of file
  
+/*****************************************************************************
  + * Copyright (C) The Apache Software Foundation. All rights reserved.        
*
  + * ------------------------------------------------------------------------- 
*
  + * This software is published under the terms of the Apache Software License 
*
  + * version 1.1, a copy of which has been included  with this distribution in 
*
  + * the LICENSE file.                                                         
*
  + 
*****************************************************************************/
  +
  +package org.apache.cocoon.jispstore;
  +
  +import com.coyotegulch.jisp.KeyObject;
  +import java.io.IOException;
  +import java.io.ObjectInput;
  +import java.io.ObjectOutput;
  +
  +/**
  + *  Wrapper class to make our cache Key compatible with the Jisp KeyObject 
NOTE:
  + *  This Wrapper is only for String Keys.
  + *
  + * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">
  + *      [EMAIL PROTECTED]</a>
  + */
  +
  +final class JispStringKey extends KeyObject {
  +    final static long serialVersionUID = -6894793231339165076L;
  +    private String mKey;
  +
  +    /**
  +     *  Constructor for the JispStringKey object
  +     */
  +    public JispStringKey() {
  +        mKey = new String("");
  +    }
  +
  +    /**
  +     *  Constructor for the JispStringKey object
  +     *
  +     * @param  the Value of the Key as String
  +     */
  +    public JispStringKey(String keyValue) {
  +        mKey = keyValue;
  +    }
  +
  +    /**
  +     *  Compares two Keys
  +     *
  +     * @param  the KeyObject to be compared
  +     * @return 0 if equal, 1 if greater, -1 if less
  +     */
  +
  +    public int compareTo(KeyObject key) {
  +        if (key instanceof JispStringKey) {
  +            int comp = mKey.trim().compareTo(((JispStringKey) 
key).mKey.trim());
  +            if (comp == 0) {
  +                return KEY_EQUAL;
  +            } else {
  +                if (comp < 0) {
  +                    return KEY_LESS;
  +                } else {
  +                    return KEY_MORE;
  +                }
  +            }
  +        } else {
  +            return KEY_ERROR;
  +        }
  +    }
  +
  +    /**
  +     *  Composes a null Kewy
  +     *
  +     * @return a null Key 
  +     */
  +    public KeyObject makeNullKey() {
  +        return new JispStringKey();
  +    }
  +
  +    /**
  +     *
  +     *
  +     * @param  out              Description of Parameter
  +     * @exception  IOException  Description of Exception
  +     */
  +    public void writeExternal(ObjectOutput out)
  +        throws IOException {
  +        String outKey;
  +        outKey = new String(mKey);
  +        out.writeUTF(outKey);
  +    }
  +
  +    /**
  +     * Description of the Method
  +     *
  +     * @param  in                          Description of Parameter
  +     * @exception  IOException             Description of Exception
  +     * @exception  ClassNotFoundException  Description of Exception
  +     */
  +
  +    public void readExternal(ObjectInput in)
  +        throws IOException, ClassNotFoundException {
  +        mKey = in.readUTF();
  +    }
  +
  +    /**
  +     *  Overrides the toString() method
  +     *
  +     * @return the Key as String
  +     */
  +    public String toString() {
  +        return mKey;
  +    }
  +}
  +
  +
  +
  
  
  
  1.3       +301 -1    
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/MRUMemoryStore.java
  
  Index: MRUMemoryStore.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/MRUMemoryStore.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MRUMemoryStore.java       6 Jan 2002 14:28:10 -0000       1.2
  +++ MRUMemoryStore.java       6 Jan 2002 17:18:26 -0000       1.3
  @@ -1 +1,301 @@
  
-/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/
package org.apache.cocoon.jispstore;

import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.store.FilesystemQueue;
import org.apache.cocoon.components.store.FilesystemQueueObject;
import org.apache.cocoon.components.store.Store;
import org.apache.cocoon.components.store.StoreJanitor;
import org.apache.cocoon.util.ClassUtils;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;

/**
 *  This class provides a cache algorithm for the requested documents. It
 *  combines a HashMap and a LinkedList to create a so called MRU (Most Recently
 *  Used) cache.
 *
 * @author     <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a>
 * @author     <a href="mailto:[EMAIL PROTECTED]">Davanum Srinivas</a>
 */
public final class MRUMemoryStore
extends AbstractLoggable
implements Store,
           Parameterizable,
           ThreadSafe,
           Composable,
           Disposable {

    private int mMaxobjects;
    private boolean mFilesystem;
    private Hashtable mCache;
    private LinkedList mMRUList;
    private Store mFsstore;
    private StoreJanitor mStorejanitor;
    private FilesystemQueue mFilesystemQueue;
    private ComponentManager mComponetManager;

    /**
     *  Get the object associated to the given unique key.
     *
     * @param the Key Object
     * @return the Object associated with Key Object
     */
    public Object get(Object key) {
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("Getting object from memory. Key: " + key);
        }
        Object tmpobject = this.mCache.get(key);
        if (tmpobject != null) {
            this.mMRUList.remove(key);
            this.mMRUList.addFirst(key);
            return tmpobject;
        }

        this.getLogger().debug("Object not found in memory");
        if (this.mFilesystem) {
            tmpobject = this.mFsstore.get(key);
            if (tmpobject == null) {
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("Object was NOT found on fs. "
                                           + "Looked for: " + key);
                }
                return null;
            } else {
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("Object was found on fs");
                }
                if (!this.mCache.containsKey(key)) {
                    this.hold(key, tmpobject);
                }
                return tmpobject;
            }
        }
        return null;
    }

    /**
     *  Get components of the ComponentManager
     *
     * @param  the Component Manager
     * @exception  ComponentException
     */
    public void compose(ComponentManager manager)
        throws ComponentException {
        this.mComponetManager = manager;
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Looking up " 
                               + Store.ROLE + "/JispFilesystemStore");
        }

        this.mFsstore = (Store) manager.lookup(Store.ROLE 
                                               + "/JispFilesystemStore");
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Looking up " + StoreJanitor.ROLE);
        }
        this.mStorejanitor = (StoreJanitor) manager.lookup(StoreJanitor.ROLE);
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Looking up " + FilesystemQueue.ROLE);
        }
        this.mFilesystemQueue = (FilesystemQueue) 
manager.lookup(FilesystemQueue.ROLE);
    }

    /**
     *  Configure the MRUMemoryStore. A few options can be used :
     *  <UL>
     *    <LI> mMaxobjects = how many objects will be stored in memory (Default:
     *    10 objects)</LI>
     *    <LI> mFilesystem = use filesystem storage to keep object persistent
     *    (Default: false)</LI>
     *  </UL>
     *
     *
     * @param  the Configuration Parameters
     * @exception  ParameterException
     */

    public void parameterize(Parameters params)
        throws ParameterException {
        this.mMaxobjects = params.getParameterAsInteger("maxobjects", 100);
        this.mFilesystem = params.getParameterAsBoolean("filesystem", false);
        if ((this.mMaxobjects < 1)) {
            throw new ParameterException("MRUMemoryStore maxobjects must be "
                                         + "at least 1 milli second!");
        }
        this.mCache = new Hashtable((int) (this.mMaxobjects * 1.2));
        this.mMRUList = new LinkedList();
        this.mStorejanitor.register(this);
    }

    /**
     *  Dispose the component
     */
    public void dispose() {
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("dispose()");
        }

        if (this.mComponetManager != null) {
            this.mComponetManager.release(this.mStorejanitor);
            this.mStorejanitor = null;
            this.mComponetManager.release(this.mFilesystemQueue);
            this.mFilesystemQueue = null;
            this.mComponetManager.release(this.mFsstore);
            this.mFsstore = null;
        }
    }

    /**
     *  Store the given object in a persistent state. It is up to the caller to
     *  ensure that the key has a persistent state across different JVM
     *  executions.
     *
     * @param the Key Object
     * @param the Value Object
     */
    public void store(Object key, Object value) {
        if (this.mFilesystem) {
            if (this.checkSerializable(value) &&
                    !this.mFsstore.containsKey(key)) {
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("Storing object on fs");
                }
                try {
                    this.mFilesystemQueue.insert(new FilesystemQueueObject(key, 
value));
                } catch (Exception e) {
                    this.getLogger().error("Error storing Object on fs", e);
                }
            }
        }
    }

    /**
     *  This method holds the requested object in a HashMap combined with a
     *  LinkedList to create the MRU. It also stores objects onto the filesystem
     *  if configured.
     *
     * @param the Key Object
     * @param the Value Object
     */
    public void hold(Object key, Object value) {
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Holding object in memory. key: " + key);
            getLogger().debug("Holding object in memory. value: " + value);
        }

        while (this.mMRUList.size() >= this.mMaxobjects) {
            this.free();
        }
      
        this.mCache.put(key, value);
        this.mMRUList.remove(key);
        this.mMRUList.addFirst(key);
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("Cache size=" + mCache.size());
        }
    }

    /**
     *  Remove the object associated to the given key.
     *
     * @param the Key object
     */
    public void remove(Object key) {
        if (getLogger().isDebugEnabled()) {
            this.getLogger().debug("Removing object from store");
        }
        this.mCache.remove(key);
        this.mMRUList.remove(key);
        if (this.mFilesystem && key != null) {
            this.mFsstore.remove(key);
        }
    }

    /**
     *  Indicates if the given key is associated to a contained object.
     *
     * @param the Key Object
     * @return true if Key exists and false if not
     */
    public boolean containsKey(Object key) {
        if (mFilesystem) {
            return (this.mCache.containsKey(key) 
                    || this.mFsstore.containsKey(key));
        } else {
            return this.mCache.containsKey(key);
        }
    }

    /**
     *  Returns the list of used keys as an Enumeration.
     *
     * @return    the enumeration of the cache
     */
    public Enumeration keys() {
        return this.mCache.keys();
    }

    /**
     *  Frees some of the fast memory used by this store. It removes the last
     *  element in the store.
     */
    public void free() {
        try {
            if (this.mCache.size() > 0) {
                this.getLogger().debug("Freeing cache");
                this.mCache.remove(this.mMRUList.getLast());
                this.mMRUList.removeLast();
                if (getLogger().isDebugEnabled()) {
                    this.getLogger().debug("Cache size=" + mCache.size());
                }
            }
        } catch (Exception e) {
            this.getLogger().error("Error in free()", e);
        }
    }

    /**
     *  This method checks if an object is seriazable. FIXME: In the moment only
     *  CachedEventObject or CachedStreamObject are stored.
     *
     * @param the Object to be tested
     * @return  true if the object is storeable
     */
    private boolean checkSerializable(Object object) {
        try {
            if (getLogger().isDebugEnabled()) {
                this.getLogger().debug("Object=" + object);
            }
            if ((object.getClass().getName().equals(
                                "org.apache.cocoon.caching.CachedEventObject"))
                     || (object.getClass().getName().equals(
                                "org.apache.cocoon.caching.CachedStreamObject"))
                     || 
(ClassUtils.implementsInterface(object.getClass().getName(),
                                "org.apache.cocoon.caching.CacheValidity"))) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            this.getLogger().error("Error in checkSerializable()!", e);
            return false;
        }
    }
}
  \ No newline at end of file
  
+/*****************************************************************************
  + * Copyright (C) The Apache Software Foundation. All rights reserved.        
*
  + * ------------------------------------------------------------------------- 
*
  + * This software is published under the terms of the Apache Software License 
*
  + * version 1.1, a copy of which has been included  with this distribution in 
*
  + * the LICENSE file.                                                         
*
  + 
*****************************************************************************/
  +package org.apache.cocoon.jispstore;
  +
  +import org.apache.avalon.framework.activity.Disposable;
  +import org.apache.avalon.framework.component.ComponentException;
  +import org.apache.avalon.framework.component.ComponentManager;
  +import org.apache.avalon.framework.component.Composable;
  +import org.apache.avalon.framework.logger.AbstractLoggable;
  +import org.apache.avalon.framework.parameters.ParameterException;
  +import org.apache.avalon.framework.parameters.Parameterizable;
  +import org.apache.avalon.framework.parameters.Parameters;
  +import org.apache.avalon.framework.thread.ThreadSafe;
  +import org.apache.cocoon.Constants;
  +import org.apache.cocoon.components.store.FilesystemQueue;
  +import org.apache.cocoon.components.store.FilesystemQueueObject;
  +import org.apache.cocoon.components.store.Store;
  +import org.apache.cocoon.components.store.StoreJanitor;
  +import org.apache.cocoon.util.ClassUtils;
  +
  +import java.util.Enumeration;
  +import java.util.Hashtable;
  +import java.util.LinkedList;
  +
  +/**
  + *  This class provides a cache algorithm for the requested documents. It
  + *  combines a HashMap and a LinkedList to create a so called MRU (Most 
Recently
  + *  Used) cache.
  + *
  + * @author     <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a>
  + * @author     <a href="mailto:[EMAIL PROTECTED]">Davanum Srinivas</a>
  + */
  +public final class MRUMemoryStore
  +extends AbstractLoggable
  +implements Store,
  +           Parameterizable,
  +           ThreadSafe,
  +           Composable,
  +           Disposable {
  +
  +    private int mMaxobjects;
  +    private boolean mFilesystem;
  +    private Hashtable mCache;
  +    private LinkedList mMRUList;
  +    private Store mFsstore;
  +    private StoreJanitor mStorejanitor;
  +    private FilesystemQueue mFilesystemQueue;
  +    private ComponentManager mComponetManager;
  +
  +    /**
  +     *  Get the object associated to the given unique key.
  +     *
  +     * @param the Key Object
  +     * @return the Object associated with Key Object
  +     */
  +    public Object get(Object key) {
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("Getting object from memory. Key: " + 
key);
  +        }
  +        Object tmpobject = this.mCache.get(key);
  +        if (tmpobject != null) {
  +            this.mMRUList.remove(key);
  +            this.mMRUList.addFirst(key);
  +            return tmpobject;
  +        }
  +
  +        this.getLogger().debug("Object not found in memory");
  +        if (this.mFilesystem) {
  +            tmpobject = this.mFsstore.get(key);
  +            if (tmpobject == null) {
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Object was NOT found on fs. "
  +                                           + "Looked for: " + key);
  +                }
  +                return null;
  +            } else {
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Object was found on fs");
  +                }
  +                if (!this.mCache.containsKey(key)) {
  +                    this.hold(key, tmpobject);
  +                }
  +                return tmpobject;
  +            }
  +        }
  +        return null;
  +    }
  +
  +    /**
  +     *  Get components of the ComponentManager
  +     *
  +     * @param  the Component Manager
  +     * @exception  ComponentException
  +     */
  +    public void compose(ComponentManager manager)
  +        throws ComponentException {
  +        this.mComponetManager = manager;
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Looking up " 
  +                               + Store.ROLE + "/JispFilesystemStore");
  +        }
  +
  +        this.mFsstore = (Store) manager.lookup(Store.ROLE 
  +                                               + "/JispFilesystemStore");
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Looking up " + StoreJanitor.ROLE);
  +        }
  +        this.mStorejanitor = (StoreJanitor) 
manager.lookup(StoreJanitor.ROLE);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Looking up " + FilesystemQueue.ROLE);
  +        }
  +        this.mFilesystemQueue = (FilesystemQueue) 
manager.lookup(FilesystemQueue.ROLE);
  +    }
  +
  +    /**
  +     *  Configure the MRUMemoryStore. A few options can be used :
  +     *  <UL>
  +     *    <LI> mMaxobjects = how many objects will be stored in memory 
(Default:
  +     *    10 objects)</LI>
  +     *    <LI> mFilesystem = use filesystem storage to keep object persistent
  +     *    (Default: false)</LI>
  +     *  </UL>
  +     *
  +     *
  +     * @param  the Configuration Parameters
  +     * @exception  ParameterException
  +     */
  +
  +    public void parameterize(Parameters params)
  +        throws ParameterException {
  +        this.mMaxobjects = params.getParameterAsInteger("maxobjects", 100);
  +        this.mFilesystem = params.getParameterAsBoolean("filesystem", false);
  +        if ((this.mMaxobjects < 1)) {
  +            throw new ParameterException("MRUMemoryStore maxobjects must be "
  +                                         + "at least 1 milli second!");
  +        }
  +        this.mCache = new Hashtable((int) (this.mMaxobjects * 1.2));
  +        this.mMRUList = new LinkedList();
  +        this.mStorejanitor.register(this);
  +    }
  +
  +    /**
  +     *  Dispose the component
  +     */
  +    public void dispose() {
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("dispose()");
  +        }
  +
  +        if (this.mComponetManager != null) {
  +            this.mComponetManager.release(this.mStorejanitor);
  +            this.mStorejanitor = null;
  +            this.mComponetManager.release(this.mFilesystemQueue);
  +            this.mFilesystemQueue = null;
  +            this.mComponetManager.release(this.mFsstore);
  +            this.mFsstore = null;
  +        }
  +    }
  +
  +    /**
  +     *  Store the given object in a persistent state. It is up to the caller 
to
  +     *  ensure that the key has a persistent state across different JVM
  +     *  executions.
  +     *
  +     * @param the Key Object
  +     * @param the Value Object
  +     */
  +    public void store(Object key, Object value) {
  +        if (this.mFilesystem) {
  +            if (this.checkSerializable(value) &&
  +                    !this.mFsstore.containsKey(key)) {
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Storing object on fs");
  +                }
  +                try {
  +                    this.mFilesystemQueue.insert(new 
FilesystemQueueObject(key, value));
  +                } catch (Exception e) {
  +                    this.getLogger().error("Error storing Object on fs", e);
  +                }
  +            }
  +        }
  +    }
  +
  +    /**
  +     *  This method holds the requested object in a HashMap combined with a
  +     *  LinkedList to create the MRU. It also stores objects onto the 
filesystem
  +     *  if configured.
  +     *
  +     * @param the Key Object
  +     * @param the Value Object
  +     */
  +    public void hold(Object key, Object value) {
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Holding object in memory. key: " + key);
  +            getLogger().debug("Holding object in memory. value: " + value);
  +        }
  +
  +        while (this.mMRUList.size() >= this.mMaxobjects) {
  +            this.free();
  +        }
  +      
  +        this.mCache.put(key, value);
  +        this.mMRUList.remove(key);
  +        this.mMRUList.addFirst(key);
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("Cache size=" + mCache.size());
  +        }
  +    }
  +
  +    /**
  +     *  Remove the object associated to the given key.
  +     *
  +     * @param the Key object
  +     */
  +    public void remove(Object key) {
  +        if (getLogger().isDebugEnabled()) {
  +            this.getLogger().debug("Removing object from store");
  +        }
  +        this.mCache.remove(key);
  +        this.mMRUList.remove(key);
  +        if (this.mFilesystem && key != null) {
  +            this.mFsstore.remove(key);
  +        }
  +    }
  +
  +    /**
  +     *  Indicates if the given key is associated to a contained object.
  +     *
  +     * @param the Key Object
  +     * @return true if Key exists and false if not
  +     */
  +    public boolean containsKey(Object key) {
  +        if (mFilesystem) {
  +            return (this.mCache.containsKey(key) 
  +                    || this.mFsstore.containsKey(key));
  +        } else {
  +            return this.mCache.containsKey(key);
  +        }
  +    }
  +
  +    /**
  +     *  Returns the list of used keys as an Enumeration.
  +     *
  +     * @return    the enumeration of the cache
  +     */
  +    public Enumeration keys() {
  +        return this.mCache.keys();
  +    }
  +
  +    /**
  +     *  Frees some of the fast memory used by this store. It removes the last
  +     *  element in the store.
  +     */
  +    public void free() {
  +        try {
  +            if (this.mCache.size() > 0) {
  +                this.getLogger().debug("Freeing cache");
  +                this.mCache.remove(this.mMRUList.getLast());
  +                this.mMRUList.removeLast();
  +                if (getLogger().isDebugEnabled()) {
  +                    this.getLogger().debug("Cache size=" + mCache.size());
  +                }
  +            }
  +        } catch (Exception e) {
  +            this.getLogger().error("Error in free()", e);
  +        }
  +    }
  +
  +    /**
  +     *  This method checks if an object is seriazable. FIXME: In the moment 
only
  +     *  CachedEventObject or CachedStreamObject are stored.
  +     *
  +     * @param the Object to be tested
  +     * @return  true if the object is storeable
  +     */
  +    private boolean checkSerializable(Object object) {
  +        try {
  +            if (getLogger().isDebugEnabled()) {
  +                this.getLogger().debug("Object=" + object);
  +            }
  +            if ((object.getClass().getName().equals(
  +                                
"org.apache.cocoon.caching.CachedEventObject"))
  +                     || (object.getClass().getName().equals(
  +                                
"org.apache.cocoon.caching.CachedStreamObject"))
  +                     || 
(ClassUtils.implementsInterface(object.getClass().getName(),
  +                                "org.apache.cocoon.caching.CacheValidity"))) 
{
  +                return true;
  +            } else {
  +                return false;
  +            }
  +        } catch (Exception e) {
  +            this.getLogger().error("Error in checkSerializable()!", e);
  +            return false;
  +        }
  +    }
  +}
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to