KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > caching > impl > AbstractDoubleMapEventRegistry


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.caching.impl;
17
18 import java.io.Serializable JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import org.apache.avalon.framework.activity.Disposable;
24 import org.apache.avalon.framework.activity.Initializable;
25 import org.apache.avalon.framework.logger.AbstractLogEnabled;
26 import org.apache.avalon.framework.thread.ThreadSafe;
27 import org.apache.cocoon.caching.EventRegistry;
28 import org.apache.cocoon.caching.validity.Event;
29 import org.apache.commons.collections.MultiHashMap;
30
31 /**
32  * This abstract base implementation of <code>EventRegistry</code> stores
33  * the event-key mappings in a simple pair of <code>MultiMap</code>s. It
34  * leaves all persistence to its concrete subclasses. To protect against
35  * future confusing inheritance trees, all internal implementation of the
36  * event-key mapping mechanism is hidden from its subclasses. If future
37  * EventRegistry implementations desire to use a different event-key mapping
38  * strategy but share persistence code, this package should probably be
39  * refactored to employ composition rather than inheritance. For now,
40  * simplicity favors inheritance.
41  *
42  * @since 2.1
43  * @author <a HREF="mailto:ghoward@apache.org">Geoff Howard</a>
44  * @version CVS $Id: AbstractDoubleMapEventRegistry.java 30932 2004-07-29 17:35:38Z vgritsenko $
45  */

46
47 public abstract class AbstractDoubleMapEventRegistry
48     extends AbstractLogEnabled
49     implements Initializable, EventRegistry, Disposable, ThreadSafe {
50
51     private boolean m_init_success = false;
52     private MultiHashMap m_keyMMap;
53     private MultiHashMap m_eventMMap;
54     
55     /**
56      * Registers (stores) a two-way mapping between this Event and this
57      * PipelineCacheKey for later retrieval.
58      *
59      * @param e The event to
60      * @param key key
61      */

62     public void register(Event e, Serializable JavaDoc key) {
63         synchronized(this) {
64             m_keyMMap.put(key,e);
65             m_eventMMap.put(e,key);
66         }
67     }
68
69     /**
70      * Remove all registered data.
71      */

72     public void clear() {
73         synchronized(this) {
74             m_keyMMap.clear();
75             m_eventMMap.clear();
76         }
77     }
78
79     /**
80      * Retrieve all pipeline keys mapped to this event.
81      */

82     public Serializable JavaDoc[] keysForEvent(Event e) {
83         Collection JavaDoc coll = (Collection JavaDoc)m_eventMMap.get(e);
84         if (coll==null || coll.isEmpty()) {
85             if (getLogger().isDebugEnabled()) {
86                 getLogger().debug("The event map returned empty");
87             }
88             return null;
89         } else {
90             return (Serializable JavaDoc[])coll.toArray(new Serializable JavaDoc[coll.size()]);
91         }
92     }
93
94     /**
95      * Return all pipeline keys mapped to any event
96      */

97     public Serializable JavaDoc[] allKeys() {
98         Set JavaDoc keys = this.m_keyMMap.keySet();
99         return (Serializable JavaDoc[])keys.toArray(
100                 new Serializable JavaDoc[keys.size()]);
101     }
102
103     /**
104      * When a CachedResponse is removed from the Cache, any entries
105      * in the event mapping must be cleaned up.
106      */

107     public void removeKey(Serializable JavaDoc key) {
108         Collection JavaDoc coll = (Collection JavaDoc)m_keyMMap.get(key);
109         if (coll==null || coll.isEmpty()) {
110             return;
111         }
112         // get the iterator over all matching PCK keyed
113
// entries in the key-indexed MMap.
114
synchronized(this) {
115             Iterator JavaDoc it = coll.iterator();
116             while (it.hasNext()) {
117                 /* remove all entries in the event-indexed map where this
118                  * PCK key is the value.
119                  */

120                 Object JavaDoc o = it.next();
121                 if (o != null) {
122                     if (getLogger().isDebugEnabled()) {
123                         getLogger().debug("Removing from event mapping: " + o.toString());
124                     }
125                     m_eventMMap.remove(o,key);
126                 }
127             }
128             
129             // remove all entries in the key-indexed map where this PCK key
130
// is the key -- confused yet?
131
m_keyMMap.remove(key);
132         }
133     }
134     
135     /**
136      * Recover state by de-serializing the data wrapper. If this fails
137      * a new empty mapping is initialized and the Cache is signalled of
138      * the failure so it can clean up.
139      */

140     public void initialize() throws Exception JavaDoc {
141         if (recover()) {
142             m_init_success = true;
143         }
144     }
145     
146     /**
147      * Delegate persistence to subclasses then clean up resources.
148      */

149     public void dispose() {
150         EventRegistryDataWrapper ecdw = wrapRegistry();
151         persist(ecdw);
152         m_keyMMap.clear();
153         m_keyMMap = null;
154         m_eventMMap.clear();
155         m_eventMMap = null;
156     }
157
158     /**
159      * @return true if persistent state existed and was recovered successfully.
160      */

161     public boolean wasRecoverySuccessful() {
162         return m_init_success;
163     }
164     
165     protected EventRegistryDataWrapper wrapRegistry() {
166         EventRegistryDataWrapper ecdw = new EventRegistryDataWrapper();
167         ecdw.setupMaps(this.m_keyMMap, this.m_eventMMap);
168         return ecdw;
169     }
170     
171     protected void unwrapRegistry(EventRegistryDataWrapper ecdw) {
172         this.m_eventMMap = ecdw.get_eventMap();
173         this.m_keyMMap = ecdw.get_keyMap();
174     }
175
176     protected final void createBlankCache() {
177         // TODO: don't hardcode initial size
178
this.m_eventMMap = new MultiHashMap(100);
179         this.m_keyMMap = new MultiHashMap(100);
180     }
181     
182     /**
183      * An EventRegistry must recover its persisted data. Failed
184      * recovery must be signaled so that the Cache will know not to
185      * serve potentially stale content. Of course, at first start up
186      * failed recovery is a normal state.
187      *
188      * @return boolean to signal success or failure of recovery.
189      */

190     protected abstract boolean recover();
191     
192     /**
193      * An EventRegistry must persist its data.
194      */

195     protected abstract void persist(EventRegistryDataWrapper wrapper);
196     
197 }
198
Popular Tags