/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.internal.util; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.security.AccessController; import java.security.PrivilegedAction; import org.hibernate.HibernateException; /** * An object that is shallow-coneable * * @author Steve Ebersole */ public class Cloneable { private static final Object[] READER_METHOD_ARGS = new Object[0]; /** * Essentially performs a shallow copy of this SessionEventListenerConfig * instance; meaning the SessionEventListenerConfig itself is cloned, but * the individual listeners are <b>not</b> cloned. * * @return The SessionEventListenerConfig shallow copy. */ public Object shallowCopy() { return AccessController.doPrivileged( new PrivilegedAction() { @Override public Object run() { return copyListeners(); } } ); } /** * Checks to ensure the SessionEventListenerConfig is fully * configured (basically, that none of the listeners is null). * * @throws HibernateException If the SessionEventListenerConfig * is not fully configured. */ public void validate() throws HibernateException { AccessController.doPrivileged( new PrivilegedAction() { @Override public Object run() { checkListeners(); return null; } } ); } private Object copyListeners() { Object copy = null; BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo( getClass(), Object.class ); internalCheckListeners( beanInfo ); copy = getClass().newInstance(); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for ( PropertyDescriptor pd : pds ) { try { pd.getWriteMethod().invoke( copy, pd.getReadMethod().invoke( this, READER_METHOD_ARGS ) ); } catch (Throwable t) { throw new HibernateException( "Unable copy copy listener [" + pd.getName() + "]" ); } } } catch (Exception t) { throw new HibernateException( "Unable to copy listeners", t ); } finally { if ( beanInfo != null ) { // release the jdk internal caches everytime to ensure this // plays nicely with destroyable class-loaders Introspector.flushFromCaches( getClass() ); } } return copy; } private void checkListeners() { BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo( getClass(), Object.class ); internalCheckListeners( beanInfo ); } catch (IntrospectionException t) { throw new HibernateException( "Unable to validate listener config", t ); } finally { if ( beanInfo != null ) { // release the jdk internal caches everytime to ensure this // plays nicely with destroyable class-loaders Introspector.flushFromCaches( getClass() ); } } } private void internalCheckListeners(BeanInfo beanInfo) { PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); try { for ( PropertyDescriptor pd : pds ) { final Object listener = pd.getReadMethod().invoke( this, READER_METHOD_ARGS ); if ( listener == null ) { throw new HibernateException( "Listener [" + pd.getName() + "] was null" ); } if ( listener.getClass().isArray() ) { Object[] listenerArray = (Object[]) listener; for ( Object aListenerArray : listenerArray ) { if ( aListenerArray == null ) { throw new HibernateException( "Listener in [" + pd.getName() + "] was null" ); } } } } } catch (HibernateException e) { throw e; } catch (Throwable t) { throw new HibernateException( "Unable to validate listener config" ); } } }