From 6aad4e3549de148add0341a25f520efe3832d9f1 Mon Sep 17 00:00:00 2001 From: Florent BENOIT Date: Thu, 25 Feb 2016 10:34:19 +0100 Subject: [PATCH] CODENVY-132 FactoryWorkspaceComponent is reusing a previously created workspace Change-Id: I4d3d4cd9693b1443d4aeebd9148a9668679681bb Signed-off-by: Florent BENOIT --- .../che/ide/CoreLocalizationConstant.java | 12 ++ .../workspace/FactoryWorkspaceComponent.java | 142 +++++------------- .../ide/CoreLocalizationConstant.properties | 4 + 3 files changed, 55 insertions(+), 103 deletions(-) diff --git a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/CoreLocalizationConstant.java b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/CoreLocalizationConstant.java index 75bc90b6c0..c5a7d30a1d 100644 --- a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/CoreLocalizationConstant.java +++ b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/CoreLocalizationConstant.java @@ -546,6 +546,18 @@ public interface CoreLocalizationConstant extends Messages { @Key("workspace.config.undefined") String workspaceConfigUndefined(); + @Key("workspace.id.undefined") + String workspaceIdUndefined(); + + @Key("workspace.get.failed") + String workspaceGetFailed(); + + @Key("workspace.not.ready") + String workspaceNotReady(String workspaceId); + + @Key("workspace.not.running") + String workspaceNotRunning(); + @Key("start.ws.error.title") String startWsErrorTitle(); diff --git a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java index ec80ed654a..bd47745859 100644 --- a/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java +++ b/core/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/FactoryWorkspaceComponent.java @@ -16,25 +16,23 @@ import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; +import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.factory.gwt.client.FactoryServiceClient; import org.eclipse.che.api.factory.shared.dto.Factory; import org.eclipse.che.api.machine.gwt.client.MachineManager; -import org.eclipse.che.api.promises.client.Function; -import org.eclipse.che.api.promises.client.FunctionException; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.PromiseError; -import org.eclipse.che.api.promises.client.js.Promises; import org.eclipse.che.api.workspace.gwt.client.WorkspaceServiceClient; import org.eclipse.che.api.workspace.shared.dto.UsersWorkspaceDto; -import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; import org.eclipse.che.ide.CoreLocalizationConstant; import org.eclipse.che.ide.actions.WorkspaceSnapshotCreator; import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.api.component.Component; import org.eclipse.che.ide.api.notification.NotificationManager; import org.eclipse.che.ide.api.preferences.PreferencesManager; -import org.eclipse.che.ide.api.component.Component; +import org.eclipse.che.ide.context.BrowserQueryFieldRenderer; import org.eclipse.che.ide.dto.DtoFactory; import org.eclipse.che.ide.rest.AsyncRequestCallback; import org.eclipse.che.ide.rest.DtoUnmarshallerFactory; @@ -43,27 +41,22 @@ import org.eclipse.che.ide.ui.loaders.initialization.InitialLoadingInfo; import org.eclipse.che.ide.ui.loaders.initialization.LoaderPresenter; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.ide.websocket.MessageBusProvider; -import org.eclipse.che.ide.context.BrowserQueryFieldRenderer; import org.eclipse.che.ide.workspace.create.CreateWorkspacePresenter; import org.eclipse.che.ide.workspace.start.StartWorkspacePresenter; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING; import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL; /** - * Retrieves specified factory, and creates and/or starts workspace configured in it. + * Retrieves specified factory, and reuse previously created workspace for this factory. * * @author Max Shaposhnik + * @author Florent Benoit */ @Singleton public class FactoryWorkspaceComponent extends WorkspaceComponent implements Component { - private static final String FACTORY_ID_ATTRIBUTE = "factoryId"; - private final FactoryServiceClient factoryServiceClient; - private Factory factory; + private String workspaceId; @Inject public FactoryWorkspaceComponent(WorkspaceServiceClient workspaceServiceClient, @@ -108,12 +101,17 @@ public class FactoryWorkspaceComponent extends WorkspaceComponent implements Com public void start(final Callback callback) { this.callback = callback; String factoryParams = browserQueryFieldRenderer.getParameterFromURLByName("factory"); + + // get workspace ID to use dedicated workspace for this factory + this.workspaceId = browserQueryFieldRenderer.getParameterFromURLByName("workspaceId"); + factoryServiceClient.getFactory(factoryParams, true, new AsyncRequestCallback(dtoUnmarshallerFactory.newUnmarshaller(Factory.class)) { @Override protected void onSuccess(Factory result) { - factory = result; appContext.setFactory(result); + + // get workspace tryStartWorkspace(); } @@ -127,108 +125,46 @@ public class FactoryWorkspaceComponent extends WorkspaceComponent implements Com @Override public void tryStartWorkspace() { - final WorkspaceConfigDto workspaceConfigDto = factory.getWorkspace(); - - if (workspaceConfigDto == null) { - notificationManager.notify(locale.failedToLoadFactory(), locale.workspaceConfigUndefined(), FAIL, true); + if (this.workspaceId == null) { + notificationManager.notify(locale.failedToLoadFactory(), locale.workspaceIdUndefined(), FAIL, true); return; } - getWorkspaceToStart().then(startWorkspace()).catchError(new Operation() { + getWorkspaceToStart().then(checkWorkspaceIsStarted()).catchError(new Operation() { @Override public void apply(PromiseError arg) throws OperationException { + notificationManager.notify(locale.workspaceNotReady(workspaceId), locale.workspaceGetFailed(), FAIL, true); Log.error(getClass(), arg.getMessage()); } }); } + /** - * Gets {@link Promise} of workspace according to {@code factory} {@link org.eclipse.che.api.factory.shared.dto.Policies}. - *

- *

Return policy for workspace: - *

perClick - every click from any user always creates a new workspace every time and if policy is not specified
- * it will be used by default. - *

- *

perUser - create one workspace for a user, a 2nd click from same user reloads the same workspace. - *

- *

perAccount - only create workspace for all users. A 2nd click from any user reloads the same workspace
- * Note that if location = owner, then only 1 workspace ever is created. If location = acceptor
- * it's one workspace for each unique user. + * Checks if specified workspace has {@link WorkspaceStatus} which is {@code RUNNING} + */ + protected Operation checkWorkspaceIsStarted() { + return new Operation() { + @Override + public void apply(UsersWorkspaceDto workspace) throws OperationException { + if (!RUNNING.equals(workspace.getStatus())) { + notificationManager.notify(locale.failedToLoadFactory(), locale.workspaceNotRunning(), FAIL, true); + throw new OperationException(locale.workspaceNotRunning()); + } else { + startWorkspace().apply(workspace); + } + } + }; + } + + + /** + * Gets {@link Promise} of workspace according to workspace ID specified in parameter. */ private Promise getWorkspaceToStart() { - final WorkspaceConfigDto workspaceConfigDto = factory.getWorkspace(); - final String policy = factory.getPolicies() == null ? "perClick" : factory.getPolicies().getCreate(); - switch (policy) { - case "perUser": - return getWorkspaceByConditionOrCreateNew(workspaceConfigDto, new Function() { - @Override - public Boolean apply(UsersWorkspaceDto existWs) throws FunctionException { - return factory.getId().equals(existWs.getConfig().getAttributes().get(FACTORY_ID_ATTRIBUTE)); - } - }); - case "perAccount": - return getWorkspaceByConditionOrCreateNew(workspaceConfigDto, new Function() { - @Override - public Boolean apply(UsersWorkspaceDto arg) throws FunctionException { - //TODO rework it when account will be ready - return workspaceConfigDto.getName().equals(arg.getConfig().getName()); - } - }); - case "perClick": - default: - return getWorkspaceByConditionOrCreateNew(workspaceConfigDto, new Function() { - @Override - public Boolean apply(UsersWorkspaceDto arg) throws FunctionException { - return false; - } - }); - } + // get workspace from the given id + return this.workspaceServiceClient.getUsersWorkspace(workspaceId); } - /** - * Gets the workspace by condition which is determined by given {@link Function} - * if workspace found by condition then it will be returned in other way new workspace will be returned. - */ - private Promise getWorkspaceByConditionOrCreateNew(final WorkspaceConfigDto workspaceConfigDto, - final Function condition) { - return workspaceServiceClient.getWorkspaces(0, 0) - .thenPromise(new Function, Promise>() { - @Override - public Promise apply(List workspaces) - throws FunctionException { - for (UsersWorkspaceDto existsWs : workspaces) { - if (condition.apply(existsWs)) { - return Promises.resolve(existsWs); - } - } - return createWorkspaceWithCounterName(workspaces, workspaceConfigDto); - } - }); - } - - /** - * Create workspace with counter in name and add factoryId attribute - * if workspace with specified name already exist. - */ - private Promise createWorkspaceWithCounterName(final List workspaces, - final WorkspaceConfigDto workspaceConfigDto) { - workspaceConfigDto.getAttributes().put(FACTORY_ID_ATTRIBUTE, factory.getId()); - final Set workspacesNames = new HashSet<>(); - final String wsName = workspaceConfigDto.getName(); - for (UsersWorkspaceDto workspace : workspaces) { - workspacesNames.add(workspace.getConfig().getName()); - } - if (!workspacesNames.contains(wsName)) { - return workspaceServiceClient.create(workspaceConfigDto, null); - } - String genName = wsName; - int counter = 1; - while (workspacesNames.contains(genName)) { - genName = wsName + '-' + counter++; - } - workspaceConfigDto.withName(genName); - workspaceConfigDto.getAttributes().put(FACTORY_ID_ATTRIBUTE, factory.getId()); - return workspaceServiceClient.create(workspaceConfigDto, null); - } } diff --git a/core/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/CoreLocalizationConstant.properties b/core/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/CoreLocalizationConstant.properties index 07dcea848b..4a9f220f7e 100644 --- a/core/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/CoreLocalizationConstant.properties +++ b/core/ide/che-core-ide-app/src/main/resources/org/eclipse/che/ide/CoreLocalizationConstant.properties @@ -267,8 +267,12 @@ started.ws=Workspace is running ext.server.started=Workspace agent started ext.server.stopped=Workspace agent stopped workspace.start.failed=Failed to start workspace +workspace.get.failed=Failed to get workspace failed.to.load.factory=Failed to load factory +workspace.not.ready=Workspace {0} is not ready +workspace.not.running=Workspace is not running workspace.config.undefined=Workspace config is not defined. +workspace.id.undefined=Workspace ID is not defined. start.ws.error.title=Start Workspace Error start.ws.error.content=Could not start workspace {0}. Reason: {1}