| /** |
| * Copyright (c) 2015 Codetrails GmbH. |
| * 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 aeri.rcp; |
| |
| import static java.lang.System.currentTimeMillis; |
| import static java.util.concurrent.TimeUnit.MINUTES; |
| import static org.eclipse.epp.logging.aeri.core.ProblemStatus.*; |
| import static org.eclipse.epp.logging.aeri.core.SendMode.BACKGROUND; |
| import static org.eclipse.epp.logging.aeri.core.SystemControl.executeHandler; |
| |
| import java.io.IOException; |
| import java.util.concurrent.TimeUnit; |
| |
| import javax.inject.Inject; |
| import javax.inject.Named; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.core.di.extensions.EventTopic; |
| import org.eclipse.e4.core.services.events.IEventBroker; |
| import org.eclipse.epp.logging.aeri.core.Constants; |
| import org.eclipse.epp.logging.aeri.core.IModelFactory; |
| import org.eclipse.epp.logging.aeri.core.IProblemState; |
| import org.eclipse.epp.logging.aeri.core.ISendOptions; |
| import org.eclipse.epp.logging.aeri.core.IServerConnection; |
| import org.eclipse.epp.logging.aeri.core.ISystemSettings; |
| import org.eclipse.epp.logging.aeri.core.ProblemStatus; |
| import org.osgi.service.event.Event; |
| |
| import com.google.common.collect.ImmutableSet; |
| |
| import aeri.rcp.handlers.NotifyConfigureSystemHandler; |
| import aeri.rcp.handlers.NotifyLogEventHandler; |
| import aeri.rcp.handlers.NotifyServerResponseHandler; |
| |
| /** |
| * Basic single-server, no log queue, no throttling work-flow for handling log events in an RCP application. |
| * <p> |
| * You may reuse this class or implement your own work-flow from scratch using this class as an example. |
| */ |
| @SuppressWarnings("restriction") |
| public class DemoSingleServerWorkflow { |
| |
| public static final String CTX_STATE_REVIEW_IN_PROGRESS = Constants.BUNDLE_ID + ".di.review-in-progress"; |
| public static final String CTX_STATE_SETUP_IN_PROGRESS = Constants.BUNDLE_ID + ".di.configure-in-progress"; |
| public static final String CTX_STATE_NOTIFICATION_IN_PROGRESS = Constants.BUNDLE_ID + ".di.notification-in-progress"; |
| |
| public static final String CTX_LATEST_LOG_EVENT = Constants.BUNDLE_ID + ".events.latest.logged"; |
| |
| private static final ImmutableSet<ProblemStatus> INGORED = ImmutableSet.of(IGNORED, INVALID); |
| |
| public static final String TOPIC_BASE = "org/eclipse/epp/internal/logging/aeri/ui"; |
| |
| // The log listener uses this topic to announce new interesting status events |
| public static final String TOPIC_NEW_STATUS_LOGGED = TOPIC_BASE + "/status/new"; |
| public static final String TOPIC_NEW_EVENT_LOGGED = TOPIC_BASE + "/event/new"; |
| |
| public static final String TOPIC_RESCHEDULE_NOTIFCATION_LAST_LOG_EVENT = TOPIC_BASE + "/event/reschedule"; |
| public static final String TOPIC_USER_REQUESTS_DISABLE_NEW_SERVERS = TOPIC_BASE + "/servers/disabled"; |
| // |
| public static final String TOPIC_NEW_SERVER_RESPONSES = TOPIC_BASE + "/events/responses"; |
| public static final String TOPIC_USER_REQUESTS_SEND = TOPIC_BASE + "/event/send"; |
| |
| protected IEclipseContext context; |
| protected IEventBroker broker; |
| |
| protected ISystemSettings system; |
| |
| protected boolean systemStateSetupInProgress; |
| protected boolean systemStateReviewInProgress; |
| protected boolean systemStateNotificationInProgress; |
| protected long setupTimeout; |
| |
| private IServerConnection server; |
| |
| @Inject |
| public DemoSingleServerWorkflow(IServerConnection server, ISystemSettings settings, IEventBroker broker, IEclipseContext context) { |
| this.server = server; |
| this.system = settings; |
| this.broker = broker; |
| this.context = context; |
| context.declareModifiable(CTX_LATEST_LOG_EVENT); |
| } |
| |
| @Inject |
| @Optional |
| protected void onLoggedNewStatus(@EventTopic(TOPIC_NEW_STATUS_LOGGED) IStatus status) { |
| ISendOptions options = IModelFactory.eINSTANCE.createSendOptions(); |
| |
| IEclipseContext statusContext = context.createChild("Log event context"); |
| statusContext.set(IStatus.class, status); |
| statusContext.set(IServerConnection.class, server); |
| statusContext.set(ISendOptions.class, options); |
| |
| IProblemState prediction = server.interested(status, statusContext, new NullProgressMonitor()); |
| // ignore this event if the server is not (yet) interested |
| if (INGORED.contains(prediction.getStatus())) { |
| return; |
| } |
| |
| LogEvent event = new LogEvent(status, statusContext); |
| event.setContext(statusContext); |
| event.setStatus(status); |
| event.setConnection(server); |
| event.setOptions(options); |
| |
| broker.post(TOPIC_NEW_EVENT_LOGGED, event); |
| } |
| |
| @Inject |
| @Optional |
| protected synchronized void onLoggedNewEvent(@EventTopic(TOPIC_NEW_EVENT_LOGGED) LogEvent event) { |
| context.modify(CTX_LATEST_LOG_EVENT, event); |
| if (!system.isConfigured()) { |
| if (isAfterWelcomeTimeout()) { |
| setupTimeout = in(15, MINUTES); |
| executeHandler(NotifyConfigureSystemHandler.class); |
| } |
| return; |
| } |
| if (system.getSendMode() == BACKGROUND) { |
| broker.post(TOPIC_USER_REQUESTS_SEND, event); |
| } else { |
| if (canShowNotification()) { |
| executeHandler(NotifyLogEventHandler.class); |
| } |
| } |
| } |
| |
| private boolean isAfterWelcomeTimeout() { |
| return currentTimeMillis() > setupTimeout; |
| } |
| |
| private long in(int i, TimeUnit minutes) { |
| return currentTimeMillis() + minutes.toMillis(i); |
| } |
| |
| private boolean canShowNotification() { |
| return !(systemStateSetupInProgress || systemStateReviewInProgress || systemStateNotificationInProgress); |
| } |
| |
| @Inject |
| @Optional |
| protected void onSendLogEvent(@EventTopic(TOPIC_USER_REQUESTS_SEND) final LogEvent event) { |
| new Job("Upload error report") { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| IServerConnection server = event.getConnection(); |
| try { |
| server.submit(event.getStatus(), event.getContext(), monitor); |
| } catch (IOException e) { |
| return new Status(IStatus.WARNING, "aeri.rcp", "Uploading error report failed", e); |
| } |
| return Status.OK_STATUS; |
| } |
| }.schedule(); |
| } |
| |
| @Inject |
| @Optional |
| protected void onReceivedServerResponse(@EventTopic(TOPIC_NEW_SERVER_RESPONSES) LogEvent event) { |
| if (canShowNotification()) { |
| IEclipseContext local = context.createChild(); |
| local.set(LogEvent.class, event); |
| executeHandler(NotifyServerResponseHandler.class, local); |
| } |
| } |
| |
| @Inject |
| @Optional |
| protected void onRescheduleDelayedLogEvent(@EventTopic(TOPIC_RESCHEDULE_NOTIFCATION_LAST_LOG_EVENT) Event some) { |
| LogEvent event = (LogEvent) context.get(CTX_LATEST_LOG_EVENT); |
| if (!canShowNotification() || event == null) { |
| return; |
| } |
| executeHandler(NotifyLogEventHandler.class); |
| context.remove(CTX_LATEST_LOG_EVENT); |
| } |
| |
| // Injection of *internal* global system state variables |
| // We may move this into some state class later on as soon as these flags consolidate |
| @Inject |
| protected void setConfigureInProgress(@Named(CTX_STATE_SETUP_IN_PROGRESS) boolean newState) { |
| systemStateSetupInProgress = newState; |
| } |
| |
| @Inject |
| protected void setReviewInProgress(@Named(CTX_STATE_REVIEW_IN_PROGRESS) boolean newState) { |
| systemStateReviewInProgress = newState; |
| } |
| |
| @Inject |
| protected void setNotificationInProgress(@Named(CTX_STATE_NOTIFICATION_IN_PROGRESS) boolean newState) { |
| systemStateSetupInProgress = newState; |
| } |
| } |