/*******************************************************************************
* Copyright (c) 2012-2017 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.workspace;
import com.google.gwt.core.client.Callback;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.promises.client.Function;
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.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.ide.CoreLocalizationConstant;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.component.Component;
import org.eclipse.che.ide.api.dialogs.DialogFactory;
import org.eclipse.che.ide.api.factory.FactoryServiceClient;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.preferences.PreferencesManager;
import org.eclipse.che.ide.api.workspace.WorkspaceServiceClient;
import org.eclipse.che.ide.context.AppContextImpl;
import org.eclipse.che.ide.context.BrowserAddress;
import org.eclipse.che.ide.context.QueryParameters;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
import org.eclipse.che.ide.ui.loaders.LoaderPresenter;
import org.eclipse.che.ide.util.loging.Log;
import org.eclipse.che.ide.workspace.create.CreateWorkspacePresenter;
import org.eclipse.che.ide.workspace.start.StartWorkspacePresenter;
import java.util.HashMap;
import java.util.Map;
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
/**
* Retrieves specified factory, and reuse previously created workspace for this factory.
*
* @author Max Shaposhnik
* @author Florent Benoit
*/
@Singleton
public class FactoryWorkspaceComponent extends WorkspaceComponent {
private final QueryParameters queryParameters;
private final FactoryServiceClient factoryServiceClient;
private String workspaceId;
@Inject
public FactoryWorkspaceComponent(WorkspaceServiceClient workspaceServiceClient,
CreateWorkspacePresenter createWorkspacePresenter,
StartWorkspacePresenter startWorkspacePresenter,
FactoryServiceClient factoryServiceClient,
CoreLocalizationConstant locale,
DtoUnmarshallerFactory dtoUnmarshallerFactory,
EventBus eventBus,
AppContext appContext,
NotificationManager notificationManager,
BrowserAddress browserAddress,
DialogFactory dialogFactory,
PreferencesManager preferencesManager,
DtoFactory dtoFactory,
LoaderPresenter loader,
QueryParameters queryParameters,
RequestTransmitter requestTransmitter) {
super(workspaceServiceClient,
createWorkspacePresenter,
startWorkspacePresenter,
locale,
dtoUnmarshallerFactory,
eventBus,
appContext,
notificationManager,
browserAddress,
dialogFactory,
preferencesManager,
dtoFactory,
loader,
requestTransmitter);
this.factoryServiceClient = factoryServiceClient;
this.queryParameters = queryParameters;
}
@Override
public void start(final Callback<Component, Exception> callback) {
this.callback = callback;
Map<String, String> factoryParameters = new HashMap<>();
for (Map.Entry<String, String> queryParam : queryParameters.getAll().entrySet()) {
String key = queryParam.getKey();
if (key.startsWith("factory-")) {
factoryParameters.put(key.substring("factory-".length()), queryParam.getValue());
}
}
// get workspace ID to use dedicated workspace for this factory
this.workspaceId = queryParameters.getByName("workspaceId");
Promise<FactoryDto> factoryPromise;
// now search if it's a factory based on id or from parameters
if (factoryParameters.containsKey("id")) {
factoryPromise = factoryServiceClient.getFactory(factoryParameters.get("id"), true);
} else {
factoryPromise = factoryServiceClient.resolveFactory(factoryParameters, true);
}
factoryPromise.then((Function<FactoryDto, Void>)factory -> {
if (appContext instanceof AppContextImpl) {
(appContext).setFactory(factory);
}
// get workspace
tryStartWorkspace();
return null;
}).catchError(error -> {
Log.error(FactoryWorkspaceComponent.class, "Unable to load Factory", error);
callback.onFailure(new Exception(error.getCause()));
});
}
@Override
public void tryStartWorkspace() {
if (this.workspaceId == null) {
notificationManager.notify(locale.failedToLoadFactory(), locale.workspaceIdUndefined(), FAIL, FLOAT_MODE);
return;
}
getWorkspaceToStart().then(checkWorkspaceIsStarted()).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError arg) throws OperationException {
notificationManager.notify(locale.workspaceNotReady(workspaceId), locale.workspaceGetFailed(), FAIL, FLOAT_MODE);
Log.error(getClass(), arg.getMessage());
}
});
}
/**
* Checks if specified workspace has {@link WorkspaceStatus} which is {@code RUNNING}
*/
protected Operation<WorkspaceDto> checkWorkspaceIsStarted() {
return workspace -> {
if (!RUNNING.equals(workspace.getStatus())) {
notificationManager.notify(locale.failedToLoadFactory(), locale.workspaceNotRunning(), FAIL, FLOAT_MODE);
throw new OperationException(locale.workspaceNotRunning());
} else {
startWorkspace().apply(workspace);
}
};
}
/**
* Gets {@link Promise} of workspace according to workspace ID specified in parameter.
*/
private Promise<WorkspaceDto> getWorkspaceToStart() {
// get workspace from the given id
return this.workspaceServiceClient.getWorkspace(workspaceId);
}
}