package org.om.core.impl.persistence.cglib; import static org.om.core.impl.util.ClassUtils.extractFieldName; import static org.om.core.impl.util.ClassUtils.isGetter; import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.om.core.api.exception.MappingException; import org.om.core.api.mapping.EntityMapping; import org.om.core.api.mapping.MappedField; import org.om.core.api.persistence.interceptor.PersistenceInterceptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link MethodInterceptor} that will intercept all calls to getters for mapped * entities. All other method calls will be dispatched to the original object. * * @author Jakob Külzer * */ public class CglibPersistenceInterceptor implements MethodInterceptor { private static final Logger LOG = LoggerFactory.getLogger(CglibPersistenceInterceptor.class); private final EntityMapping entityMapping; private final PersistenceInterceptor interceptor; public CglibPersistenceInterceptor(EntityMapping entityMapping, PersistenceInterceptor interceptor) { this.interceptor = interceptor; this.entityMapping = entityMapping; } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { final String name = method.getName(); LOG.debug("Intercepted method {}()", name); final boolean isGetter = isGetter(name); if (!isGetter) { LOG.trace("Method {}() not a getter, not intercepted.", name); return proxy.invokeSuper(obj, args); } final String fieldName = extractFieldName(name); if (!entityMapping.hasField(fieldName)) { LOG.trace("Method {}() mapped to field {}. No mapping for property, method not intercepted.", name, fieldName); return proxy.invokeSuper(obj, args); } final MappedField mappedField = entityMapping.getByFieldName(fieldName); LOG.trace("Retrieved {}", mappedField); try { return interceptor.get(mappedField); } catch (MappingException e) { e.setMappedType(entityMapping.getTypeClass()); throw e; } } }