/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file. */
package er.extensions.concurrency;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import er.extensions.eof.ERXConstant;
import er.extensions.foundation.ERXUtilities;
/**
* <code>ERXClonableThreadLocal</code> extends {@link InheritableThreadLocal}
* to bequeath a cloned copy of the parent object to the child thread.
* <p>
* Note: Objects used with this thread local must implement the {@link Cloneable}
* interface and have a public <code>clone</code> method.
*/
public class ERXCloneableThreadLocal extends InheritableThreadLocal {
private static final Logger log = LoggerFactory.getLogger(ERXCloneableThreadLocal.class);
/**
* Clones a copy of the parent object for the child thread.
* The parentValue must implement the {@link Cloneable}
* interface and have a public <code>clone</code> method.
* @param parentValue local object to the parent thread.
* @return a cloned value of the parent if not null.
*/
@Override
protected Object childValue(Object parentValue) {
Object child = null;
if (parentValue != null) {
if (!(parentValue instanceof Cloneable)) {
throw new IllegalStateException("Using a ERXCloneableThreadLocal with an object: "
+ parentValue.getClass() + " " + parentValue.toString()
+ " that does not implement the Cloneable interface ");
}
// This is very lame. clone() is a protected method off of object and the Cloneable
// interface doesn't specify any methods.
try {
Method m = parentValue.getClass().getMethod("clone", ERXConstant.EmptyClassArray);
child = m.invoke(parentValue, ERXConstant.EmptyObjectArray);
} catch (InvocationTargetException ite) {
log.error("Invocation exception occurred when invoking clone in ERXClonableThreadLocal: {} backtrace: {}",
ite.getTargetException(), ERXUtilities.stackTrace(ite.getTargetException()));
} catch (NoSuchMethodException nsme) {
log.error("No clone method for the class: {} very strange.", parentValue.getClass());
} catch (IllegalAccessException iae) {
log.error("Clone method has protected or private access for the object: {} {}",
parentValue.getClass(), parentValue, iae);
}
}
return child;
}
}