Package org.fjank.jcache

Source Code of org.fjank.jcache.CacheAccessImpl2

/*   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;

import java.io.File;
import java.io.Serializable;
import java.util.Iterator;
import javax.util.jcache.Attributes;
import javax.util.jcache.CacheException;
import javax.util.jcache.CacheFullException;
import javax.util.jcache.CacheLoader;
import javax.util.jcache.CacheLogger;
import javax.util.jcache.DiskCacheException;
import javax.util.jcache.NotARetrievableObjectException;
import javax.util.jcache.ObjectNotFoundException;
import org.fjank.jcache.persistence.DiskCache;


/**
* An optimized implementation of CacheAccess.
* No exceptions is thrown excpet in really exceptional situations.
* The Map interface uses this class directly,
* while the old CacheAccessImpl interface should be reprogrammed
* to work with this class.
*/
public final class CacheAccessImpl2 {
    /** a boolean indication wether this obejct is valid or not. */
    private boolean valid = true;
    /** the current region this CacheAccess applies to. */
    private CacheRegion region;
    private Class lastException;
    private String lastMessage;

    /**
     * Creates a new CacheAccessImpl object.
     *
     * @param aCache the the cahce the region belopngs to.
     * @param aRegion the region to get an CacheAccessImpl to.
     */
    CacheAccessImpl2(final CacheRegion aRegion) {
        this.region = aRegion;
    }

    /**
     * terminates the request for a reply from the previous invalidate or
     * update. If a response was requested, the either cancelResponse or
     * waitForResponse should be called to terminate the request and free up
     * related structures. If the waitForResponse method times out,
     * cancelResponse should be called. All response associated with the
     * CacheAccess object are canceled. If the object is local or a reply has
     * not been requested, this call returns immediantely.
     * @todo Implement me.
     */
    public void cancelResponse() {
        if (!isValid()) {
            return;
        }
    }

    /**
     * Will check if close() has been called.
     * @return <code>true</code> if this CacheAccess is valid, <code>false</code>
     * otherwise.
     */
    private boolean isValid() {
        if (this.valid) {
            return true;
        }
        return false;
    }

    /**
     * will return the CacheAccess object to the cache. Any attempt to use a
     * CacheAccess object after it has been closed will be ignored.
     */
    public void close() {
        if (!isValid()) {
            return;
        }
        region = null;
        this.valid = false;
    }

    /**
     * Is used to create a new group object. The attributes of the region or
     * group the new group is associated with are used.
     *
     * @param name the name of the new group.
     */
    public void defineGroup(final String name) {
        if (!isValid()) {
            return;
        }
        defineGroupImpl(name, null, null);
    }

    /**
     * Is used to create a new group object. The attrbutes-parameter are used as
     * the attributes for the new group.
     * @param name the group the new group should be associated with.
     * @param attributes the attributes of the new group.
     *
     */
    public void defineGroup(final String name, final Attributes attributes) {
        if (!isValid()) {
            return;
        }
        defineGroupImpl(name, null, attributes);
    }

    /**
     * Is used to create a new group which belongs to another group.
     * The attributes of the group the new group is attached to are used
     * as the attrbutes for the new group.
     * @param name the name of the new group.
     * @param group the group the new group should be associated with.
     *
     */
    public void defineGroup(final String name, final String group) {
        if (!isValid()) {
            return;
        }
        defineGroupImpl(name, group, null);
    }

    /**
     * Is used to create a new group which belongs to another group.
     * The attrbutes-parameter are used as
     * the attributes for the new group.
     * @param name the name of the new group.
     * @param groupName the group the new group should be associated with.
     * @param attributes the attributes of the new group.
     */
    public void defineGroup(final String name, final String groupName, final Attributes attributes) {
        if (!isValid()) {
            return;
        }
        defineGroupImpl(name, groupName, attributes);
    }

    /**
     * The actual implementation of defineGroup.
     * @param name the name of the group to define.
     * @param groupName the groupName the group should belong to.
     * @param attributes the attributes of the new group.
     */
    private void defineGroupImpl(final String name, final String groupName, final Attributes attributes) {
        if (name == null) {
            return;
        }
        if (name.equals("")) {
            return;
        }
        CacheGroup group;
        if (groupName == null) {
            group = region;
        } else {
            group = region.getGroup(groupName);
            if (group == null) {
                return;
            }
        }
        group.put(new CacheGroup(name, new AttributesImpl(attributes)));
    }

