///////////////////////////////
// Makumba, Makumba tag library
// Copyright (C) 2000-2003 http://www.makumba.org
//
// 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
//
// -------------
// $Id: NamedResources.java 1688 2007-09-25 12:54:46Z manuel_gay $
// $Name$
/////////////////////////////////////
package org.makumba.commons;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
/**
* An instance of this class holds a cache of resources. If a resource is requested but is not present, it is produced
* using the associated NamedResourceFactory, in a thread-safe way
*
* @author Cristian Bogdan
* @version $Id: NamedResources.java 1688 2007-09-25 12:54:46Z manuel_gay $
* @see org.makumba.commons.NamedResourceFactory
*/
public class NamedResources implements java.io.Serializable {
private static final long serialVersionUID = 1L;
static boolean soft_static_caches;
static {
String soft = null;
try {
soft = System.getProperty("makumba.soft-static-caches");
} catch (SecurityException se) {
} // for applets
if (soft != null)
soft = soft.trim();
soft_static_caches = "true".equals(soft);
}
NamedResourceFactory f;
String name;
Map values = new HashMap();
int hits, misses;
static List staticCaches = new ArrayList();
static Vector allCaches = new Vector();
/**
* Cleans-up all the static and soft caches
*/
static public void cleanup() {
for (int i = 0; i < staticCaches.size(); i++)
((NamedResources) staticCaches.get(i)).close();
staticCaches.clear();
for (int i = 0; i < allCaches.size(); i++)
((java.lang.ref.WeakReference) allCaches.elementAt(i)).clear();
allCaches.clear();
}
/**
* Creates a static cache
* @param name the name of the cache
* @param fact the {@link NamdedResourceFactory} used to create the cache
* @param soft <code>true</code> if this should be a soft cache
* @return The identifier of this cache
*/
public synchronized static int makeStaticCache(String name, NamedResourceFactory fact, boolean soft) {
staticCaches.add(soft ? new SoftNamedResources(name, fact) : new NamedResources(name, fact));
return staticCaches.size() - 1;
}
/**
* Creates a static cache
* @param name the name of the cache
* @param fact the NamdedResourceFactory used to create the cache
* @return The identifier of this cache
*/
public synchronized static int makeStaticCache(String name, NamedResourceFactory fact) {
return makeStaticCache(name, fact, soft_static_caches);
}
/**
* Gets the static cache identified by n
* @param n the index of the cached object in the cache
* @return The cache of resources
*/
public static NamedResources getStaticCache(int n) {
return (NamedResources) staticCaches.get(n);
}
/**
* Cleans the given cache. Use this for developping purposes.
* @param n the index of the cache to be cleaned
*/
public static void cleanStaticCache(int n) {
((NamedResources) staticCaches.get(n)).values = new HashMap();
}
/**
* Wraps information about the cache into a Map
* @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
*/
public static Map getCacheInfo() {
Map m = new HashMap();
for (int i = 0; i < allCaches.size(); i++) {
NamedResources nr = (NamedResources) ((java.lang.ref.WeakReference) allCaches.elementAt(i)).get();
if (nr == null)
continue;
int[] n = (int[]) m.get(nr.getName());
if (n == null) {
m.put(nr.getName(), n = new int[3]);
}
n[0] += nr.size();
n[1] += nr.hits;
n[2] += nr.misses;
}
return m;
}
/**
* Initializes using the given factory
* @param name the name of the NamedResources object to initalise
* @param f the {@link NamedResourceFactory} used to construct the NamedResource
*/
public NamedResources(String name, NamedResourceFactory f) {
this.name = name;
this.f = f;
allCaches.addElement(new java.lang.ref.WeakReference(this));
}
/**
* Checks if a resource is known
* @param name the name of the resource to be checked
* @return <code>true</code> if the resource is known, <code>false</code> otherwise
*/
public boolean knowResource(Object name) {
try {
return values.get(f.getHashObject(name)) != null;
} catch (Throwable t) {
throw new RuntimeWrappedException(t);
}
}
/**
* Whatever supplementary stuff the factory wants to keep
* @return An object with the supplementary things the factory may need
*/
public Object getSupplementary() {
return f.supplementary;
}
/**
* Gets a specific resource. If it doesn't exist, calls the NamedResourceFactory to produce it
* @param name the name of the resource to get
* @return The resource
*/
public Object getResource(Object name) {
NameValue nv = null;
synchronized (this) {
Object hash = null;
try {
hash = f.getHashObject(name);
} catch (Throwable t) {
throw new RuntimeWrappedException(t);
}
nv = getNameValue(name, hash);
}
return nv.getResource();
}
protected NameValue getNameValue(Object name, Object hash) {
NameValue nv = (NameValue) values.get(hash);
if (nv == null) {
misses++;
values.put(hash, nv = new NameValue(name, hash, f));
} else
hits++;
return nv;
}
public int size() {
return values.size();
}
public String getName() {
return name;
}
/**
* Closes each contained object by calling its close() method, if any
*/
public void close() {
for (Iterator i = values.keySet().iterator(); i.hasNext();) {
Object nvo = values.get(i.next());
if (nvo instanceof java.lang.ref.Reference) {
nvo = ((java.lang.ref.Reference) nvo).get();
if (nvo == null)
continue;
}
if (!(((NameValue) nvo).returner instanceof NameValue))
continue;
Object o = ((NameValue) nvo).getResource();
java.lang.reflect.Method m = null;
if (o == null)
continue;
try {
m = o.getClass().getMethod("close", ((java.lang.Class[]) null));
} catch (NoSuchMethodException e) {
// we assume homogenous caches
return;
}
try {
m.invoke(o, ((java.lang.Object[]) null));
} catch (Throwable t) {
t.printStackTrace();
}
}
values.clear();
}
}
|