Patched version of OSCache.java for Hibernate 3 - originally created by Mathias Bogaert.

OSCache.java
import java.util.Properties;
import java.util.Map;

import org.hibernate.util.PropertiesHelper;
import org.hibernate.util.StringHelper;
import org.hibernate.cache.*;

import com.opensymphony.oscache.base.Config;
import com.opensymphony.oscache.base.CacheEntry;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;

/**
 * Adapter for the OSCache implementation
 */
public class OSCache implements Cache {
    
    /** 
     * The <tt>OSCache</tt> cache capacity property suffix. 
     */
    public static final String OSCACHE_CAPACITY = "cache.capacity";

    private static final Properties OSCACHE_PROPERTIES = new Config().getProperties();
	/** 
	 * The OSCache 2.0 cache administrator. 
	 */
	private static GeneralCacheAdministrator cache = new GeneralCacheAdministrator();

    private static Integer capacity = PropertiesHelper.getInteger(OSCACHE_CAPACITY,
                                                                  OSCACHE_PROPERTIES);

    static {
        if (capacity != null) cache.setCacheCapacity(capacity.intValue());
    }
    
	private final int refreshPeriod;
	private final String cron;
	private final String regionName;
    private final String[] regionGroups;
	
	private String toString(Object key) {
		return String.valueOf(key) + "." + regionName;
	}

	public OSCache(int refreshPeriod, String cron, String region) {
		this.refreshPeriod = refreshPeriod;
		this.cron = cron;
		this.regionName = region;
        this.regionGroups = new String[] {region};
	}

	public Object get(Object key) throws CacheException {
		try {
			return cache.getFromCache( toString(key), refreshPeriod, cron );
		}
		catch (NeedsRefreshException e) {
			cache.cancelUpdate( toString(key) );
			return null;
		}
	}

	public void put(Object key, Object value) throws CacheException {
		cache.putInCache( toString(key), value, regionGroups );
	}

	public void remove(Object key) throws CacheException {
		cache.flushEntry( toString(key) );
	}

	public void clear() throws CacheException {
		cache.flushGroup(regionName);
	}

	public void destroy() throws CacheException {
		synchronized (cache) {
		    cache.destroy();
        }
	}

	public void lock(Object key) throws CacheException {
		// local cache, so we use synchronization
	}

	public void unlock(Object key) throws CacheException {
		// local cache, so we use synchronization
	}

	public long nextTimestamp() {
		return Timestamper.next();
	}

	public int getTimeout() {
		return Timestamper.ONE_MS * 60000; //ie. 60 seconds
	}

	public Map toMap() {
		throw new UnsupportedOperationException();
	}    

	public long getElementCountOnDisk() {
		return -1;
	}

	public long getElementCountInMemory() {
		return -1;
	}
    
	public long getSizeInMemory() {
		return -1;
	}

	public String getRegionName() {
		return regionName;
	}

	public void update(Object key, Object value) throws CacheException {
		put(key, value);
	}    

	public Object read(Object key) throws CacheException {
		return get(key);
	}
}