001: ///////////////////////////////
002: // Makumba, Makumba tag library
003: // Copyright (C) 2000-2003 http://www.makumba.org
004: //
005: // This library is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU Lesser General Public
007: // License as published by the Free Software Foundation; either
008: // version 2.1 of the License, or (at your option) any later version.
009: //
010: // This library is distributed in the hope that it will be useful,
011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: // Lesser General Public License for more details.
014: //
015: // You should have received a copy of the GNU Lesser General Public
016: // License along with this library; if not, write to the Free Software
017: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: //
019: // -------------
020: // $Id: NamedResources.java 1688 2007-09-25 12:54:46Z manuel_gay $
021: // $Name$
022: /////////////////////////////////////
023:
024: package org.makumba.commons;
025:
026: import java.util.ArrayList;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Vector;
032:
033: /**
034: * An instance of this class holds a cache of resources. If a resource is requested but is not present, it is produced
035: * using the associated NamedResourceFactory, in a thread-safe way
036: *
037: * @author Cristian Bogdan
038: * @version $Id: NamedResources.java 1688 2007-09-25 12:54:46Z manuel_gay $
039: * @see org.makumba.commons.NamedResourceFactory
040: */
041: public class NamedResources implements java.io.Serializable {
042:
043: private static final long serialVersionUID = 1L;
044:
045: static boolean soft_static_caches;
046: static {
047: String soft = null;
048: try {
049: soft = System.getProperty("makumba.soft-static-caches");
050: } catch (SecurityException se) {
051: } // for applets
052: if (soft != null)
053: soft = soft.trim();
054: soft_static_caches = "true".equals(soft);
055: }
056:
057: NamedResourceFactory f;
058:
059: String name;
060:
061: Map values = new HashMap();
062:
063: int hits, misses;
064:
065: static List staticCaches = new ArrayList();
066:
067: static Vector allCaches = new Vector();
068:
069: /**
070: * Cleans-up all the static and soft caches
071: */
072: static public void cleanup() {
073: for (int i = 0; i < staticCaches.size(); i++)
074: ((NamedResources) staticCaches.get(i)).close();
075: staticCaches.clear();
076: for (int i = 0; i < allCaches.size(); i++)
077: ((java.lang.ref.WeakReference) allCaches.elementAt(i))
078: .clear();
079: allCaches.clear();
080:
081: }
082:
083: /**
084: * Creates a static cache
085: * @param name the name of the cache
086: * @param fact the {@link NamdedResourceFactory} used to create the cache
087: * @param soft <code>true</code> if this should be a soft cache
088: * @return The identifier of this cache
089: */
090: public synchronized static int makeStaticCache(String name,
091: NamedResourceFactory fact, boolean soft) {
092: staticCaches.add(soft ? new SoftNamedResources(name, fact)
093: : new NamedResources(name, fact));
094: return staticCaches.size() - 1;
095: }
096:
097: /**
098: * Creates a static cache
099: * @param name the name of the cache
100: * @param fact the NamdedResourceFactory used to create the cache
101: * @return The identifier of this cache
102: */
103: public synchronized static int makeStaticCache(String name,
104: NamedResourceFactory fact) {
105: return makeStaticCache(name, fact, soft_static_caches);
106: }
107:
108: /**
109: * Gets the static cache identified by n
110: * @param n the index of the cached object in the cache
111: * @return The cache of resources
112: */
113: public static NamedResources getStaticCache(int n) {
114: return (NamedResources) staticCaches.get(n);
115: }
116:
117: /**
118: * Cleans the given cache. Use this for developping purposes.
119: * @param n the index of the cache to be cleaned
120: */
121: public static void cleanStaticCache(int n) {
122: ((NamedResources) staticCaches.get(n)).values = new HashMap();
123: }
124:
125: /**
126: * Wraps information about the cache into a Map
127: * @return A Map having as keys the names of the caches and as value an array of int containing the size, hits and misses of each cache
128: */
129: public static Map getCacheInfo() {
130: Map m = new HashMap();
131: for (int i = 0; i < allCaches.size(); i++) {
132: NamedResources nr = (NamedResources) ((java.lang.ref.WeakReference) allCaches
133: .elementAt(i)).get();
134: if (nr == null)
135: continue;
136: int[] n = (int[]) m.get(nr.getName());
137: if (n == null) {
138: m.put(nr.getName(), n = new int[3]);
139: }
140: n[0] += nr.size();
141: n[1] += nr.hits;
142: n[2] += nr.misses;
143: }
144: return m;
145: }
146:
147: /**
148: * Initializes using the given factory
149: * @param name the name of the NamedResources object to initalise
150: * @param f the {@link NamedResourceFactory} used to construct the NamedResource
151: */
152: public NamedResources(String name, NamedResourceFactory f) {
153: this .name = name;
154: this .f = f;
155: allCaches.addElement(new java.lang.ref.WeakReference(this ));
156: }
157:
158: /**
159: * Checks if a resource is known
160: * @param name the name of the resource to be checked
161: * @return <code>true</code> if the resource is known, <code>false</code> otherwise
162: */
163: public boolean knowResource(Object name) {
164: try {
165: return values.get(f.getHashObject(name)) != null;
166: } catch (Throwable t) {
167: throw new RuntimeWrappedException(t);
168: }
169: }
170:
171: /**
172: * Whatever supplementary stuff the factory wants to keep
173: * @return An object with the supplementary things the factory may need
174: */
175: public Object getSupplementary() {
176: return f.supplementary;
177: }
178:
179: /**
180: * Gets a specific resource. If it doesn't exist, calls the NamedResourceFactory to produce it
181: * @param name the name of the resource to get
182: * @return The resource
183: */
184: public Object getResource(Object name) {
185: NameValue nv = null;
186:
187: synchronized (this ) {
188: Object hash = null;
189: try {
190: hash = f.getHashObject(name);
191: } catch (Throwable t) {
192: throw new RuntimeWrappedException(t);
193: }
194: nv = getNameValue(name, hash);
195: }
196: return nv.getResource();
197: }
198:
199: protected NameValue getNameValue(Object name, Object hash) {
200: NameValue nv = (NameValue) values.get(hash);
201: if (nv == null) {
202: misses++;
203: values.put(hash, nv = new NameValue(name, hash, f));
204: } else
205: hits++;
206: return nv;
207: }
208:
209: public int size() {
210: return values.size();
211: }
212:
213: public String getName() {
214: return name;
215: }
216:
217: /**
218: * Closes each contained object by calling its close() method, if any
219: */
220: public void close() {
221: for (Iterator i = values.keySet().iterator(); i.hasNext();) {
222: Object nvo = values.get(i.next());
223: if (nvo instanceof java.lang.ref.Reference) {
224: nvo = ((java.lang.ref.Reference) nvo).get();
225: if (nvo == null)
226: continue;
227: }
228:
229: if (!(((NameValue) nvo).returner instanceof NameValue))
230: continue;
231:
232: Object o = ((NameValue) nvo).getResource();
233:
234: java.lang.reflect.Method m = null;
235: if (o == null)
236: continue;
237: try {
238: m = o.getClass().getMethod("close",
239: ((java.lang.Class[]) null));
240: } catch (NoSuchMethodException e) {
241: // we assume homogenous caches
242: return;
243: }
244: try {
245: m.invoke(o, ((java.lang.Object[]) null));
246: } catch (Throwable t) {
247: t.printStackTrace();
248: }
249: }
250: values.clear();
251: }
252: }
|