    /**
     * is used to specify the attributes to associate with an object when it is
     * loaded. This can include the loader object, cache event handlers, and
     * spesific attributes for the object such as distribute, spool, etc.
     * Attributes (with the exception of the CacheLoader object itself) can also
     * be specified within the load method of the CacheLoader object using the
     * setAttributes method, if the attributes for an object are not defined,
     * the attributes of the region will be used.
     *
     * @param name the name of the object to associate the attributes with.
     * @param attributes the attributes to associate.
     *
     */
    public void defineObject(final Object name, final Attributes attributes) {
        if (!isValid()) {
            return;
        }
        putImpl(name, null, attributes, NullObject.getInstance());
    }

    /**
     * See defineObject(Object, Attributes)
     *
     * @param name the name of the object to associate the attributes with.
     * @param group the group the object to associate the attributes with is
     *            contained in.
     * @param attributes the attributes to associate.
     *
     */
    public void defineObject(final Object name, final String group, final Attributes attributes) {
        if (!isValid()) {
            return;
        }
        putImpl(name, group, attributes, NullObject.getInstance());
    }

    /**
     * Will invalidate all objects within the region for this CacheAccess
     * object, and the region itself. All references to the objects and any
     * loaders registered will be destroyed. This object is unusable after this
     * operation, will be closed and returned to the cache pool.
     *
     */
    public void destroy() {
        if (!isValid()) {
            return;
        }
        if (region.getName() != null) {
            destroy(region.getName());
        } else {
            region.destroy();
        }
        close();
    }

    /**
     * Will invalidate all objects in the named region and the named region.
     *
     * @param name the name of the region to destroy.
     *
     *
     * @see #destroy()
     */
    public void destroy(final Object name) {
        if (!isValid()) {
            return;
        }
        CacheImpl.getCache(true).destroyRegion(name);
    }

    /**
     * Returns a reference to the object accosiated with the specified name. If
     * the object is a streamAccess object, an {@link java.io.InputStream}is
     * returned, if the object is a disk object, a {@link java.lang.String}
     * containg the full path to the object is returned. The name parameter must
     * override the {@link java.lang.Object#equals(Object)}and {@link
     * java.lang.Object#hashCode()} methods. If a loader object has not been
     * registered for the object the default load method will do a netSearch for
     * the object. A CacheAccess will only maintain a reference to one cached
     * object at any gived time. If get is called multiple times, the object
     * accessed previously, will be released.
     *
     * @param name the name of the object to get.
     *
     * @return a reference to a shared object. Will always return the latest
     *         version of the object.
     *
     */
    public Object get(final Object name) {
        if (!isValid()) {
            return null;
        }
        return getImpl(name, null, null);
    }

    /**
     * Gets the object from the cache. If the object is not currently in the
     * cache and a loader object has been registered, the object will be loaded
     * into the cache with the arguments specified.
     *
     * @param name the name of the object to get.
     * @param arguments the arguments wich is passed to the load method of the
     *            CacheLoader, if registered.
     *
     * @return a reference to a shared object. Will always return the latest
     *         version of the object.
     * @see #get(Object)
     */
    public Object get(final Object name, final Object arguments) {
        if (!isValid()) {
            return null;
        }
        return getImpl(name, null, arguments);
    }

    /**Gets an object from the cache.
     * @param name the name of the object to get
     * @param arguments the arguments to send to the loader, if any.
     * @return the object which is stored in the cache.
     */
    private Object getImpl(final Object name, final String group, final Object arguments) {
        CacheObject objHandle = getCacheObject(name, group);
        if (objHandle == null) {
            return null;
        }
        return getTrueObject(objHandle, arguments);
    }

