package org.argeo.cms.swt;
-import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
+import org.argeo.api.cms.CmsApp;
import org.argeo.api.cms.CmsEventBus;
+import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsImageManager;
import org.argeo.api.cms.ux.CmsUi;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.api.cms.ux.UxContext;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.util.CurrentSubject;
import org.eclipse.swt.widgets.Display;
public abstract class AbstractSwtCmsView implements CmsView {
+ private final static CmsLog log = CmsLog.getLog(AbstractSwtCmsView.class);
+
+ /** A timer to be used to perform background UX tasks. */
+ private final static Timer uxTimer = new Timer(true);
+
+ static {
+ // purge every day
+ uxTimer.schedule(new TimerTask() {
+
+ @Override
+ public void run() {
+ uxTimer.purge();
+ }
+ }, 0, 24 * 60 * 60 * 1000);
+ }
+
protected final String uiName;
protected LoginContext loginContext;
protected String state;
- protected Throwable exception;
+// protected Throwable exception;
protected UxContext uxContext;
protected CmsImageManager imageManager;
public abstract CmsEventBus getCmsEventBus();
+ public abstract CmsApp getCmsApp();
+
@Override
public void sendEvent(String topic, Map<String, Object> properties) {
if (properties == null)
throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
+ properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
properties.put(CMS_VIEW_UID_PROPERTY, uid);
+
+ log.trace(() -> uid + ": send event to " + topic);
+
getCmsEventBus().sendEvent(topic, properties);
+ // getCmsApp().onEvent(topic, properties);
}
- public <T> T doAs(PrivilegedAction<T> action) {
+// public void runAs(Runnable runnable) {
+// display.asyncExec(() -> doAs(Executors.callable(runnable)));
+// }
+
+ public <T> T doAs(Callable<T> action) {
try {
CompletableFuture<T> result = new CompletableFuture<>();
Runnable toDo = () -> {
- T res = Subject.doAs(getSubject(), action);
+ log.trace(() -> uid + ": process doAs");
+ Subject subject = CurrentSubject.current();
+ T res;
+ if (subject != null) {
+ assert subject == getSubject();
+ try {
+ res = action.call();
+ } catch (Exception e) {
+ throw new CompletionException("Failed to execute action for " + subject, e);
+ }
+ } else {
+ res = CurrentSubject.callAs(getSubject(), action);
+ }
result.complete(res);
};
if (Thread.currentThread() == display.getThread())
toDo.run();
- else
- display.syncExec(toDo);
+ else {
+ display.asyncExec(toDo);
+ display.wake();
+ }
+// throw new IllegalStateException("Must be called from UI thread");
return result.get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("Cannot execute action ins CMS view " + uid, e);
}
}
+ @Override
+ public TimerTask schedule(Runnable task, long delay) {
+ TimerTask timerTask = newSwtUxTimerTask(task);
+ uxTimer.schedule(timerTask, delay);
+ return timerTask;
+ }
+
+ @Override
+ public TimerTask schedule(Runnable task, long delay, long period) {
+ TimerTask timerTask = newSwtUxTimerTask(task);
+ uxTimer.schedule(timerTask, delay, period);
+ return timerTask;
+ }
+
+ protected TimerTask newSwtUxTimerTask(Runnable todo) {
+ return new TimerTask() {
+
+ @Override
+ public void run() {
+ synchronized (display) {
+ try {
+ if (!display.isDisposed()) {
+ display.syncExec(() -> {
+ todo.run();
+ });
+ }
+ } catch (Exception e) {
+ log.error("Cannot run UX timer task", e);
+ }
+ }
+ }
+ };
+ }
}