package rocks.inspectit.shared.all.serializer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import com.esotericsoftware.kryo.Registration;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.util.DefaultClassResolver;
import rocks.inspectit.shared.all.serializer.impl.HibernateProxySerializer;
import rocks.inspectit.shared.all.util.IHibernateUtil;
/**
* Class resolver that writes java collections and maps instead of the hibernate ones.
* <p>
* The current mapping is:
* <ul>
* <li>Hibernate PersistentSet -> HashSet</li>
* <li>Hibernate PersistentMap -> HashMap</li>
* <li>Hibernate PersistentList -> ArrayList</li>
* </ul>
* <p>
* Also it intercepts the Hibernate proxies, writes the correct entity class and returns the alerted
* registration that has a {@link HibernateProxySerializer} delegating to the correct serializer for
* the entity.
*
* @author Ivan Senic
*
*/
public class HibernateAwareClassResolver extends DefaultClassResolver {
/**
* {@link IHibernateUtil} to use.
*/
private IHibernateUtil hibernateUtil;
/**
* Map for caching altered registrations for the proxies.
*/
private final Map<Class<?>, Registration> hibernateProxiesRegistrations;
/**
* Default constructor.
*
* @param hibernateUtil
* {@link IHibernateUtil} to use.
*/
public HibernateAwareClassResolver(IHibernateUtil hibernateUtil) {
if (null == hibernateUtil) {
throw new IllegalArgumentException("Hibernate util is needed with creation of Hibernate aware class resolver");
}
this.hibernateUtil = hibernateUtil;
this.hibernateProxiesRegistrations = new HashMap<Class<?>, Registration>();
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Registration writeClass(Output output, Class type) {
Class<?> writeType = type;
if (null != type) {
if (hibernateUtil.isPersistentList(type)) {
writeType = ArrayList.class; // NOPMD
} else if (hibernateUtil.isPersistentSet(type)) {
writeType = HashSet.class; // NOPMD
} else if (hibernateUtil.isPersistentMap(type)) {
writeType = HashMap.class; // NOPMD
} else if (hibernateUtil.isProxy(writeType)) {
writeType = writeType.getSuperclass();
Registration registration = super.writeClass(output, writeType);
Registration returnRegistration = hibernateProxiesRegistrations.get(writeType);
if (null == returnRegistration) {
returnRegistration = new Registration(registration.getType(), new HibernateProxySerializer(hibernateUtil, registration.getSerializer()), registration.getId());
hibernateProxiesRegistrations.put(writeType, returnRegistration);
}
return returnRegistration;
}
}
return super.writeClass(output, writeType);
}
}