    private Object getTrueObject(final CacheObject objHandle, final Object arguments) {
        if (objHandle.needsLoading(arguments)) {
            Attributes attribs = objHandle.getAttributes();
            CacheLoader loader = attribs.getLoader();
            Object retrievedObject;
            try {
                retrievedObject = loader.load(objHandle, arguments);
                if (retrievedObject == null) {
                    throw new ObjectNotFoundException("The returned object from the CacheLoader " + loader.getClass().getName() + " was null.");
                }
                if (retrievedObject instanceof CacheOutputStream) {
                    /*
                     * a CacheLoader has created an OutputStream, and loaded the
                     * object. Get the owner object for the stream, and return
                     * the corresponding InputStream. The StreamObjects are
                     * created in the CacheLoader, but the regular memory
                     * objects are created below, is this correct? And a double
                     * creation is also done... once before the load, and once
                     * further down, but this is not called as we have multiple
                     * return points in this method.... well, if it works, dont
                     * touch it! Refactor when we are moving towards a
                     * production release.
                     * 
                     */
                    return ((CacheOutputStream) retrievedObject).getStreamObject().getInputStream();
                } else if (retrievedObject instanceof File) {
                    /*
                     * The object was a DiskObject, return the path to the
                     * diskfile.
                     */
                    return ((File) retrievedObject).getAbsolutePath();
                }
                attribs.setCreateTime(System.currentTimeMillis());
            } catch (CacheException e) {
                this.lastException  = e.getClass();
                this.lastMessage = e.getMessage();
                return null;
            }
            CacheGroup group = objHandle.getGroup();
            CacheObject newRef = new CacheObject(objHandle.getKey(), retrievedObject, group, region, CacheImpl.getCache().getReferenceQueue());
            group.replace(objHandle.getKey(), newRef);
            return newRef.get();
        }
        return objHandle.get();
    }

    /**
     * gets a cacheobject from the cache.
     * @param name the name of the object to get.
     * @param group the group to get the object from.
     * @return an cacheobject.
     *
     */
    private CacheObject getCacheObject(final Object name, final String group) {
        Object object = null;
        //first check the memory cache
        CacheGroup parentCacheObject = region;
        if (group != null) {
            parentCacheObject = region.getGroup(group);
            if (parentCacheObject == null) {
                return null;
            }
        }
        if (parentCacheObject.contains(name)) {
            object = parentCacheObject.get(name);
        } else if (name instanceof Serializable) {
            //second, check the disk cache.
            try {
                DiskCache diskCache = CacheImpl.getCache().getDiskCache();
                if (diskCache != null) {
                    object = diskCache.getObject((Serializable) name);
                    if (object == null) {
                        return null;
                    }
                }
            } catch (DiskCacheException e) {
                this.lastException = DiskCacheException.class;
                this.lastMessage = e.getMessage();
                return null;
            }
        }
        if (object == null) {
            return null;
        }
        if (object instanceof CacheGroup) {
            this.lastException = NotARetrievableObjectException.class;
            this.lastMessage = ("This object is a group and cannot be retrieved.");
            return null;
        }
        CacheObject objHandle = (CacheObject) object;
        return objHandle;
    }

    /**
     * Gets the object from the specified group. If the object is not currently
     * in the cache, and a loader object has been registered, the object will be
     * loaded into the cache and accosiated with the specified group.
     *
     * @param name the name of the object to get.
     * @param group The group the Object is associated with.
     * @param arguments the arguments wich is passed to the load method of the
     *            CacheLoader, if registered.
     *
     * @return a reference to a shared object. Will always return the latest
     *         version of the object.
     *
     * @see #get(Object)
     */
    public Object get(final Object name, final String group, final Object arguments) {
        if (!isValid()) {
            return null;
        }
        return getImpl(name, group, arguments);
    }

    /**
     * Will return an attribute object describing the current attributes
     * associated for the region for this CacheAccess.
     *
     * @return an Attributes object for the region of this CacheAccess.
     *
     */
    public Attributes getAttributes() {
        if (!isValid()) {
            return null;
        }
        return region.getAttributes();
    }

