/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.remotecontrol.server;
import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
import io.remotecontrol.groovy.ClosureCommand;
import io.remotecontrol.RemoteControlException;
import io.remotecontrol.SerializationUtil;
import org.codehaus.groovy.runtime.InvokerInvocationException;
import java.io.IOException;
public class CommandInvoker {
private final ClassLoader parentLoader;
private final ClosureCommand command;
public CommandInvoker(ClassLoader parentLoader, ClosureCommand command) {
this.parentLoader = parentLoader;
this.command = command;
}
public Object invokeAgainst(Object delegate, Object argument) throws Throwable {
try {
Closure instance = instantiate();
instance.setResolveStrategy(Closure.DELEGATE_ONLY);
instance.setDelegate(delegate);
if (instance.getMaximumNumberOfParameters() < 1) {
return instance.call();
} else {
return instance.call(argument);
}
} catch (Throwable thrown) {
// If the server and client do not share the groovy classes, we get this
try {
parentLoader.loadClass(InvokerInvocationException.class.getName()).isAssignableFrom(thrown.getClass());
} catch (ClassNotFoundException throwable) {
throw thrown.getCause();
}
throw thrown;
}
}
protected Closure<?> instantiate() throws IOException {
final GroovyClassLoader classLoader = new GroovyClassLoader(parentLoader);
SerializationUtil.defineClass(classLoader, command.getRoot());
for (byte[] bytes : command.getSupports()) {
SerializationUtil.defineClass(classLoader, bytes);
}
try {
return SerializationUtil.deserialize(Closure.class, command.getInstance(), classLoader);
} catch (ClassNotFoundException e) {
throw RemoteControlException.classNotFoundOnServer(e);
}
}
}