blob: 6ce93a0d72f74c22efb4b54b9d9417f9eb91ae8d [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2015, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.docmlet.base.ui.viewer;
import static org.eclipse.statet.docmlet.base.ui.viewer.DocViewerConfig.DDE_APPLICATION_ATTR_KEY;
import static org.eclipse.statet.docmlet.base.ui.viewer.DocViewerConfig.DDE_COMMAND_ATTR_KEY;
import static org.eclipse.statet.docmlet.base.ui.viewer.DocViewerConfig.DDE_TOPIC_ATTR_KEY;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nullable;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.variables.IStringVariable;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.debug.core.util.LaunchUtils;
import org.eclipse.statet.ecommons.io.FileValidator;
import org.eclipse.statet.ecommons.io.win.DDE;
import org.eclipse.statet.ecommons.io.win.DDEClient;
import org.eclipse.statet.ecommons.resources.core.variables.ResourceVariableResolver;
import org.eclipse.statet.ecommons.resources.core.variables.ResourceVariables;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.ui.workbench.workspace.ResourceVariableUtil;
import org.eclipse.statet.ecommons.variables.core.StaticVariable;
import org.eclipse.statet.ecommons.variables.core.VariableText2;
import org.eclipse.statet.ecommons.variables.core.VariableUtils;
import org.eclipse.statet.docmlet.base.ui.DocmlBaseUI;
import org.eclipse.statet.docmlet.base.ui.processing.DocProcessingConfig;
import org.eclipse.statet.docmlet.base.ui.viewer.DocViewerConfig;
import org.eclipse.statet.docmlet.base.ui.viewer.DocViewerUI;
@NonNullByDefault
public class DocViewerLaunchConfig {
protected static CoreException createMissingConfigAttr(final String attrName) {
return new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
NLS.bind("Invalid configuration: configuration attribute ''{0}'' is missing.", attrName) ));
}
protected static CoreException createValidationFailed(final FileValidator validator) {
final IStatus status= validator.getStatus();
return new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
status.getMessage() ));
}
protected static CoreException createValidationFailed(final String message) {
return new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
message ));
}
public static class DDETask {
private final String command;
private final String application;
private final String topic;
public DDETask(final String command, final String application, final String topic) {
this.command= command;
this.application= application;
this.topic= topic;
}
public void exec() throws CoreException {
DDEClient.execute(this.application, this.topic, this.command);
}
}
private IFile docFile;
private ResourceVariableUtil docFileUtil;
private @Nullable VariableText2 variableText;
/**
* {@link #initDocFile(ILaunchConfiguration, SubMonitor)}
*/
public DocViewerLaunchConfig() {
}
public DocViewerLaunchConfig(final ResourceVariableUtil sourceFileUtil,
final @Nullable Map<String, ? extends IStringVariable> extraVariables) {
this.docFileUtil= nonNullAssert(sourceFileUtil);
setDocFile(nonNullAssert((IFile)sourceFileUtil.getResource()));
if (extraVariables != null) {
getVariableResolver().getExtraVariables().putAll(extraVariables);
}
}
public VariableText2 getVariableResolver() {
VariableText2 variableText= this.variableText;
if (variableText == null) {
final Map<String, IStringVariable> variables= new HashMap<>();
variableText= new VariableText2(variables);
this.variableText= variableText;
}
return variableText;
}
public void initDocFile(final ILaunchConfiguration configuration,
final SubMonitor m) throws CoreException {
final FileValidator validator= new FileValidator(true);
validator.setResourceLabel("document");
validator.setRequireWorkspace(true, true);
validator.setOnDirectory(IStatus.ERROR);
final String path= configuration.getAttribute(DocViewerUI.DOC_PATH_ATTR_NAME, (String) null);
if (path != null) {
validator.setExplicit(path);
}
else {
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
final ResourceVariableUtil util= new ResourceVariableUtil();
util.getResource();
DocViewerLaunchConfig.this.docFileUtil= util;
}
});
if (this.docFileUtil.getResource() == null) {
throw new CoreException(new Status(IStatus.ERROR, DocmlBaseUI.BUNDLE_ID,
"No resource for 'document' to view selected in the active Workbench window." ));
}
validator.setExplicit(this.docFileUtil.getResource());
}
if (validator.getStatus().getSeverity() == IStatus.ERROR) {
throw createValidationFailed(validator);
}
setDocFile(nonNullAssert((IFile)validator.getWorkspaceResource()));
}
protected void setDocFile(final IFile file) {
this.docFile= file;
ResourceVariableUtil docFileUtil= nullable(this.docFileUtil);
if (docFileUtil == null) {
docFileUtil= UIAccess.syncExecGet(() -> new ResourceVariableUtil(file));
this.docFileUtil= nonNullAssert(docFileUtil);
}
{ final Map<String, IStringVariable> variables= getVariableResolver().getExtraVariables();
VariableUtils.add(variables,
ResourceVariables.getSingleResourceVariables(),
new ResourceVariableResolver(this.docFileUtil) );
VariableUtils.add(variables, new StaticVariable(
DocProcessingConfig.SOURCE_FILE_PATH_VAR,
file.getFullPath().toString() ));
}
}
public IWorkbenchPage getWorkbenchPage() {
return this.docFileUtil.getWorkbenchPage();
}
public IFile getSourceFile() {
return this.docFile;
}
public ResourceVariableUtil getSourceFileVariableUtil() {
return this.docFileUtil;
}
public ProcessBuilder initProgram(final ILaunchConfiguration configuration) throws CoreException {
final IPath programPath;
{ final FileValidator validator= new FileValidator(true);
validator.setResourceLabel("program location");
validator.setOnDirectory(IStatus.ERROR);
validator.setVariableResolver(getVariableResolver());
final String path= configuration.getAttribute(DocViewerConfig.PROGRAM_FILE_ATTR_NAME,
(String) null );
if (path == null) {
throw createMissingConfigAttr(DocViewerConfig.PROGRAM_FILE_ATTR_NAME);
}
validator.setExplicit(path);
if (validator.getStatus().getSeverity() == IStatus.ERROR) {
throw createValidationFailed(validator);
}
programPath= URIUtil.toPath(validator.getFileStore().toURI());
}
final ProcessBuilder processBuilder= new ProcessBuilder(programPath.toOSString());
{ final ImList<String> arguments= getProgramArguments(configuration, getVariableResolver());
if (!arguments.isEmpty()) {
processBuilder.command().addAll(arguments);
}
}
{ final Map<String, String> environment= processBuilder.environment();
environment.clear();
environment.putAll(LaunchUtils.createEnvironment(configuration, null));
}
return processBuilder;
}
private ImList<String> getProgramArguments(final ILaunchConfiguration configuration,
final VariableText2 variableResolver) throws CoreException {
String arguments= configuration.getAttribute(DocViewerConfig.PROGRAM_ARGUMENTS_ATTR_NAME,
"" ); //$NON-NLS-1$
if (arguments.isEmpty()) {
return ImCollections.emptyList();
}
try {
arguments= variableResolver.performStringSubstitution(arguments, null);
return ImCollections.newList(DebugPlugin.parseArguments(arguments));
}
catch (final CoreException e) {
throw createValidationFailed(NLS.bind(Messages.ProgramArgs_error_Other_message,
e.getMessage() ));
}
}
public @Nullable DDETask loadDDETask(final ILaunchConfiguration configuration, final String attrQualifier,
@Nullable String taskLabel, final SubMonitor m) throws CoreException {
if (DDE.isSupported()) {
if (taskLabel == null) {
taskLabel= "DDE"; //$NON-NLS-1$
}
String command= configuration.getAttribute(attrQualifier + '/' + DDE_COMMAND_ATTR_KEY,
(String) null );
if (command != null && !command.isEmpty()) {
String application= configuration.getAttribute(attrQualifier + '/' + DDE_APPLICATION_ATTR_KEY,
"" ); //$NON-NLS-1$
String topic= configuration.getAttribute(attrQualifier + '/' + DDE_TOPIC_ATTR_KEY,
"" ); //$NON-NLS-1$
final VariableText2 variableResolver= getVariableResolver();
try {
command= variableResolver.performStringSubstitution(command, null);
}
catch (final CoreException e) {
createValidationFailed(NLS.bind(Messages.DDECommand_error_Other_message,
taskLabel, e.getMessage() ));
}
try {
application= variableResolver.performStringSubstitution(application, null);
}
catch (final CoreException e) {
throw createValidationFailed(NLS.bind(Messages.DDEApplication_error_Other_message,
taskLabel, e.getMessage() ));
}
try {
topic= variableResolver.performStringSubstitution(topic, null);
}
catch (final CoreException e) {
throw createValidationFailed(NLS.bind(Messages.DDETopic_error_Other_message,
taskLabel, e.getMessage() ));
}
return new DDETask(command, application, topic);
}
}
return null;
}
}