/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.gui.wizards.toolintegration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import de.rcenvironment.core.communication.api.PlatformService;
import de.rcenvironment.core.communication.common.LogicalNodeId;
import de.rcenvironment.core.component.api.ComponentUtils;
import de.rcenvironment.core.component.api.DistributedComponentKnowledge;
import de.rcenvironment.core.component.api.DistributedComponentKnowledgeService;
import de.rcenvironment.core.component.integration.ToolIntegrationConstants;
import de.rcenvironment.core.component.integration.ToolIntegrationContext;
import de.rcenvironment.core.component.integration.ToolIntegrationContextRegistry;
import de.rcenvironment.core.component.integration.ToolIntegrationService;
import de.rcenvironment.core.component.model.api.ComponentInstallation;
import de.rcenvironment.core.component.model.api.ComponentInterface;
import de.rcenvironment.core.gui.wizards.toolintegration.api.IntegrationWizardPageContributor;
import de.rcenvironment.core.gui.wizards.toolintegration.api.IntegrationWizardPageContributorRegistry;
import de.rcenvironment.core.gui.wizards.toolintegration.api.ToolIntegrationWizardPage;
import de.rcenvironment.core.utils.common.StringUtils;
import de.rcenvironment.core.utils.common.TempFileServiceAccess;
import de.rcenvironment.core.utils.incubator.ServiceRegistry;
import de.rcenvironment.core.utils.incubator.ServiceRegistryAccess;
/**
* Wizard for integrating a new external tool.
*
* @author Sascha Zur
*/
public class ToolIntegrationWizard extends Wizard {
protected static ToolIntegrationService integrationService;
private static final int MINIMUM_HEIGHT = 700;
private static final int MINIMUM_WIDTH = 500;
private static final Log LOGGER = LogFactory.getLog(ToolIntegrationWizard.class);
protected ToolIntegrationContextRegistry integrationContextRegistry;
private Map<String, Object> configurationMap;
private ToolCharacteristicsPage characteristicsPage;
private InOutputConfigurationPage inOutputPage;
private PropertyConfigurationPage propertyPage;
private ToolConfigurationPage toolPage;
private ScriptConfigurationPage scriptPage;
private final ServiceRegistryAccess serviceRegistryAccess;
private ChooseConfigurationPage editConfigurationPage;
private ToolIntegrationContext integrationContext;
private final String wizardType;
private String integrationType;
private final Map<String, List<ToolIntegrationWizardPage>> additionalPages = new HashMap<>();
private List<ToolIntegrationWizardPage> currentAdditionalPages = null;
private boolean configOK;
private Map<String, Object> previousConfiguration;
private File toolDocuTarget;
private File iconTarget;
/**
* Constructor for Wizard.
*
* @param type
*/
public ToolIntegrationWizard(boolean progressMonitor, String type) {
setNeedsProgressMonitor(progressMonitor);
configurationMap = new HashMap<>();
configurationMap.put(ToolIntegrationConstants.INTEGRATION_TYPE, ToolIntegrationConstants.COMMON_TOOL_INTEGRATION_CONTEXT_TYPE);
setWindowTitle(Messages.wizardTitle);
serviceRegistryAccess = ServiceRegistry.createAccessFor(this);
integrationService = serviceRegistryAccess.getService(ToolIntegrationService.class);
integrationContextRegistry = serviceRegistryAccess.getService(ToolIntegrationContextRegistry.class);
TrayDialog.setDialogHelpAvailable(true);
wizardType = type;
}
@Override
public void addPages() {
List<String> toolNames = new LinkedList<>();
for (String id : integrationService.getIntegratedComponentIds()) {
toolNames.add(id.substring(id.lastIndexOf(".") + 1));
}
List<String> groupNames = new ArrayList<>();
LogicalNodeId localNode = serviceRegistryAccess.getService(PlatformService.class).getLocalDefaultLogicalNodeId();
Collection<ComponentInstallation> installations = getInitialComponentKnowledge().getAllInstallations();
installations = ComponentUtils.eliminateComponentInterfaceDuplicates(installations, localNode);
for (ComponentInstallation ci : installations) {
ComponentInterface componentInterface = ci.getComponentRevision().getComponentInterface();
String groupName = componentInterface.getGroupName();
if (!groupName.startsWith("_") && !groupNames.contains(groupName)) {
groupNames.add(groupName);
}
}
Collections.sort(groupNames, String.CASE_INSENSITIVE_ORDER);
editConfigurationPage =
new ChooseConfigurationPage(Messages.chooseConfigPageTitle, integrationContextRegistry.getAllIntegrationContexts(), this,
wizardType);
characteristicsPage =
new ToolCharacteristicsPage(Messages.firstToolIntegrationPageTitle, configurationMap, toolNames, groupNames);
inOutputPage = new InOutputConfigurationPage(Messages.inOuputPage, configurationMap);
propertyPage = new PropertyConfigurationPage(Messages.propertyPage, configurationMap);
toolPage = new ToolConfigurationPage(Messages.toolPage, configurationMap);
scriptPage = new ScriptConfigurationPage(Messages.scriptPage, configurationMap);
addPage(editConfigurationPage);
addPage(characteristicsPage);
addPage(inOutputPage);
addPage(propertyPage);
addPage(toolPage);
addPage(scriptPage);
this.getShell().setMinimumSize(MINIMUM_WIDTH, MINIMUM_HEIGHT);
IntegrationWizardPageContributorRegistry contributorRegistry =
serviceRegistryAccess.getService(IntegrationWizardPageContributorRegistry.class);
for (IntegrationWizardPageContributor contributor : contributorRegistry.getAllContributors()) {
List<ToolIntegrationWizardPage> pages = contributor.getAdditionalPagesList(configurationMap);
additionalPages.put(contributor.getType(), pages);
for (ToolIntegrationWizardPage page : pages) {
addPage(page);
}
}
}
private DistributedComponentKnowledge getInitialComponentKnowledge() {
DistributedComponentKnowledgeService registry = serviceRegistryAccess.getService(DistributedComponentKnowledgeService.class);
return registry.getCurrentComponentKnowledge();
}
@Override
public IWizardPage getNextPage(IWizardPage page) {
IWizardPage nextPage = null;
if (currentAdditionalPages == null) {
if (page.equals(toolPage)) {
nextPage = scriptPage;
} else if (page.equals(scriptPage)) {
for (String key : additionalPages.keySet()) {
for (ToolIntegrationWizardPage addPage : additionalPages.get(key)) {
addPage.setPageComplete(true);
}
}
return null;
} else {
nextPage = super.getNextPage(page);
}
} else {
if (page.equals(toolPage)) {
nextPage = currentAdditionalPages.get(0);
} else if (currentAdditionalPages.contains(page) && currentAdditionalPages.indexOf(page) < currentAdditionalPages.size() - 1) {
nextPage = currentAdditionalPages.get(currentAdditionalPages.indexOf(page) + 1);
} else if (currentAdditionalPages.contains(page) && currentAdditionalPages.indexOf(page) == currentAdditionalPages.size() - 1) {
nextPage = scriptPage;
} else if (page.equals(scriptPage)) {
return null;
} else {
nextPage = super.getNextPage(page);
}
}
if (nextPage != null) {
((ToolIntegrationWizardPage) nextPage).updatePage();
}
return nextPage;
}
@Override
public IWizardPage getPreviousPage(IWizardPage page) {
IWizardPage previousPage = null;
if (currentAdditionalPages == null) {
if (page.equals(scriptPage)) {
previousPage = toolPage;
} else {
previousPage = super.getPreviousPage(page);
}
} else {
if (page.equals(scriptPage)) {
previousPage = currentAdditionalPages.get(currentAdditionalPages.size() - 1);
} else if (currentAdditionalPages.contains(page) && currentAdditionalPages.indexOf(page) > 0) {
previousPage = currentAdditionalPages.get(currentAdditionalPages.indexOf(page) - 1);
} else if (currentAdditionalPages.contains(page) && currentAdditionalPages.indexOf(page) == 0) {
previousPage = scriptPage;
} else if (page.equals(editConfigurationPage)) {
return null;
} else {
previousPage = super.getPreviousPage(page);
}
}
if (previousPage != null) {
((ToolIntegrationWizardPage) previousPage).updatePage();
}
return previousPage;
}
@Override
public boolean performFinish() {
Job job =
new Job(StringUtils.format(Messages.integrateToolJobTitle, configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME))) {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (checkConfiguration(configurationMap)) {
determineIntegrationContext();
integrationService.setFileWatcherActive(false);
configurationMap.put(ToolIntegrationConstants.IS_ACTIVE, true);
handleIcon();
Boolean publish = (Boolean) configurationMap.get(ToolIntegrationConstants.TEMP_KEY_PUBLISH_COMPONENT);
File toolPath = new File(new File(new File(integrationContext.getRootPathToToolIntegrationDirectory(),
integrationContext.getNameOfToolIntegrationDirectory()), integrationContext.getToolDirectoryPrefix()),
(String) configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME));
if (toolDocuTarget != null && configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH) != null
&& !((String) configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH)).isEmpty()) {
try {
FileUtils.copyDirectory(toolDocuTarget, new File(toolPath, ToolIntegrationConstants.DOCS_DIR_NAME));
TempFileServiceAccess.getInstance().disposeManagedTempDirOrFile(toolDocuTarget);
} catch (IOException e) {
LOGGER.error("Could not copy icon from temporary tool directory.", e);
}
}
if (configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH) == null
|| ((String) configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH)).isEmpty()) {
File docsDir = new File(toolPath, ToolIntegrationConstants.DOCS_DIR_NAME);
if (docsDir.exists()) {
FileUtils.deleteQuietly(docsDir);
}
}
if (publish != null && publish) {
integrationService.addPublishedTool(toolPath.getAbsolutePath());
configurationMap.remove(ToolIntegrationConstants.TEMP_KEY_PUBLISH_COMPONENT);
} else {
integrationService.unpublishTool(toolPath.getAbsolutePath());
}
integrationService.savePublishedComponents(integrationContext);
integrationService.updatePublishedComponents(integrationContext);
try {
integrationService.writeToolIntegrationFile(configurationMap, integrationContext);
} catch (IOException e) {
return Status.CANCEL_STATUS;
}
if (!integrationService.isToolIntegrated(configurationMap, integrationContext)) {
integrationService.integrateTool(configurationMap, integrationContext);
}
integrationService.setFileWatcherActive(true);
integrationService.registerRecursive((String) configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME),
integrationContext);
return Status.OK_STATUS;
}
return Status.CANCEL_STATUS;
}
private void handleIcon() {
if (configurationMap.get(ToolIntegrationConstants.KEY_TOOL_ICON_PATH) != null) {
File icon = new File((String) configurationMap.get(ToolIntegrationConstants.KEY_TOOL_ICON_PATH));
if (!icon.isAbsolute() && iconTarget != null) {
File toolConfigFile =
new File(integrationContext.getRootPathToToolIntegrationDirectory(),
integrationContext.getNameOfToolIntegrationDirectory()
+ File.separator
+ integrationContext.getToolDirectoryPrefix()
+ configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME));
icon = new File(toolConfigFile, icon.getName());
try {
FileUtils.copyFile(iconTarget, icon);
TempFileServiceAccess.getInstance().disposeManagedTempDirOrFile(iconTarget);
icon = new File(icon.getName());
} catch (IOException e) {
LOGGER.error("Could not copy icon from temporary tool directory.", e);
}
}
}
}
};
job.schedule();
return checkConfiguration(configurationMap);
}
private boolean checkConfiguration(Map<String, Object> configMap) {
configOK = true;
if (configMap == null || configMap.isEmpty()) {
configOK = false;
if (configOK) {
if (configMap == null || configMap.get(ToolIntegrationConstants.KEY_LAUNCH_SETTINGS) == null) {
configOK = false;
}
if (configMap == null || configMap.get(ToolIntegrationConstants.KEY_TOOL_NAME) == null) {
configOK = false;
}
}
}
return configOK;
}
public boolean isConfigOK() {
return configOK;
}
private void determineIntegrationContext() {
if (configurationMap.get(ToolIntegrationConstants.INTEGRATION_TYPE) != null) {
for (ToolIntegrationContext context : integrationContextRegistry.getAllIntegrationContexts()) {
if (context.getContextType().equals(configurationMap.get(ToolIntegrationConstants.INTEGRATION_TYPE))) {
integrationContext = context;
}
}
} else {
integrationContext =
integrationContextRegistry.getToolIntegrationContext(ToolIntegrationConstants.COMMON_TOOL_INTEGRATION_CONTEXT_UID);
}
}
/**
* Saves the wizards configuration to the given path.
*
* @param folderPath where to store the configuration.
*/
public void performSaveAs(String folderPath) {
determineIntegrationContext();
File toolConfigFile =
new File(folderPath, integrationContext.getNameOfToolIntegrationDirectory() + File.separator
+ integrationContext.getToolDirectoryPrefix() + configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME));
try {
integrationService.writeToolIntegrationFileToSpecifiedFolder(folderPath, configurationMap, integrationContext);
MessageBox infoDialog = new MessageBox(getShell(), SWT.ICON_INFORMATION | SWT.OK);
if (toolConfigFile.exists()) {
infoDialog.setText("Tool saved");
infoDialog
.setMessage(StringUtils.format("Successfully saved tool: %s\nLocation: " + toolConfigFile.getAbsolutePath(),
configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME)));
} else {
infoDialog.setText("Saving failed");
infoDialog
.setMessage(StringUtils.format("Could not save tool: %s\nLocation tried: " + toolConfigFile.getAbsolutePath(),
configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME)));
}
infoDialog.open();
} catch (IOException e) {
MessageBox errorDialog = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
errorDialog.setText("Saving failed");
errorDialog.setMessage(
StringUtils.format(
"Failed to save tool configuration to: " + toolConfigFile.getAbsolutePath() + "\nCause: " + e.getMessage(),
configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME)));
errorDialog.open();
}
}
protected void bindIntegrationService(ToolIntegrationService newIntegrationService) {
integrationService = newIntegrationService;
}
protected void bindIntegrationInformationRegistry(ToolIntegrationContextRegistry incIntegrationInformationRegistry) {
integrationContextRegistry = incIntegrationInformationRegistry;
}
/**
* Sets a new configurationMap and updates all pages.
*
* @param newConfigurationMap new map
*/
public void setConfigurationMap(Map<String, Object> newConfigurationMap) {
configurationMap = newConfigurationMap;
determineIntegrationContext();
for (IWizardPage page : this.getPages()) {
((ToolIntegrationWizardPage) page).setConfigMap(configurationMap);
}
}
/**
* Setter for the configuration map to edit.
*
* @param newPreviousConfiguration loaded map
* @param configJson where the config came from
*/
public void setPreviousConfiguration(Map<String, Object> newPreviousConfiguration, File configJson) {
Map<String, Object> configurationMapCopy = new HashMap<>();
previousConfiguration = new HashMap<>(newPreviousConfiguration);
if (newPreviousConfiguration != null) {
configurationMapCopy.putAll(newPreviousConfiguration);
}
setConfigurationMap(configurationMapCopy);
if (configJson != null) {
if (newPreviousConfiguration != null && newPreviousConfiguration.get(ToolIntegrationConstants.INTEGRATION_TYPE) != null) {
for (ToolIntegrationContext context : integrationContextRegistry.getAllIntegrationContexts()) {
if (newPreviousConfiguration.get(ToolIntegrationConstants.INTEGRATION_TYPE).equals(context.getContextType())) {
integrationContext = context;
}
}
} else {
integrationContext =
integrationContextRegistry.getToolIntegrationContext(ToolIntegrationConstants.COMMON_TOOL_INTEGRATION_CONTEXT_UID);
}
}
updateAllPages();
for (Entry<String, List<ToolIntegrationWizardPage>> addPages : additionalPages.entrySet()) {
if (newPreviousConfiguration != null
&& !addPages.getKey().equals(newPreviousConfiguration.get(ToolIntegrationConstants.INTEGRATION_TYPE))) {
for (ToolIntegrationWizardPage page : addPages.getValue()) {
page.setPageComplete(true);
}
}
}
}
/**
* Updated all pages registered in the wizard if a configuration changes.
*/
public void updateAllPages() {
for (IWizardPage page : getPages()) {
boolean isAdditionalPage = false;
for (String key : additionalPages.keySet()) {
if (additionalPages.get(key).contains(page)) {
isAdditionalPage = true;
}
}
if (!isAdditionalPage || (isAdditionalPage && currentAdditionalPages != null && currentAdditionalPages.contains(page))) {
((ToolIntegrationWizardPage) page).updatePage();
}
}
getContainer().updateButtons();
}
/**
* Removes old integrated component for updating the new one.
*
*/
public void removeOldIntegration() {
integrationService.setFileWatcherActive(false);
String previousToolName = "";
String toolName = (String) configurationMap.get(ToolIntegrationConstants.KEY_TOOL_NAME);
File previousToolDir = null;
if (previousConfiguration != null) {
previousToolName = (String) previousConfiguration.get(ToolIntegrationConstants.KEY_TOOL_NAME);
previousToolDir = new File(new File(integrationContext.getRootPathToToolIntegrationDirectory(),
integrationContext.getNameOfToolIntegrationDirectory()), previousToolName);
} else {
previousToolName = toolName;
}
if (previousToolDir != null) {
storeIconAndDocuInTempDir(previousToolDir);
}
integrationService.unregisterIntegration(previousToolName, integrationContext);
integrationService.removeTool(previousToolName, integrationContext);
if (!previousToolName.equals(toolName)) {
File delete = previousToolDir;
try {
FileUtils.forceDelete(delete);
} catch (IOException e) {
LogFactory.getLog(ToolIntegrationWizard.class).error(e);
}
} else {
if (configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH) == null
|| ((String) configurationMap.get(ToolIntegrationConstants.KEY_DOC_FILE_PATH)).isEmpty()) {
File docDir = new File(previousToolDir, ToolIntegrationConstants.DOCS_DIR_NAME);
if (docDir.listFiles() != null) {
for (File f : docDir.listFiles()) {
try {
FileUtils.forceDelete(f);
} catch (IOException e) {
LOGGER.error("Could not delete file in tool docs directory: ", e);
}
}
}
}
}
integrationService.setFileWatcherActive(true);
}
private void storeIconAndDocuInTempDir(File previousToolDir) {
try {
File tempToolDir = TempFileServiceAccess.getInstance().createManagedTempDir();
toolDocuTarget = null;
if (new File(previousToolDir, ToolIntegrationConstants.DOCS_DIR_NAME).exists()) {
toolDocuTarget = new File(tempToolDir, ToolIntegrationConstants.DOCS_DIR_NAME);
FileUtils.copyDirectory(new File(previousToolDir, ToolIntegrationConstants.DOCS_DIR_NAME), toolDocuTarget);
}
iconTarget = null;
String iconPath = (String) previousConfiguration.get(ToolIntegrationConstants.KEY_TOOL_ICON_PATH);
if (iconPath != null && !iconPath.isEmpty() && !new File(iconPath).isAbsolute()) {
if (new File(previousToolDir, iconPath).exists()) {
iconTarget = new File(tempToolDir, iconPath);
FileUtils.copyFile(new File(previousToolDir, iconPath), iconTarget);
}
}
} catch (IOException e) {
LOGGER.warn("Could not create temporiary tool dir.", e);
}
}
public String getIntegrationType() {
return integrationType;
}
/**
* Sets the new integration type and creates a new Map.
*
* @param incIntegrationType to set
* @param template if the new type comes from a template
*/
public void setIntegrationType(String incIntegrationType, boolean template) {
this.integrationType = incIntegrationType;
determineIntegrationContext();
}
/**
* Removes all pages that were added through an extension.
*/
public void removeAdditionalPages() {
currentAdditionalPages = null;
}
/**
* Sets the pages that are needed for the given context.
*
* @param contextType that needs additional pages
*/
public void setAdditionalPages(String contextType) {
currentAdditionalPages = additionalPages.get(contextType);
}
public Map<String, Object> getConfigurationMap() {
return configurationMap;
}
/**
* Returns the current {@link ToolIntegrationContext} or, if not yet set, the common version of it.
*
* @return current {@link ToolIntegrationContext}
*/
public ToolIntegrationContext getCurrentContext() {
if (integrationContext == null) {
return integrationContextRegistry.getToolIntegrationContext(ToolIntegrationConstants.COMMON_TOOL_INTEGRATION_CONTEXT_UID);
}
return integrationContext;
}
/**
*
*/
public void open() {
editConfigurationPage.updatePage();
}
}