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);
+
}