package rocks.inspectit.agent.java.util; import java.lang.ref.SoftReference; import java.util.AbstractList; import java.util.ArrayList; import java.util.List; /** * This list is used to store elements as weak references. Especially useful to save a list of * {@link ClassLoader} objects in a JEE environment. Objects are added and removed as in any other * list, but can turn to become null. Calling {@link #removeAllNullElements()} is the only way to * get rid of the garbage collected elements. {@link #getHardReferences()} returns an * {@link ArrayList} suppressing all the references in this list which are already removed by the * garbage collector. * * @param <T> * The class contained in the list. * * @author Patrice Bouillet * */ public class WeakList<T> extends AbstractList<T> { /** * Stores the weak references to the object. */ private List<SoftReference<T>> refs = new ArrayList<SoftReference<T>>(); /** * Returns the hard reference. * * @param o * The object. * @return The reference to the object. */ private T getHardReference(SoftReference<T> o) { if (null != o) { return o.get(); } else { return null; } } /** * {@inheritDoc} */ @Override public T get(int index) { return getHardReference(refs.get(index)); } /** * {@inheritDoc} */ @Override public boolean add(T o) { return refs.add(new SoftReference<T>(o)); } /** * {@inheritDoc} */ @Override public void add(int index, T o) { refs.add(index, new SoftReference<T>(o)); } /** * {@inheritDoc} */ @Override public void clear() { refs.clear(); } /** * {@inheritDoc} */ @Override public T remove(int index) { return getHardReference(refs.remove(index)); } /** * {@inheritDoc} */ @Override public T set(int index, T element) { return getHardReference(refs.set(index, new SoftReference<T>(element))); } /** * {@inheritDoc} */ @Override public boolean contains(Object o) { for (int i = 0; i < size(); i++) { if (o == get(i)) { return true; } } return false; } /** * {@inheritDoc} */ @Override public int size() { return refs.size(); } /** * Returns a list of hard references. Skips all weak references but doesn't delete them if there * are any. The list returned (especially the indices) aren't the same as the ones from this * list. * * @return An {@link ArrayList} containing all the hard references of this weak list. */ public List<T> getHardReferences() { List<T> result = new ArrayList<T>(); for (int i = 0; i < size(); i++) { T tmp = get(i); if (null != tmp) { result.add(tmp); } } return result; } /** * Calling this method removes all the garbage collected elements in this list which appear to * be null now.<br> * TODO: call this method periodically! */ public void removeAllNullElements() { for (int i = size() - 1; i >= 0; i--) { if (get(i) == null) { remove(i); } } } }