Skip to content

Commit

Permalink
copy from remote
Browse files Browse the repository at this point in the history
  • Loading branch information
ccaner committed May 16, 2012
1 parent 53da1d7 commit 709196b
Show file tree
Hide file tree
Showing 15 changed files with 472 additions and 238 deletions.
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<module>jetty</module>
<module>remotemock</module>
<module>remotemock-example</module>
<module>resultsetmock</module>
</modules>

<properties>
Expand All @@ -22,6 +23,7 @@
<mockito.version>1.9.0</mockito.version>
<cglib.version>2.2.2</cglib.version>
<commons.version>3.1</commons.version>
<slf4j.version>1.6.4</slf4j.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -87,6 +89,11 @@
<artifactId>commons-lang3</artifactId>
<version>${commons.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down Expand Up @@ -127,6 +134,10 @@
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<constructor-arg value="mock."/>
</bean>

<bean class="play.remotemock.processor.RemotableBeanProcessor">
<bean class="play.remotemock.processor.RemotableInvocationHandler">
<constructor-arg ref="rmiRegistry" />
</bean>

Expand Down
10 changes: 8 additions & 2 deletions remotemock/src/main/java/play/remotemock/Remotable.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package play.remotemock;

public interface Remotable {
/**
* Implementations can proxy method invocations to an attached remote object.
* <p/>
* If you are using this interface instead of Remotable annotation, your class should handle
* all proxying logic.
*/
public interface Remotable<T> {

void attachRemote(String rmiUrl);
void attachRemote(T remoteObject);

void switchRemoteModeOn();

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,60 +1,76 @@
package play.remotemock.processor;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.remotemock.Remotable;
import play.remotemock.util.CallLocalMethodException;
import play.remotemock.util.RmiUtil;
import play.remotemock.util.InvokeLocalMethodException;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;


/**
* Enhances proxy with a RemotableHelper object. Makes it effectively implement Remotable interface.
* <p/>
* Handles Remotable and T(interface) methods
* <p/>
* RMI-free
*/
public class RemotableInvocationHandler<T> implements InvocationHandler {

private final RemotableHelper<T> remotableHelper;
private static final Logger logger = LoggerFactory.getLogger(RemotableInvocationHandler.class);

private final RemotableHelper<T> helper;

public RemotableInvocationHandler(T localObject, Class<T> serviceInterface) {
remotableHelper = new RemotableHelper<>(localObject, serviceInterface);
helper = new RemotableHelper<T>(localObject, serviceInterface);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass().equals(Remotable.class)) {
return method.invoke(remotableHelper, args);
}
Method serviceMethod = null;
try {
serviceMethod = remotableHelper.serviceInterface.getMethod(method.getName(),
method.getParameterTypes());
} catch (NoSuchMethodException ignore) {
logControl(method, args);
return method.invoke(helper, args);
}
if (serviceMethod != null && remotableHelper.remoteModeOn) {
// we volunteer to handle toString or hashCode here
boolean isServiceMethod = method.getDeclaringClass().isAssignableFrom(helper.serviceInterface);
if (isServiceMethod && helper.remoteModeOn) {
try {
return serviceMethod.invoke(remotableHelper.remoteObject, args);
Object result = method.invoke(helper.remoteObject, args);
logRemote(method, args, result);
return result;
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof CallLocalMethodException) {
return serviceMethod.invoke(remotableHelper.localObject, args);
if (InvokeLocalMethodException.class.isInstance(e.getCause())) {
Object result = method.invoke(helper.localObject, args);
logRedirect(method, args, result);
return result;
}
throw e;
throw e.getCause();
}
}
return method.invoke(remotableHelper.localObject, args);
Object result = method.invoke(helper.localObject, args);
logLocal(method, args, result);
return result;
}

private static class RemotableHelper<T> implements Remotable {
private static class RemotableHelper<T> implements Remotable<T> {

volatile private boolean remoteModeOn = false;
private T localObject;
private T remoteObject;
private Class<T> serviceInterface;
volatile T remoteObject;
final T localObject;
final Class<T> serviceInterface;
volatile boolean remoteModeOn = false;

private RemotableHelper(T localObject, Class<T> serviceInterface) {
this.localObject = localObject;
this.serviceInterface = serviceInterface;
}

@Override
public void attachRemote(String rmiUrl) {
remoteObject = RmiUtil.clientProxy(rmiUrl, serviceInterface);
public void attachRemote(T remoteObject) {
RemotableHelper.this.remoteObject = remoteObject;
}

@Override
Expand All @@ -68,4 +84,30 @@ public void switchRemoteModeOff() {
}
}

private void logLocal(Method method, Object[] args, Object result) {
if (!method.getDeclaringClass().equals(Object.class)) {
logger.debug("LOCAL: method: [{},{}] response: [{}]",
new Object[]{method.getName(), Arrays.toString(args),
ReflectionToStringBuilder.toString(result)});
}
}

private void logRedirect(Method method, Object[] args, Object result) {
logger.debug("REMOTE call directed to local: method: [{},{}] response: [{}]",
new Object[]{method.getName(), Arrays.toString(args),
ReflectionToStringBuilder.toString(result)});
}

private void logRemote(Method method, Object[] args, Object result) {
logger.debug("REMOTE: method: [{},{}] response: [{}]",
new Object[]{method.getName(), Arrays.toString(args),
ReflectionToStringBuilder.toString(result)});
}

private void logControl(Method method, Object[] args) {
logger.trace("CONTROL: method: [{},{}] local class: [{}]",
new Object[]{method.getName(), Arrays.toString(args),
helper.localObject.getClass().getSimpleName()});
}

}
Loading

0 comments on commit 709196b

Please sign in to comment.