/******************************************************************************* * Copyright (c) 2012-2016 Codenvy, S.A. * 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 * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.client.dependenciesupdater; import com.google.gwt.core.client.Scheduler; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; import org.eclipse.che.api.machine.gwt.client.events.ExtServerStateEvent; import org.eclipse.che.api.machine.gwt.client.events.ExtServerStateHandler; import org.eclipse.che.ide.ext.java.client.event.DependencyUpdatedEvent; import org.eclipse.che.ide.ext.java.client.event.DependencyUpdatedEventHandler; import org.eclipse.che.ide.extension.machine.client.outputspanel.OutputsContainerPresenter; import org.eclipse.che.ide.extension.machine.client.outputspanel.console.CommandConsoleFactory; import org.eclipse.che.ide.extension.machine.client.outputspanel.console.DefaultOutputConsole; import org.eclipse.che.ide.util.StringUtils; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.ide.websocket.MessageBus; import org.eclipse.che.ide.websocket.MessageBusProvider; import org.eclipse.che.ide.websocket.WebSocketException; import org.eclipse.che.ide.websocket.rest.StringUnmarshallerWS; import org.eclipse.che.ide.websocket.rest.SubscriptionHandler; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * The class contains business logic which allows output logs from different channels into different consoles. * * @author Dmitry Shnurenko */ @Singleton public class LogsOutputHandler implements DependencyUpdatedEventHandler, ExtServerStateHandler { private final CommandConsoleFactory consoleFactory; private final OutputsContainerPresenter outputsContainerPresenter; private final Map<String, ChannelParameters> channelParameters; private final MessageBusProvider messageBusProvider; private MessageBus messageBus; private SubscriptionHandler<String> outputHandler; @Inject public LogsOutputHandler(CommandConsoleFactory consoleFactory, OutputsContainerPresenter outputsContainerPresenter, EventBus eventBus, MessageBusProvider messageBusProvider) { this.consoleFactory = consoleFactory; this.outputsContainerPresenter = outputsContainerPresenter; this.messageBus = messageBusProvider.getMachineMessageBus(); this.channelParameters = new HashMap<>(); this.messageBusProvider = messageBusProvider; eventBus.addHandler(DependencyUpdatedEvent.TYPE, this); eventBus.addHandler(ExtServerStateEvent.TYPE, this); } @Override public void onExtServerStarted(ExtServerStateEvent event) { messageBus = messageBusProvider.getMachineMessageBus(); } @Override public void onExtServerStopped(ExtServerStateEvent event) { } @Override public void onDependencyUpdated(DependencyUpdatedEvent event) { String updatedChannel = event.getChannel(); channelParameters.get(updatedChannel).outputEnded(); flushBuffer(updatedChannel); try { if (outputHandler == null) { return; } messageBus.unsubscribe(updatedChannel, outputHandler); } catch (WebSocketException exception) { Log.error(getClass(), exception); } } /** * Subscribes to web socket via special channel to get logs. * * @param channel * channel id which will be used to subscribe to output * @param tabName * name of tab in which output will be printed */ public void subscribeToOutput(final String channel, String tabName) { DefaultOutputConsole console = (DefaultOutputConsole)consoleFactory.create(tabName); outputsContainerPresenter.addConsole(console); channelParameters.put(channel, ChannelParameters.of(console, new LinkedList<String>())); outputHandler = new SubscriptionHandler<String>(new StringUnmarshallerWS()) { @Override protected void onMessageReceived(String logs) { List<String> lines = StringUtils.split(logs, "\n"); channelParameters.get(channel).addAllLines(lines); if (channelParameters.get(channel).isOutputEnded()) { flushBuffer(channel); return; } printOutput(channel); } @Override protected void onErrorReceived(Throwable exception) { Log.error(getClass(), exception); } }; try { messageBus.subscribe(channel, outputHandler); } catch (WebSocketException e) { e.printStackTrace(); } } private void flushBuffer(String channel) { LinkedList<String> output = channelParameters.get(channel).getOutput(); DefaultOutputConsole console = channelParameters.get(channel).getConsole(); while (!output.isEmpty()) { String toOutput = output.pop(); console.printText(toOutput, toOutput.contains("KB")); } } private void printOutput(final String channel) { final LinkedList<String> output = channelParameters.get(channel).getOutput(); final DefaultOutputConsole console = channelParameters.get(channel).getConsole(); Scheduler.get().scheduleFixedPeriod(new Scheduler.RepeatingCommand() { @Override public boolean execute() { if (output.isEmpty()) { return false; } String toOutput = output.pop(); console.printText(toOutput, toOutput.contains("KB")); return !channelParameters.get(channel).isOutputEnded(); } }, 100); } }