    /**
     * will return an attribute object describing the current attributes
     * associated with the object name.
     *
     * @param name the name of the object to get the attributes for.
     *
     * @return an Attributes object for the named object.
     *
     */
    public Attributes getAttributes(final Object name) {
        if (!isValid()) {
            return null;
        }
        if (name == null) {
            return null;
        }
        Object obj = region.get(name);
        if (obj == null) {
            return null;
        }
        if (obj instanceof CacheObject) {
            return ((CacheObject) obj).getAttributes();
        } else if (obj instanceof CacheGroup) {
            return ((CacheGroup) obj).getAttributes();
        }
        this.lastException = CacheException.class;
        this.lastMessage = "The object " + name + " is not valid. (" + obj.getClass().getName() + ')';
        return null;
    }

    /**
     * will claim ownership for the named object for this instance of
     * CacheAccess. If ownership is not available, this method will block for
     * the specified timeout. The local cache is checked first, if the local
     * cache does not hold ownership of the object, a message is sent to all
     * other caches in the system. Ownership is only relevant for synchronized
     * objects. Ownership is maintained until an update or invalidation
     * completes (this includes the reciept of replies when applicable) or until
     * ownership is explicitly released with a call to releaseOwnership(). An
     * instance of CacheAccess con only hold ownership of one object at a time.
     * Ownership only applies to individual objects, it is not available on
     * groups.
     *
     * @param name the name of the object to claim ownership for.
     * @param timeout number of milliseconds to wait for the ownership claim.
     *
     * @return true if ownership was obtained, false otherwise.
     *
     *
     *
     * @todo not implemented.
     */
    public boolean getOwnership(final Object name, final int timeout) {
        if (!isValid()) {
            return false;
        }
        return false;
    }

    /**
     * Will mark all objects in the region as invalid.
     * @todo distribution of this event
     */
    public void invalidate() {
        if (!isValid()) {
            return;
        }
        region.invalidate();
        // TODO: distribution of this event
    }

    /**
     * Will mark all objects withing the scope of the specified name as invalid.
     * If the name refers to a group object, the invalidate will cascade to all
     * objects associated with the group or any subgroups. Invalidate does not
     * "unregister" an object. The loader object will remain associated with the
     * object name. To completely remove any knowledge of an object from the
     * cache, destroy must be called.
     *
     * @param name the name of the object to invalidate.
     *
     *
     */
    public void invalidate(final Object name) {
        if (!isValid()) {
            return;
        }
        invalidateWithoutDistribution(name);
        if (CacheImpl.getCache().isDistributed()) {
            CacheImpl.getCache().getDistributionEngine().cacheObjectInvalidated(getRegionName(), (Serializable) name);
        }
    }

    private void invalidateWithoutDistribution(final Object name) {
        if (!region.contains(name)) {
            return;
        }
        Object object = region.get(name);
        if (object == null) {
            return;
        }
        if (object instanceof CacheGroup) {
            CacheGroup group = (CacheGroup) object;
            group.invalidate();
        } else {
            //            2004/09-FB
            if (object instanceof CacheObject) {
                CacheObject obj = (CacheObject) object;
                obj.invalidate();
            }
        }
    }

    /**
     * Check the existence of a valid copy of the named object in the region
     * associated with this CacheAccess object.
     *
     * @param name the name of the object to check the existence for.
     *
     * @return true if a valid copy was found, false otherwise.
     */
    public boolean isPresent(final Object name) {
        if (!isValid()) {
            return false;
        }
        return region.contains(name);
    }

    /**
     * This method allows for asynchronous loading of object into the cache.
     * This method will schedule a background task to the registered load
     * method, then return. Any exception that occur during the load, will be
     * written to the log, if logging is on and a log is available.
     *
     * @param name the name of the object to load.
     *
     *
     */
    public void preLoad(final Object name) {
        if (!isValid()) {
            return;
        }
        preLoad(name, null);
    }

    /**
     * See {@link #preLoad(Object)}.
     *
     * @param name the name of the object to load.
     * @param arguments these arguments will be passed to the load method of the
     *            loader object.

     */
    public void preLoad(final Object name, final Object arguments) {
        if (!isValid()) {
            return;
        }
        preLoad(name, null, arguments);
    }

