/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.utils.servicemanager;
import java.lang.ref.WeakReference;
/**
* A holder which is designed to make it easy to hold onto a reference
* to a class which is outside of our ClassLoader and not cause it to
* not be able to reload happily. The reference to the
* object that is held onto here needs to not be the only one in the
* system or this object will be garbage collected before it probably
* should be. That is generally outside the purview of the service
* manager system though.
*
* @author Aaron Zeckoski (azeckoski @ gmail.com)
*/
public final class ProviderHolder<T> {
private WeakReference<T> providerReference = null;
/**
* Default constructor.
*/
public ProviderHolder() {}
/**
* Create the holder with a provider already in it.
* @param provider the provider to place in the holder to start
*/
public ProviderHolder(T provider) {
setProvider(provider);
}
/**
* Gets the provider out of this holder.
* Use the {@link #getProviderOrFail()} method if you want a method
* that never returns null.
*
* @return the provider if it is still available OR null if none is set or no longer available
*/
public T getProvider() {
T t = null;
if (this.providerReference != null) {
t = this.providerReference.get();
}
return t;
}
/**
* Gets the provider out of this holder if it still exists.
* Will not return null (unlike the {@link #getProvider()} method).
*
* @return the provider if it is available
* @throws ProviderNotFoundException if there is none available
*/
public T getProviderOrFail() {
T t = getProvider();
if (t == null) {
throw new ProviderNotFoundException("Could not get provider from this holder, none available");
}
return t;
}
/**
* Stores a provider in this holder in a ClassLoader safe way.
*
* @param provider the provider to store. If this is null then the current provider is cleared.
*/
public void setProvider(T provider) {
if (provider == null) {
if (this.providerReference != null) {
this.providerReference.clear();
}
this.providerReference = null;
} else {
this.providerReference = new WeakReference<T>(provider);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
T provider = getProvider();
result = prime * result + ((provider == null) ? 0 : provider.hashCode());
return result;
}
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ProviderHolder<T> other = (ProviderHolder<T>) obj;
T provider = getProvider();
T otherProvider = other.getProvider();
if (provider == null || otherProvider == null) {
return false;
} else if (provider.equals(otherProvider)) {
return true;
}
return false;
}
@Override
public String toString() {
T provider = getProvider();
return "ph:" + (provider == null ? null : provider.getClass() + ":" + provider) + ": " + super.toString();
}
}