blob: 2f2d08917bb1e94a1a682ac16c856b5b70aa3293 [file] [log] [blame]
/**
* 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;
}
}