    /**
     * See {@link #preLoad(Object)}.
     *
     * @param name the name of the object to load.
     * @param group the group the new object will be associated with.
     * @param arguments these arguments will be passed to the load method of the
     *            loader object.
     *
     *
     */
    public void preLoad(final Object name, final String group, final Object arguments) {
        if (!isValid()) {
            return;
        }
        if (name == null) {
            //log this, and silently return.
            return;
        }
        final CacheLogger logger = CacheImpl.getCache().getAttributes().getLogger();
        try {
            final CacheObject obj = getCacheObject(name, group);
            final CacheLoader loader = obj.getAttributes().getLoader();
            if (loader == null) {
                throw new ObjectNotFoundException("The object has no CacheLoader associated with it.");
            }
            Runnable runnable = new Runnable() {
                public void run() {
                    try {
                        loader.load(obj, arguments);
                    } catch (CacheException e) {
                        if (logger != null) {
                            logger.log("The object was not found in the cache.", e);
                        }
                    }
                }
            };
            CacheImpl.getCache().getExecPool().execute(runnable);
        } catch (ObjectNotFoundException e) {
            if (logger != null) {
                logger.log("The object was not found in the cache.", e);
            }
        } catch (InterruptedException e) {
            if (logger != null) {
                logger.log("Some strange concurrency issue have occured.", e);
            }
        }
    }

    /**
     * See {@link #put(Object, Object)}
     *
     * @param name the name associated with the object.
     * @param attributes the attributes to associate with the object put into
     *            the cache,
     * @param object the object wich is put in the cache.
     *
     *
     *
     * @see #put(Object,Object)
     */
    public void put(final Object name, final Attributes attributes, final Object object) {
        if (!isValid()) {
            return;
        }
        putImpl(name, null, attributes, object);
    }

    /**
     * See {@link #put(Object, Object)}
     *
     * @param name the name associated with the object.
     * @param group The group associated with the object.
     * @param attributes the attributes to associate with the object put into
     *            the cache,
     * @param object the object wich is put in the cache.
     *
     *
     * @see #put(Object,Object)
     */
    public void put(final Object name, final String group, final Attributes attributes, final Object object) {
        putImpl(name, group, attributes, object);
    }

    /**Gets the current number of objects in the cache.
     * @return The current number of objects in the cache.
     */
    private int getCurrentObjectCount() {
        int count = 0;
        count += CacheImpl.getCache().getRegion().getObjectCount();
        Iterator regions = CacheImpl.getCache().userRegionNames();
        while (regions.hasNext()) {
            count += CacheImpl.getCache().getRegion(regions.next()).getObjectCount();
        }
        return count;
    }

    /**
     * Will return the last exception which occured.
     * If no exception has occured, this will return null.
     *
     * @param cached if <code>true</code>, a cached exception is returned. The stacktrace of this exception
     * will not be correct. Otherwise a new CacheException will be created. if you use <code>false</code> as the cache
     * parameter, be adviced that this will be detrimental for performance.
     * @return the last CacheException which occured.
     */
    public CacheException getException(boolean cached) {
        if (lastException == null) {
            return null;
        }
        try {
            CacheException ex = (CacheException) lastException.newInstance();
            ex.setMessage(lastMessage);
            this.lastException = null;
            this.lastMessage = null;
            return ex;
        } catch (InstantiationException e) {
            throw new IllegalStateException(e.getMessage() + ":" + lastMessage);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException(e.getMessage() + ":" + lastMessage);
        }
    }

