Package org.apache.cocoon.caching.impl

Source Code of org.apache.cocoon.caching.impl.AbstractDoubleMapEventRegistry

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.caching.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.caching.EventRegistry;
import org.apache.cocoon.caching.validity.Event;
import org.apache.commons.collections.map.MultiValueMap;

/**
* This abstract base implementation of <code>EventRegistry</code> stores
* the event-key mappings in a simple pair of <code>MultiMap</code>s.  It
* leaves all persistence to its concrete subclasses.  To protect against
* future confusing inheritance trees, all internal implementation of the
* event-key mapping mechanism is hidden from its subclasses.  If future
* EventRegistry implementations desire to use a different event-key mapping
* strategy but share persistence code, this package should probably be
* refactored to employ composition rather than inheritance.  For now,
* simplicity favors inheritance.
*
* @since 2.1
* @author <a href="mailto:ghoward@apache.org">Geoff Howard</a>
* @version CVS $Id: AbstractDoubleMapEventRegistry.java 433543 2006-08-22 06:22:54Z crossley $
*/

public abstract class AbstractDoubleMapEventRegistry
    extends AbstractLogEnabled
    implements Initializable, EventRegistry, Disposable, ThreadSafe {

    private boolean m_init_success = false;
    private MultiValueMap m_keyMMap;
    private MultiValueMap m_eventMMap;
   
    /**
     * Registers (stores) a two-way mapping between this Event and this
     * PipelineCacheKey for later retrieval.
     *
     * @param e The event to
     * @param key key
     */
    public void register(Event e, Serializable key) {
        synchronized(this) {
            m_keyMMap.put(key,e);
            m_eventMMap.put(e,key);
        }
    }

    /**
     * Remove all registered data.
     */
    public void clear() {
        synchronized(this) {
            m_keyMMap.clear();
            m_eventMMap.clear();
        }
    }

    /**
     * Retrieve all pipeline keys mapped to this event.
     */
    public Serializable[] keysForEvent(Event e) {
        Collection coll = (Collection)m_eventMMap.get(e);
        if (coll==null || coll.isEmpty()) {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("The event map returned empty");
            }
            return null;
        } else {
            return (Serializable[])coll.toArray(new Serializable[coll.size()]);
        }
    }

    /**
     * Return all pipeline keys mapped to any event
     */
    public Serializable[] allKeys() {
        Set keys = this.m_keyMMap.keySet();
        return (Serializable[])keys.toArray(
                new Serializable[keys.size()]);
    }

    /**
     * When a CachedResponse is removed from the Cache, any entries
     * in the event mapping must be cleaned up.
     */
    public void removeKey(Serializable key) {
        Collection coll = (Collection)m_keyMMap.get(key);
        if (coll==null || coll.isEmpty()) {
            return;
        }
        // get the iterator over all matching PCK keyed
        // entries in the key-indexed MMap.
        synchronized(this) {
            Iterator it = coll.iterator();
            while (it.hasNext()) {
                /* remove all entries in the event-indexed map where this
                 * PCK key is the value.
                 */
                Object o = it.next();
                if (o != null) {
                    if (getLogger().isDebugEnabled()) {
                        getLogger().debug("Removing from event mapping: " + o.toString());
                    }
                    m_eventMMap.remove(o,key);           
                }
            }
           
            // remove all entries in the key-indexed map where this PCK key
            // is the key -- confused yet?
            m_keyMMap.remove(key);
        }
    }
   
    /**
     * Recover state by de-serializing the data wrapper.  If this fails
     * a new empty mapping is initialized and the Cache is signalled of
     * the failure so it can clean up.
     */
    public void initialize() throws Exception {
        if (recover()) {
            m_init_success = true;
        }
    }
   
    /**
     * Delegate persistence to subclasses then clean up resources.
     */
    public void dispose() {
        EventRegistryDataWrapper ecdw = wrapRegistry();
        persist(ecdw);
        m_keyMMap.clear();
        m_keyMMap = null;
        m_eventMMap.clear();
        m_eventMMap = null;
    }

    /**
     * @return true if persistent state existed and was recovered successfully.
     */
    public boolean wasRecoverySuccessful() {
        return m_init_success;
    }
   
    protected EventRegistryDataWrapper wrapRegistry() {
        EventRegistryDataWrapper ecdw = new EventRegistryDataWrapper();
        ecdw.setupMaps(this.m_keyMMap, this.m_eventMMap);
        return ecdw;
    }
   
    protected void unwrapRegistry(EventRegistryDataWrapper ecdw) {
        this.m_eventMMap = ecdw.get_eventMap();
        this.m_keyMMap = ecdw.get_keyMap();
    }

    protected final void createBlankCache() {
        this.m_eventMMap = new MultiValueMap();
        this.m_keyMMap = new MultiValueMap();
    }
   
    /**
     * An EventRegistry must recover its persisted data.  Failed
     * recovery must be signaled so that the Cache will know not to
     * serve potentially stale content.  Of course, at first start up
     * failed recovery is a normal state.
     *
     * @return boolean to signal success or failure of recovery. 
     */
    protected abstract boolean recover();
   
    /**
     *  An EventRegistry must persist its data.
     */
    protected abstract void persist(EventRegistryDataWrapper wrapper)
   
}
TOP

Related Classes of org.apache.cocoon.caching.impl.AbstractDoubleMapEventRegistry

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.