/**
* (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jabylon.cdo.connector.internal;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.util.ObjectNotFoundException;
import org.eclipse.emf.cdo.view.CDOStaleObject;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* retries with a proxy handler if the default strategy fails.
*
* see https://github.com/jutzig/jabylon/issues/218
* @author utzig
*
*/
public class RetryingStaleReferencePolicy implements CDOStaleReferencePolicy {
public static final CDOStaleReferencePolicy INSTANCE = new RetryingStaleReferencePolicy();
private static final Logger LOG = LoggerFactory
.getLogger(RetryingStaleReferencePolicy.class);
@Override
public Object processStaleReference(final EObject source,
EStructuralFeature feature, int index, final CDOID target) {
try {
LOG.warn("Processing stale reference {} feature {}",source,feature);
return CDOStaleReferencePolicy.DEFAULT.processStaleReference(source, feature, index, target);
} catch (Exception e) {
LOG.warn("failed to process stale reference. Falling back to different classloader",e);
final EClassifier type = feature.getEType();
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.equals("cdoID")) //$NON-NLS-1$
{
return target;
}
if (name.equals("eIsProxy")) //$NON-NLS-1$
{
return false;
}
if (name.equals("eClass")) //$NON-NLS-1$
{
return type;
}
if (name.equals("eAdapters")) //$NON-NLS-1$
{
return source.eAdapters();
}
throw new ObjectNotFoundException(target);
}
};
Class<?> instanceClass = type.getInstanceClass();
Class<?>[] interfaces = null;
// Be sure to have only interface
if (instanceClass.isInterface()) {
interfaces = new Class<?>[] { instanceClass, InternalEObject.class, CDOStaleObject.class };
} else {
interfaces = new Class<?>[] { InternalEObject.class, CDOStaleObject.class };
}
return Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, handler);
}
}
}