    /**
     * puts an object into the cache without distribution.
     * @param name the name of the object
     * @param group the group to put the object into.
     * @param attributes the attributoes belonging to the object
     * @param object the actual object to put into the cache,.
     * @return returns a boolean indicating wether the return was successfull or not. To get the errortype
     * and errormessage you can call
     */
    private boolean putImpl(final Object name, final String group, final Attributes attributes, final Object object) {
        CacheGroup objGr = region;
        if (group != null) {
            objGr = region.getGroup(group);
            if (objGr == null) {
                this.lastException = ObjectNotFoundException.class;
                this.lastMessage = "The object " + group + " is not present in this cache.";
                return false;
            }
        }
        CacheObject o = new CacheObject(name, object, objGr, region, CacheImpl.getCache().getReferenceQueue());
        o.setAttributes(attributes);
        int maxObjects = CacheImpl.getCache().getAttributes().getMaxObjects();
        int currentObjectCount = getCurrentObjectCount();
        if (currentObjectCount >= maxObjects) {
            DiskCache diskCache = CacheImpl.getCache().getDiskCache();
            if (diskCache == null) {
                //no disk, and memory is full.
                this.lastException = CacheFullException.class;
                this.lastMessage = "The maximum number of objects in the cache has been reached.";
                return false;
            }
            boolean updated = diskCache.update(o);
            if (!updated) {
                this.lastException = CacheFullException.class;
                this.lastMessage = "The maximum size for the diskCache has been reached.";
            }
            return updated;
        }
        if ((attributes != null) && (attributes.getSize() != 0)) {
            if ((region.getCurrentSize() + attributes.getSize()) > (CacheImpl.getCache().getAttributes().getMemoryCacheSize() * 1024 * 1024)) {
                DiskCache diskCache = CacheImpl.getCache().getDiskCache();
                if (diskCache == null) {
                    //no disk, and memory is full.
                    this.lastException = CacheFullException.class;
                    this.lastMessage = "The maximum size for the memory cache has been reached.";
                    return false;
                }
                boolean updated = diskCache.update(o);
                if (!updated) {
                    this.lastException = CacheFullException.class;
                    this.lastMessage = "The maximum size for the diskCache has been reached.";
                }
                return updated;
            }
        }
        objGr.put(name, o, object);
        return true;
    }

    /**
     * inserts the specified object into the cache, and associates it with the
     * specified name. Names are scoped to a region, so they must be unique
     * within the region they are placed. This method is intended for very
     * simple caching situations. In general it is better to create a
     * CacheLoader object and allow the cache to manage the creation and loading
     * of objects. Default attributes are assumed.
     *
     * @param name the name associated with the object.
     * @param object the object wich is put in the cache.
     *
     *
     */
    public boolean put(final Object name, final Object object) {
        if (!isValid()) {
            return false;
        }
        return putImpl(name, null, null, object);
    }

    /**
     * See {@link #put(Object, Object)}
     *
     * @param name the name associated with the object.
     * @param group The group associated with the object.
     * @param object the object wich is put in the cache.
     *
     *
     *
     * @see #put(Object, Object)
     */
    public void put(Object name, String group, Object object) {
        if (!isValid()) {
            return;
        }
        putImpl(name, group, null, object);
    }

    /**
     * Is called to explicitly give up ownership for an object. Ownership is
     * only relevant for synchronized objects. If ownership is not held,
     * releaseOwnership is ignored.
     *
     *
     */
    public void releaseOwnership() {
        if (!isValid()) {
            return;
        }
    }

    /**
     * Will create a new version of the object indentified by the name,
     * replacing the current version with the object specified. If the object
     * doesn't exist in the cache, replace is equivalent to a put. The
     * attributes will be inherited from the existing object or if no object
     * exists, from the group or region the object associated with. Names are in
     * the scope of a region so they must be unique within the region they are
     * placed. This method is not valid on a disk, StreamAccess or Group Object.
     *
     * @param name the name of the object to replace.
     * @param object The new object to be put in the cache.
     *
     * @return a reference to the newly replaced object.
     *
     */
    public Object replace(Object name, Object object) {
        if (!isValid()) {
            return null;
        }
        if (name == null)
            return null;
        if (object == null)
            return null;
        Object replacedObject = replaceWithoutDistribution(name, object);
        if (CacheImpl.getCache().isDistributed()) {
            CacheImpl.getCache().getDistributionEngine().cacheObjectUpdated(getRegionName(), null, (Serializable) name, (Serializable) object);
        }
        return replacedObject;
    }

    /**
     * @todo refactor me to another place. I really do not belong here, and I do not want to be public!
     *
     */
    public Object replaceWithoutDistribution(Object name, Object object) {
        if (!isValid()) {
            return null;
        }
        return region.replace(name, new CacheObject(name, object, region, region, CacheImpl.getCache().getReferenceQueue()));
    }

