/*
 * 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.
 */

/* $Id: SoftMapCache.java 750418 2009-03-05 11:03:54Z vhennebert $ */

package org.apache.xmlgraphics.image.loader.util;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Collections;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Provides a simple cache using soft references and storing the values in a Map. The keys into the Map are hard references, the values are referenced through soft references. The collected values are cleaned up through a ReferenceQueue.
/** * Provides a simple cache using soft references and storing the values in a Map. The keys into * the Map are hard references, the values are referenced through soft references. The collected * values are cleaned up through a ReferenceQueue. */
public class SoftMapCache {
logger
/** logger */
private static Log log = LogFactory.getLog(SoftMapCache.class); private Map map; private ReferenceQueue refQueue = new ReferenceQueue();
Creates a new soft cache.
Params:
  • synched – true if the Map containing the values should by synchronized
/** * Creates a new soft cache. * @param synched true if the Map containing the values should by synchronized */
public SoftMapCache(boolean synched) { this.map = new java.util.HashMap(); if (synched) { this.map = Collections.synchronizedMap(this.map); } }
Returns the value associated with the given key. If the value is not found or the value has been collected, null is returned.
Params:
  • key – the key
Returns:the requested value or null
/** * Returns the value associated with the given key. If the value is not found or the value * has been collected, null is returned. * @param key the key * @return the requested value or null */
public Object get(Object key) { Reference ref = (Reference)map.get(key); return getReference(key, ref); }
Removed the value associated with the given key. The value that is removed is returned as the methods result. If the value is not found or the value has been collected, null is returned.
Params:
  • key – the key
Returns:the requested value or null
/** * Removed the value associated with the given key. The value that is removed is returned * as the methods result. If the value is not found or the value has been collected, * null is returned. * @param key the key * @return the requested value or null */
public Object remove(Object key) { Reference ref = (Reference)map.remove(key); return getReference(key, ref); } private Object getReference(Object key, Reference ref) { Object value = null; if (ref != null) { value = ref.get(); if (value == null) { //Remove key if its value has been garbage collected if (log.isTraceEnabled()) { log.trace("Image has been collected: " + key); } checkReferenceQueue(); } } return value; }
Put a new value in the cache overwriting any existing value with the same key.
Params:
  • key – The key
  • value – the value
/** * Put a new value in the cache overwriting any existing value with the same key. * @param key The key * @param value the value */
public void put(Object key, Object value) { map.put(key, wrapInReference(value, key)); }
Clears the cache.
/** * Clears the cache. */
public void clear() { map.clear(); }
Triggers some house-keeping, i.e. processes any pending objects in the reference queue.
/** * Triggers some house-keeping, i.e. processes any pending objects in the reference queue. */
public void doHouseKeeping() { checkReferenceQueue(); } private Reference wrapInReference(Object obj, Object key) { return new SoftReferenceWithKey(obj, key, refQueue); }
Checks the reference queue if any references have been cleared and removes them from the cache.
/** * Checks the reference queue if any references have been cleared and removes them from the * cache. */
private void checkReferenceQueue() { SoftReferenceWithKey ref; while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) { if (log.isTraceEnabled()) { log.trace("Removing ImageInfo from ref queue: " + ref.getKey()); } map.remove(ref.getKey()); } } }