/*
* Copyright (C) 2012-2013 The Cat Hive Developers.
*
* 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 com.cathive.fx.guice.thread;
import javafx.application.Platform;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.cathive.fx.guice.FxApplicationThread;
/**
* This class can be used as an AOP interceptor in conjunction with the
* {@link FxApplicationThread} annotation. It enforces method calls on the
* JavaFX Application Thread.
* <p>Basically, this class offers some wrapper functionality around
* the {@link Platform#runLater(Runnable) runLater()-Method} provided by
* the JavaFX Platform class.</p>
*
* @see FxApplicationThread
* @see Platform#runLater(Runnable)
*
* @author Benjamin P. Jung
*/
class FxApplicationThreadMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
final FxApplicationThread annotation = invocation.getMethod().getAnnotation(FxApplicationThread.class);
final FxTask fxTask = new FxTask(invocation);
if (annotation == null) {
throw new IllegalStateException("Method is not annotated with @FxApplicationThread!");
}
final Class<?> returnType = invocation.getMethod().getReturnType();
if (!(returnType.equals(void.class) || returnType.equals(Void.class))) {
throw new RuntimeException(String.format("[%s#%s] Only methods with return type 'void' can be annotated with @FxApplicationThread!", invocation.getThis().getClass().getName(), invocation.getMethod().getName()));
}
if (invocation.getMethod().getExceptionTypes().length > 0) {
throw new RuntimeException("Only methods that don't declare exception types can be annotated with @FxApplicationThread!");
}
final Object retval;
if (Platform.isFxApplicationThread()) {
retval = invocation.proceed();
} else {
Platform.runLater(fxTask);
retval = null;
}
return retval;
}
/**
*
* @author Benjamin P. Jung
*/
private static class FxTask implements Runnable {
private final MethodInvocation methodInvocation;
private Object returnValue;
private FxTask(MethodInvocation methodInvocation) {
super();
this.methodInvocation = methodInvocation;
}
@Override
public void run() {
try {
this.returnValue = methodInvocation.proceed();
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}
}