    /**
     * See replace(Object, Object)
     *
     * @param name the name of the object to replace.
     * @param group the group the object is associated with.
     * @param object The new object to be put in the cache.
     *
     * @return a reference to the newly replaced object.
     *
     */
    public Object replace(Object name, String group, Object object) {
        if (!isValid()) {
            return null;
        }
        if (name == null)
            return null;
        if (object == null)
            return null;
        if (group == null)
            return null;
        Object replacedObject = replaceWithoutDistribution(name, group, object);
        if (CacheImpl.getCache().isDistributed()) {
            CacheImpl.getCache().getDistributionEngine().cacheObjectUpdated(getRegionName(), group, (Serializable) name, (Serializable) object);
        }
        return replacedObject;
    }

    /**
     * @todo refactor me to another place. I really do not belong here, and I do not want to be public!
     *
     */
    public Object replaceWithoutDistribution(Object name, String group, Object object) {
        if (!isValid()) {
            return null;
        }
        CacheGroup cachegroup = (CacheGroup) region.get(group);
        if (cachegroup == null)
            return null;
        return cachegroup.replace(name, new CacheObject(name, object, region, region, CacheImpl.getCache().getReferenceQueue()));
    }

    /**
     * allows for some attributes of a region to be reset. The attributes are
     * expiration time attributes, time to live, default time to live, idle time
     * and event handlers. The cacheloader and attributes explicitly set can't
     * be reset with this method. To do this the object must be destroyed and
     * redefined change those parameters. Changing the default settings on
     * groups and regions will not affect existing objects. Only objects loaded
     * after the reset will use the new defaults.
     *
     * @param attributes The new attributes to append to the region.
     *
     */
    public void resetAttributes(Attributes attributes) {
        if (!isValid()) {
            return;
        }
        Attributes att = region.getAttributes();
        att.reset();
        att.applyAttributes(attributes);
    }

    /**
     * See {@link #resetAttributes(Attributes)}.
     *
     * @param name the name of the region to reset the attributes for.
     * @param attributes the new attributes for the named region.
     *
     */
    public void resetAttributes(Object name, Attributes attributes) {
        if (!isValid()) {
            return;
        }
        Attributes att = CacheImpl.getCache(true).getRegion(name).getAttributes();
        att.reset();
        att.applyAttributes(attributes);
    }

    /**
     * Will cause all objects within the region of this CacheAccess to be saved
     * to the disk cache. All exceptions encountered will be logged if logging
     * is on. Local objects will be saved in the process specific cache,
     * distributed objects will be saved in the machine global disk cache.
     *
     *
     */
    public void save() {
        if (!isValid()) {
            return;
        }
        saveImpl(region);
    }

    /**
     * Implements the stuff mentioned in save().
     * This method does not throws any exceptions, cause all exceptions should be logged instead.
     * @see CacheAccessImpl2#save()
     * @todo Implement me.
     * @param region the region to save.
     */
    private void saveImpl(CacheRegion region) {
    }

    /**
     * See {@link #save()}. If the name refers to a specific object and that
     * object does not implement the {@link java.io.Serializable}interface, a
     * {@link CacheException}will be logged. If the name referenced a group or
     * a region, all objects not implementing {@link java.io.Serializable}is
     * ignored.
     *
     * @param name the name of the object to save.
     *
     */
    public void save(Object name) {
        if (!isValid()) {
            return;
        }
        saveImpl(CacheImpl.getCache().getRegion(name));
    }

    /**
     * May be used to wait for replies returned from invalidates or updates when
     * a reply is requested. This method will block the calling thread until all
     * the responses associated with the CacheAccess object have been retrieved
     * or the time indicated in the timeout variable has expired. If this method
     * times out and the caller does not intend to call waitForResponse again on
     * this object, cancelResponse should be called. If the object is local or a
     * reply has not been requested, this call return immediately.
     *
     * @param timeout the maximum number of milliseconds to wait for remote
     *            caches to reply.
     *
     */
    public void waitForResponse(int timeout) {
        if (!isValid()) {
            return;
        }
    }

    /**
     * Gets the region this access applies to.
     *
     * @return the region this access applies to.
     */
    public CacheRegion getRegion() {
        return region;
    }

    private String getRegionName() {
        return region.getName() == null ? null : region.getName().toString();
    }
}
TOP

Related Classes of org.fjank.jcache.CacheAccessImpl2

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.