/******************************************************************************* * 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.plugin.debugger.ide.configuration; import com.google.common.base.Optional; import com.google.inject.Inject; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.api.promises.client.PromiseError; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.ide.api.debug.DebugConfiguration; import org.eclipse.che.ide.api.debug.DebugConfigurationType; import org.eclipse.che.ide.api.debug.DebugConfigurationsManager; import org.eclipse.che.ide.api.dialogs.DialogFactory; import org.eclipse.che.ide.debug.Debugger; import org.eclipse.che.ide.debug.DebuggerManager; import org.eclipse.che.ide.dto.DtoFactory; import org.eclipse.che.ide.macro.CurrentProjectPathMacro; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.ide.util.storage.LocalStorage; import org.eclipse.che.ide.util.storage.LocalStorageProvider; import org.eclipse.che.plugin.debugger.ide.DebuggerLocalizationConstant; import org.eclipse.che.plugin.debugger.ide.configuration.dto.DebugConfigurationDto; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.Collections.emptyList; /** * Implementation of {@link DebugConfigurationsManager}. * * @author Artem Zatsarynnyi */ public class DebugConfigurationsManagerImpl implements DebugConfigurationsManager { private static final String LOCAL_STORAGE_DEBUG_CONF_KEY = "che-debug-configurations"; private final DtoFactory dtoFactory; private final DebugConfigurationTypeRegistry configurationTypeRegistry; private final Optional<LocalStorage> localStorageOptional; private final Set<ConfigurationChangedListener> configurationChangedListeners; private final List<DebugConfiguration> configurations; private final DebuggerManager debuggerManager; private final DialogFactory dialogFactory; private final DebuggerLocalizationConstant localizationConstants; private final CurrentProjectPathMacro currentProjectPathMacro; private DebugConfiguration currentDebugConfiguration; @Inject public DebugConfigurationsManagerImpl(LocalStorageProvider localStorageProvider, DtoFactory dtoFactory, DebugConfigurationTypeRegistry debugConfigurationTypeRegistry, DebuggerManager debuggerManager, DialogFactory dialogFactory, DebuggerLocalizationConstant localizationConstants, CurrentProjectPathMacro currentProjectPathMacro) { this.dtoFactory = dtoFactory; this.configurationTypeRegistry = debugConfigurationTypeRegistry; this.debuggerManager = debuggerManager; this.dialogFactory = dialogFactory; this.localizationConstants = localizationConstants; this.currentProjectPathMacro = currentProjectPathMacro; localStorageOptional = Optional.fromNullable(localStorageProvider.get()); configurationChangedListeners = new HashSet<>(); configurations = new ArrayList<>(); loadConfigurations(); } private void loadConfigurations() { for (DebugConfigurationDto descriptor : retrieveConfigurations()) { final DebugConfigurationType type = configurationTypeRegistry.getConfigurationTypeById(descriptor.getType()); // skip configuration if it's type isn't registered if (type != null) { try { configurations.add(new DebugConfiguration(type, descriptor.getName(), descriptor.getHost(), descriptor.getPort(), descriptor.getConnectionProperties())); } catch (IllegalArgumentException e) { Log.warn(EditDebugConfigurationsPresenter.class, e.getMessage()); } } } } private List<DebugConfigurationDto> retrieveConfigurations() { List<DebugConfigurationDto> configurationsList; if (localStorageOptional.isPresent()) { final LocalStorage localStorage = localStorageOptional.get(); final Optional<String> data = Optional.fromNullable(localStorage.getItem(LOCAL_STORAGE_DEBUG_CONF_KEY)); if (data.isPresent() && !data.get().isEmpty()) { configurationsList = dtoFactory.createListDtoFromJson(data.get(), DebugConfigurationDto.class); } else { configurationsList = emptyList(); } } else { configurationsList = emptyList(); } return configurationsList; } @Override public Optional<DebugConfiguration> getCurrentDebugConfiguration() { return Optional.fromNullable(currentDebugConfiguration); } @Override public void setCurrentDebugConfiguration(@Nullable DebugConfiguration debugConfiguration) { currentDebugConfiguration = debugConfiguration; } @Override public List<DebugConfiguration> getConfigurations() { return new ArrayList<>(configurations); } @Override public DebugConfiguration createConfiguration(String typeId, String name, String host, int port, Map<String, String> connectionProperties) { final DebugConfigurationType configurationType = configurationTypeRegistry.getConfigurationTypeById(typeId); final DebugConfiguration configuration = new DebugConfiguration(configurationType, generateUniqueConfigurationName(configurationType, name), host, port, connectionProperties); configurations.add(configuration); saveConfigurations(); fireConfigurationAdded(configuration); return configuration; } private String generateUniqueConfigurationName(DebugConfigurationType configurationType, String customName) { Set<String> configurationNames = new HashSet<>(configurations.size()); for (DebugConfiguration configuration : configurations) { configurationNames.add(configuration.getName()); } final String configurationName; if (customName == null || customName.isEmpty()) { configurationName = "Remote " + configurationType.getDisplayName(); } else { if (!configurationNames.contains(customName)) { return customName; } configurationName = customName + " copy"; } if (!configurationNames.contains(configurationName)) { return configurationName; } for (int count = 1; count < 1000; count++) { if (!configurationNames.contains(configurationName + "-" + count)) { return configurationName + "-" + count; } } return configurationName; } @Override public void removeConfiguration(DebugConfiguration configuration) { if (getCurrentDebugConfiguration().isPresent() && getCurrentDebugConfiguration().get().equals(configuration)) { setCurrentDebugConfiguration(null); } configurations.remove(configuration); saveConfigurations(); fireConfigurationRemoved(configuration); } private void saveConfigurations() { if (localStorageOptional.isPresent()) { List<DebugConfigurationDto> configurationDtos = new ArrayList<>(); for (DebugConfiguration configuration : configurations) { configurationDtos.add(dtoFactory.createDto(DebugConfigurationDto.class) .withType(configuration.getType().getId()) .withName(configuration.getName()) .withHost(configuration.getHost()) .withPort(configuration.getPort()) .withConnectionProperties(configuration.getConnectionProperties())); } localStorageOptional.get().setItem(LOCAL_STORAGE_DEBUG_CONF_KEY, dtoFactory.toJson(configurationDtos)); } } @Override public void addConfigurationsChangedListener(ConfigurationChangedListener listener) { configurationChangedListeners.add(listener); } @Override public void removeConfigurationsChangedListener(ConfigurationChangedListener listener) { configurationChangedListeners.remove(listener); } @Override public void apply(final DebugConfiguration debugConfiguration) { if (debugConfiguration == null) { return; } if (debuggerManager.getActiveDebugger() != null) { dialogFactory.createMessageDialog(localizationConstants.connectToRemote(), localizationConstants.debuggerAlreadyConnected(), null).show(); return; } final Debugger debugger = debuggerManager.getDebugger(debugConfiguration.getType().getId()); if (debugger != null) { debuggerManager.setActiveDebugger(debugger); currentProjectPathMacro.expand().then(new Operation<String>() { @Override public void apply(String arg) throws OperationException { Map<String, String> connectionProperties = prepareConnectionProperties(debugConfiguration, arg); debugger.connect(connectionProperties).catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { debuggerManager.setActiveDebugger(null); } }); } }); } } private Map<String, String> prepareConnectionProperties(DebugConfiguration debugConfiguration, String currentProjectPath) { Map<String, String> connectionProperties = new HashMap<>(2 + debugConfiguration.getConnectionProperties().size()); connectionProperties.put("HOST", debugConfiguration.getHost()); connectionProperties.put("PORT", String.valueOf(debugConfiguration.getPort())); for (Map.Entry<String, String> entry : debugConfiguration.getConnectionProperties().entrySet()) { String newValue = entry.getValue().replace(currentProjectPathMacro.getName(), currentProjectPath); connectionProperties.put(entry.getKey(), newValue); } return connectionProperties; } private void fireConfigurationAdded(DebugConfiguration configuration) { for (ConfigurationChangedListener listener : configurationChangedListeners) { listener.onConfigurationAdded(configuration); } } private void fireConfigurationRemoved(DebugConfiguration configuration) { for (ConfigurationChangedListener listener : configurationChangedListeners) { listener.onConfigurationRemoved(configuration); } } }