diff --git a/assembly/assembly-main/pom.xml b/assembly/assembly-main/pom.xml index 8ceefc74d3..bcd6530902 100644 --- a/assembly/assembly-main/pom.xml +++ b/assembly/assembly-main/pom.xml @@ -104,7 +104,7 @@ false false - ${project.basedir}/src/assembly/assembly.xml + ${project.basedir}/src/assembly/assembly.xml eclipse-che-${project.version} posix diff --git a/plugins/plugin-composer/che-plugin-composer-ide/pom.xml b/plugins/plugin-composer/che-plugin-composer-ide/pom.xml index a22ef1887a..8abe4958b2 100644 --- a/plugins/plugin-composer/che-plugin-composer-ide/pom.xml +++ b/plugins/plugin-composer/che-plugin-composer-ide/pom.xml @@ -38,6 +38,10 @@ javax.validation validation-api + + org.eclipse.che.core + che-core-api-core + org.eclipse.che.core che-core-api-project-shared diff --git a/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/ComposerJsonRpcHandler.java b/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/ComposerJsonRpcHandler.java new file mode 100644 index 0000000000..eca31da5cb --- /dev/null +++ b/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/ComposerJsonRpcHandler.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. + * 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: + * Rogue Wave Software, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.plugin.composer.ide; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator; +import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter; +import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Consumer; + +import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_OUTPUT; +import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_SUBSCRIBE; + +/** + * A mechanism for handling all messages from the Composer and applying + * registered consumers. + * + * @author Kaloyan Raev + */ +@Singleton +public class ComposerJsonRpcHandler { + private static final String WS_AGENT_ENDPOINT = "ws-agent"; + + private RequestHandlerConfigurator configurator; + + private Set> composerOutputConsumers = new HashSet<>(); + + private boolean isSubscribed = false; + + @Inject + public ComposerJsonRpcHandler(RequestHandlerConfigurator configurator) { + this.configurator = configurator; + + handleComposerMessages(); + } + + @Inject + private void subscribe(RequestTransmitter requestTransmitter) { + if (isSubscribed) { + return; + } + + requestTransmitter.newRequest() + .endpointId(WS_AGENT_ENDPOINT) + .methodName(COMPOSER_CHANNEL_SUBSCRIBE) + .noParams() + .sendAndSkipResult(); + + isSubscribed = true; + } + + /** + * Adds consumer for the event with {@link ComposerOutput}. + * + * @param consumer + * new consumer + */ + public void addComposerOutputHandler(Consumer consumer) { + composerOutputConsumers.add(consumer); + } + + private void handleComposerMessages() { + configurator.newConfiguration() + .methodName(COMPOSER_CHANNEL_OUTPUT) + .paramsAsDto(ComposerOutput.class) + .noResult() + .withConsumer(archetypeOutput -> composerOutputConsumers.forEach(it -> it.accept(archetypeOutput))); + } +} diff --git a/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/communication/ComposerOutputHandler.java b/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/communication/ComposerOutputHandler.java index 3f2cd62909..dd97c10ad8 100644 --- a/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/communication/ComposerOutputHandler.java +++ b/plugins/plugin-composer/che-plugin-composer-ide/src/main/java/org/eclipse/che/plugin/composer/ide/communication/ComposerOutputHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -12,26 +12,14 @@ package org.eclipse.che.plugin.composer.ide.communication; import com.google.inject.Inject; import com.google.inject.Singleton; -import com.google.web.bindery.event.shared.EventBus; -import org.eclipse.che.api.promises.client.Operation; -import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.ide.api.app.AppContext; -import org.eclipse.che.ide.api.machine.WsAgentStateController; -import org.eclipse.che.ide.api.machine.events.WsAgentStateEvent; -import org.eclipse.che.ide.api.machine.events.WsAgentStateHandler; -import org.eclipse.che.ide.dto.DtoFactory; import org.eclipse.che.ide.console.CommandConsoleFactory; import org.eclipse.che.ide.console.DefaultOutputConsole; import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter; -import org.eclipse.che.ide.util.loging.Log; -import org.eclipse.che.ide.websocket.MessageBus; -import org.eclipse.che.ide.websocket.WebSocketException; -import org.eclipse.che.ide.websocket.events.MessageHandler; +import org.eclipse.che.plugin.composer.ide.ComposerJsonRpcHandler; import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; -import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_NAME; - /** * Handler which receives messages from the Composer tool. * @@ -40,77 +28,43 @@ import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_ @Singleton public class ComposerOutputHandler { - private final EventBus eventBus; - private final DtoFactory factory; private final ProcessesPanelPresenter processesPanelPresenter; - private final CommandConsoleFactory commandConsoleFactory; private final AppContext appContext; + private DefaultOutputConsole outputConsole; + @Inject - public ComposerOutputHandler(EventBus eventBus, - DtoFactory factory, - WsAgentStateController wsAgentStateController, + public ComposerOutputHandler(ComposerJsonRpcHandler composerJsonRpcHandler, ProcessesPanelPresenter processesPanelPresenter, CommandConsoleFactory commandConsoleFactory, AppContext appContext) { - this.eventBus = eventBus; - this.factory = factory; this.processesPanelPresenter = processesPanelPresenter; - this.commandConsoleFactory = commandConsoleFactory; this.appContext = appContext; - handleOperations(factory, wsAgentStateController); + composerJsonRpcHandler.addComposerOutputHandler(this::onComposerOutput); + + outputConsole = (DefaultOutputConsole) commandConsoleFactory.create("Composer"); } - private void handleOperations(final DtoFactory factory, final WsAgentStateController wsAgentStateController) { - eventBus.addHandler(WsAgentStateEvent.TYPE, new WsAgentStateHandler() { - @Override - public void onWsAgentStarted(WsAgentStateEvent event) { - wsAgentStateController.getMessageBus().then(new Operation() { - @Override - public void apply(MessageBus messageBus) throws OperationException { - handleComposerOutput(messageBus); - } - }); - } - - @Override - public void onWsAgentStopped(WsAgentStateEvent event) { - } - }); - } - - private void handleComposerOutput(final MessageBus messageBus) { - final DefaultOutputConsole outputConsole = (DefaultOutputConsole) commandConsoleFactory.create("Composer"); - - try { - messageBus.subscribe(COMPOSER_CHANNEL_NAME, new MessageHandler() { - @Override - public void onMessage(String message) { - Log.info(getClass(), message); - ComposerOutput archetypeOutput = factory.createDtoFromJson(message, ComposerOutput.class); - processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), outputConsole); - switch (archetypeOutput.getState()) { - case START: - outputConsole.clearOutputsButtonClicked(); - outputConsole.printText(archetypeOutput.getOutput(),"green"); - break; - case IN_PROGRESS: - outputConsole.printText(archetypeOutput.getOutput()); - break; - case DONE: - outputConsole.printText(archetypeOutput.getOutput(),"green"); - break; - case ERROR: - outputConsole.printText(archetypeOutput.getOutput(),"red"); - break; - default: - break; - } - } - }); - } catch (WebSocketException e) { - e.printStackTrace(); + private void onComposerOutput(ComposerOutput output) { + String message = output.getOutput(); + switch (output.getState()) { + case START: + processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), outputConsole); + outputConsole.clearOutputsButtonClicked(); + outputConsole.printText(message, "green"); + break; + case IN_PROGRESS: + outputConsole.printText(message); + break; + case DONE: + outputConsole.printText(message, "green"); + break; + case ERROR: + outputConsole.printText(message, "red"); + break; + default: + break; } } diff --git a/plugins/plugin-composer/che-plugin-composer-server/pom.xml b/plugins/plugin-composer/che-plugin-composer-server/pom.xml index c2cb23f865..9b791f925d 100644 --- a/plugins/plugin-composer/che-plugin-composer-server/pom.xml +++ b/plugins/plugin-composer/che-plugin-composer-server/pom.xml @@ -25,6 +25,10 @@ com.google.code.gson gson + + com.google.guava + guava + com.google.inject guice @@ -33,10 +37,22 @@ com.google.inject.extensions guice-multibindings + + javax.annotation + javax.annotation-api + + + javax.inject + javax.inject + org.eclipse.che.core che-core-api-core + + org.eclipse.che.core + che-core-api-dto + org.eclipse.che.core che-core-api-project diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/ComposerModule.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/ComposerModule.java index d94df1d757..86561c6f7e 100644 --- a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/ComposerModule.java +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/ComposerModule.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -17,6 +17,7 @@ import org.eclipse.che.api.project.server.handlers.ProjectHandler; import org.eclipse.che.api.project.server.type.ProjectTypeDef; import org.eclipse.che.api.project.server.type.ValueProviderFactory; import org.eclipse.che.inject.DynaModule; +import org.eclipse.che.plugin.composer.server.executor.ComposerJsonRpcMessenger; import org.eclipse.che.plugin.composer.server.projecttype.ComposerProjectGenerator; import org.eclipse.che.plugin.composer.server.projecttype.ComposerProjectInitializer; import org.eclipse.che.plugin.composer.server.projecttype.ComposerProjectType; @@ -45,5 +46,7 @@ public class ComposerModule extends AbstractModule { Multibinder projectHandlerMultibinder = newSetBinder(binder(), ProjectHandler.class); projectHandlerMultibinder.addBinding().to(ComposerProjectGenerator.class); projectHandlerMultibinder.addBinding().to(ComposerProjectInitializer.class); + + bind(ComposerJsonRpcMessenger.class); } } diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerCommandExecutor.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerCommandExecutor.java new file mode 100644 index 0000000000..22a08fd5cf --- /dev/null +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerCommandExecutor.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. + * 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: + * Rogue Wave Software, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.plugin.composer.server.executor; + +import org.eclipse.che.api.core.notification.EventService; +import org.eclipse.che.api.core.util.AbstractLineConsumer; +import org.eclipse.che.api.core.util.LineConsumer; +import org.eclipse.che.api.core.util.ProcessUtil; +import org.eclipse.che.api.core.util.ValueHolder; +import org.eclipse.che.api.core.util.Watchdog; +import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * @author Kaloyan Raev + */ +@Singleton +public class ComposerCommandExecutor { + + private EventService eventService; + + @Inject + public ComposerCommandExecutor(EventService eventService) { + this.eventService = eventService; + } + + private static final Logger LOG = LoggerFactory.getLogger(ComposerCommandExecutor.class); + + public void execute(String[] commandLine, File workDir) + throws TimeoutException, IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder(commandLine).redirectErrorStream(true).directory(workDir); + + eventService.publish(new ComposerOutputImpl(String.join(" ", commandLine), ComposerOutput.State.START)); + + LineConsumer lineConsumer = new AbstractLineConsumer() { + @Override + public void writeLine(String line) throws IOException { + eventService.publish(new ComposerOutputImpl(line, ComposerOutput.State.IN_PROGRESS)); + } + }; + + // process will be stopped after timeout + Watchdog watcher = new Watchdog(10, TimeUnit.MINUTES); + + try { + final Process process = pb.start(); + final ValueHolder isTimeoutExceeded = new ValueHolder<>(false); + watcher.start(() -> { + isTimeoutExceeded.set(true); + ProcessUtil.kill(process); + }); + // consume logs until process ends + ProcessUtil.process(process, lineConsumer); + process.waitFor(); + eventService.publish(new ComposerOutputImpl("Done", ComposerOutput.State.DONE)); + if (isTimeoutExceeded.get()) { + LOG.error("Command time expired : command-line " + Arrays.toString(commandLine)); + eventService.publish(new ComposerOutputImpl("Installing dependencies time expired", ComposerOutput.State.ERROR)); + throw new TimeoutException(); + } else if (process.exitValue() != 0) { + LOG.error("Command failed : command-line " + Arrays.toString(commandLine)); + eventService.publish(new ComposerOutputImpl("Error occurred", ComposerOutput.State.ERROR)); + throw new IOException("Process failed. Exit code " + process.exitValue() + " command-line : " + Arrays.toString(commandLine)); + } + } finally { + watcher.stop(); + } + } + +} diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerJsonRpcMessenger.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerJsonRpcMessenger.java new file mode 100644 index 0000000000..87d58bb1a5 --- /dev/null +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerJsonRpcMessenger.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. + * 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: + * Rogue Wave Software, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.che.plugin.composer.server.executor; + +import com.google.inject.Singleton; + +import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator; +import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter; +import org.eclipse.che.api.core.notification.EventService; +import org.eclipse.che.api.core.notification.EventSubscriber; +import org.eclipse.che.dto.server.DtoFactory; +import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; + +import java.util.Set; + +import static com.google.common.collect.Sets.newConcurrentHashSet; +import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_OUTPUT; +import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_SUBSCRIBE; +import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_CHANNEL_UNSUBSCRIBE; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; + +/** + * Mechanism which sends events of Composer by using JSON RPC to the client. + * + * @author Kaloyan Raev + */ +@Singleton +public class ComposerJsonRpcMessenger implements EventSubscriber { + private final Set endpointIds = newConcurrentHashSet(); + private EventService eventService; + private RequestTransmitter transmitter; + + @Inject + public ComposerJsonRpcMessenger(EventService eventService, + RequestTransmitter transmitter) { + this.eventService = eventService; + this.transmitter = transmitter; + } + + @PostConstruct + private void subscribe() { + eventService.subscribe(this); + } + + @PreDestroy + private void unsubscribe() { + eventService.unsubscribe(this); + } + + @Inject + private void configureHandlers(RequestHandlerConfigurator configurator) { + configurator.newConfiguration() + .methodName(COMPOSER_CHANNEL_SUBSCRIBE) + .noParams() + .noResult() + .withConsumer(endpointIds::add); + + configurator.newConfiguration() + .methodName(COMPOSER_CHANNEL_UNSUBSCRIBE) + .noParams() + .noResult() + .withConsumer(endpointIds::remove); + } + + @Override + public void onEvent(ComposerOutput event) { + ComposerOutput composerOutput = DtoFactory.newDto(ComposerOutput.class); + composerOutput.setOutput(event.getOutput()); + composerOutput.setState(event.getState()); + + endpointIds.forEach(it -> transmitter.newRequest() + .endpointId(it) + .methodName(COMPOSER_CHANNEL_OUTPUT).paramsAsDto(composerOutput) + .sendAndSkipResult()); + } +} diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerOutputImpl.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerOutputImpl.java similarity index 77% rename from plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerOutputImpl.java rename to plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerOutputImpl.java index 6e71739f33..f04a62e758 100644 --- a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerOutputImpl.java +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/executor/ComposerOutputImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -8,7 +8,7 @@ * Contributors: * Rogue Wave Software, Inc. - initial API and implementation *******************************************************************************/ -package org.eclipse.che.plugin.composer.server.projecttype; +package org.eclipse.che.plugin.composer.server.executor; import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; @@ -34,4 +34,14 @@ public class ComposerOutputImpl implements ComposerOutput { public State getState() { return state; } + + @Override + public void setOutput(String output) { + this.output = output; + } + + @Override + public void setState(State state) { + this.state = state; + } } diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerCommandExecutor.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerCommandExecutor.java deleted file mode 100644 index 9cfd9a018c..0000000000 --- a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerCommandExecutor.java +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. - * 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: - * Rogue Wave Software, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.che.plugin.composer.server.projecttype; - -import org.eclipse.che.api.core.util.AbstractLineConsumer; -import org.eclipse.che.api.core.util.LineConsumer; -import org.eclipse.che.api.core.util.ProcessUtil; -import org.eclipse.che.api.core.util.ValueHolder; -import org.eclipse.che.api.core.util.Watchdog; -import org.eclipse.che.api.core.util.WebsocketMessageConsumer; -import org.eclipse.che.plugin.composer.shared.Constants; -import org.eclipse.che.plugin.composer.shared.dto.ComposerOutput; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class ComposerCommandExecutor { - - private static final Logger LOG = LoggerFactory.getLogger(ComposerCommandExecutor.class); - - public static void execute(String[] commandLine, File workDir) - throws TimeoutException, IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder(commandLine).redirectErrorStream(true).directory(workDir); - - try (WebsocketMessageConsumer websocketMessageConsumer = new WebsocketMessageConsumer<>(Constants.COMPOSER_CHANNEL_NAME)) { - websocketMessageConsumer.consume(new ComposerOutputImpl(String.join(" ", commandLine), ComposerOutput.State.START)); - LineConsumer lineConsumer = new AbstractLineConsumer() { - @Override - public void writeLine(String line) throws IOException { - websocketMessageConsumer.consume(new ComposerOutputImpl(line, ComposerOutput.State.IN_PROGRESS)); - } - }; - - // process will be stopped after timeout - Watchdog watcher = new Watchdog(10, TimeUnit.MINUTES); - - try { - final Process process = pb.start(); - final ValueHolder isTimeoutExceeded = new ValueHolder<>(false); - watcher.start(() -> { - isTimeoutExceeded.set(true); - ProcessUtil.kill(process); - }); - // consume logs until process ends - ProcessUtil.process(process, lineConsumer); - process.waitFor(); - websocketMessageConsumer.consume(new ComposerOutputImpl("Done", ComposerOutput.State.DONE)); - if (isTimeoutExceeded.get()) { - LOG.error("Command time expired : command-line " + Arrays.toString(commandLine)); - websocketMessageConsumer.consume(new ComposerOutputImpl("Installing dependencies time expired", ComposerOutput.State.ERROR)); - throw new TimeoutException(); - } else if (process.exitValue() != 0) { - LOG.error("Command failed : command-line " + Arrays.toString(commandLine)); - websocketMessageConsumer.consume(new ComposerOutputImpl("Error occurred", ComposerOutput.State.ERROR)); - throw new IOException("Process failed. Exit code " + process.exitValue() + " command-line : " + Arrays.toString(commandLine)); - } - } finally { - watcher.stop(); - } - } - } - -} diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectGenerator.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectGenerator.java index df57236f63..73b354129d 100644 --- a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectGenerator.java +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectGenerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.che.plugin.composer.server.projecttype; -import com.google.inject.Inject; - import org.eclipse.che.api.core.ConflictException; import org.eclipse.che.api.core.ForbiddenException; import org.eclipse.che.api.core.ServerException; @@ -20,6 +18,7 @@ import org.eclipse.che.api.project.server.type.AttributeValue; import org.eclipse.che.api.vfs.Path; import org.eclipse.che.api.vfs.VirtualFileSystem; import org.eclipse.che.api.vfs.VirtualFileSystemProvider; +import org.eclipse.che.plugin.composer.server.executor.ComposerCommandExecutor; import org.eclipse.che.plugin.composer.shared.Constants; import java.io.File; @@ -27,10 +26,22 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.TimeoutException; +import javax.inject.Inject; + +/** + * @author Kaloyan Raev + */ public class ComposerProjectGenerator implements CreateProjectHandler { + private final VirtualFileSystem vfs; + private final ComposerCommandExecutor commandExecutor; + @Inject - private VirtualFileSystemProvider virtualFileSystemProvider; + public ComposerProjectGenerator(VirtualFileSystemProvider vfsProvider, + ComposerCommandExecutor commandExecutor) throws ServerException { + this.vfs = vfsProvider.getVirtualFileSystem(); + this.commandExecutor = commandExecutor; + } @Override public void onCreateProject(Path projectPath, Map attributes, Map options) @@ -40,12 +51,11 @@ public class ComposerProjectGenerator implements CreateProjectHandler { throw new ServerException("Missed some required options (package)"); } - VirtualFileSystem vfs = virtualFileSystemProvider.getVirtualFileSystem(); String projectAbsolutePath = new File(vfs.getRoot().toIoFile(), projectPath.toString()).toString(); String[] commandLine = { "composer", "create-project", packageName.getString(), projectAbsolutePath, "--no-install" }; try { - ComposerCommandExecutor.execute(commandLine, null); + commandExecutor.execute(commandLine, null); } catch (TimeoutException | IOException | InterruptedException e) { throw new ServerException(e); } diff --git a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectInitializer.java b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectInitializer.java index ab23b3fe66..d005c68f4d 100644 --- a/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectInitializer.java +++ b/plugins/plugin-composer/che-plugin-composer-server/src/main/java/org/eclipse/che/plugin/composer/server/projecttype/ComposerProjectInitializer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -17,6 +17,7 @@ import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.project.server.FolderEntry; import org.eclipse.che.api.project.server.ProjectRegistry; import org.eclipse.che.api.project.server.handlers.ProjectInitHandler; +import org.eclipse.che.plugin.composer.server.executor.ComposerCommandExecutor; import java.io.File; import java.io.IOException; @@ -24,15 +25,27 @@ import java.util.concurrent.TimeoutException; import static org.eclipse.che.plugin.composer.shared.Constants.COMPOSER_PROJECT_TYPE_ID; +import javax.inject.Inject; + +/** + * @author Kaloyan Raev + */ public class ComposerProjectInitializer implements ProjectInitHandler { + private ComposerCommandExecutor commandExecutor; + + @Inject + public ComposerProjectInitializer(ComposerCommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + } + @Override public void onProjectInitialized(ProjectRegistry registry, FolderEntry projectFolder) throws ServerException, ForbiddenException, ConflictException, NotFoundException { String[] commandLine = { "composer", "install" }; File workDir = projectFolder.getVirtualFile().toIoFile(); try { - ComposerCommandExecutor.execute(commandLine, workDir); + commandExecutor.execute(commandLine, workDir); } catch (TimeoutException | IOException | InterruptedException e) { throw new ServerException(e); } diff --git a/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/Constants.java b/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/Constants.java index f257853e60..654009496a 100644 --- a/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/Constants.java +++ b/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/Constants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -18,8 +18,9 @@ public class Constants { public final static String COMPOSER_PROJECT_TYPE_ID = "composer"; public final static String PACKAGE = "package"; - /** Name of WebSocket channel for Composer output */ - public final static String COMPOSER_CHANNEL_NAME = "composer:output"; + public final static String COMPOSER_CHANNEL_OUTPUT = "composer/output"; + public final static String COMPOSER_CHANNEL_SUBSCRIBE = "composer/subscribe"; + public final static String COMPOSER_CHANNEL_UNSUBSCRIBE = "composer/unsubscribe"; private Constants() { } diff --git a/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/dto/ComposerOutput.java b/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/dto/ComposerOutput.java index 029d2dceef..93b55b5a6c 100644 --- a/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/dto/ComposerOutput.java +++ b/plugins/plugin-composer/che-plugin-composer-shared/src/main/java/org/eclipse/che/plugin/composer/shared/dto/ComposerOutput.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Rogue Wave Software, Inc. + * Copyright (c) 2016-2017 Rogue Wave Software, Inc. * 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 @@ -42,4 +42,8 @@ public interface ComposerOutput { */ State getState(); + void setOutput(String output); + + void setState(State state); + }