blob: d6802ea1f496f44784d180da1e33643095ca694e [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2005, 2021 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.r.launching.winrgui;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.statet.ecommons.preferences.core.Preference.BooleanPref;
import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils;
import org.eclipse.statet.ecommons.ui.util.DNDUtils;
import org.eclipse.statet.r.launching.IRCodeSubmitConnector;
public class RGWLauncher implements IRCodeSubmitConnector {
private static BooleanPref PREF_SUBMIT_DIRECTLY_ENABLED = new BooleanPref(
WinRGuiConnectorPlugin.BUNDLE_ID, "submit_directly.enabled"); //$NON-NLS-1$
private Clipboard fClipboard;
private final boolean fSubmitDirectly;
private String fExecutable;
public RGWLauncher() throws CoreException {
final URL dir = WinRGuiConnectorPlugin.getInstance().getBundle().getEntry("/win32/RGWConnector.exe"); //$NON-NLS-1$
fSubmitDirectly = PreferenceUtils.getInstancePrefs().getPreferenceValue(PREF_SUBMIT_DIRECTLY_ENABLED);
try {
final String local = FileLocator.toFileURL(dir).getPath();
final File file = new File(local);
if (!file.exists()) {
throw new IOException("Missing File '"+file.getAbsolutePath() + "'.");
}
fExecutable = file.getAbsolutePath();
} catch (final IOException e) {
throw new CoreException(new Status(
IStatus.ERROR,
WinRGuiConnectorPlugin.BUNDLE_ID,
-1,
"Error Loading R-GUI-Windows-Connector:",
e));
}
}
private enum SubmitType { DONOTHING, SUBMITINPUT, PASTECLIPBOARD }
@Override
public boolean submit(final List<String> lines, final boolean gotoConsole) throws CoreException {
// goto option not implemented (requires extension of .net-code)
final SubmitType type;
if (lines.isEmpty()) {
type = SubmitType.DONOTHING;
}
else if (fSubmitDirectly && lines.size() == 1) {
type = SubmitType.SUBMITINPUT;
}
else {
if (!copyToClipboard(lines)) {
return false;
}
type = SubmitType.PASTECLIPBOARD;
}
doRunConnector(type, (type == SubmitType.SUBMITINPUT) ? lines : null);
return true;
// StringBuilder rCmd = new StringBuilder();
// for (int i = 0; i < rCommands.length; i++) {
// rCmd.append(rCommands[i].replace("\"", "\\\""));
// rCmd.append("\n");
// }
// cmd[1] = rCmd.toString();
}
@Override
public void gotoConsole() throws CoreException {
doRunConnector(SubmitType.DONOTHING, null);
}
private void doRunConnector(final SubmitType connectorCmd, final List<String> writeToProcess) throws CoreException {
final String[] processCmd = new String[] {
fExecutable, connectorCmd.toString().toLowerCase() };
final AtomicReference<Process> process= new AtomicReference<>();
final IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
final IRunnableWithProgress runnable = new IRunnableWithProgress(){
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException {
try {
final Process p = DebugPlugin.exec(processCmd, null);
process.set(p);
if (writeToProcess != null) {
writeTextToProcess(p, writeToProcess);
}
final int exitCode = p.waitFor();
String message = null;
switch (exitCode) {
case 0:
// ok
break;
case 100: {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
message = reader.readLine();
if (message == null) {
message = "Unable to detect Error";
}
}
catch (final Exception e) {
message = "Unable to detect Error";
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (final Exception e) {}
}
}
break; }
default:
message = "Unknown Error";
break;
}
if (message != null) {
throw new CoreException(new Status(
IStatus.ERROR,
WinRGuiConnectorPlugin.BUNDLE_ID,
-1,
"Error when running RGui-Connector: \n"+message,
null));
}
}
catch (final Exception e) {
throw new InvocationTargetException(e);
}
}
};
try {
progressService.busyCursorWhile(runnable);
}
catch (final InvocationTargetException e1) {
final Throwable cause = e1.getCause();
if (cause instanceof CoreException) {
throw (CoreException) cause;
}
else {
throw new CoreException(new Status(IStatus.ERROR, WinRGuiConnectorPlugin.BUNDLE_ID, -1,
"Unknown Error occured when running R-Gui-Connector", e1));
}
}
catch (final InterruptedException e1) {
final Process p = process.get();
if (p != null) {
try {
p.destroy();
}
catch (final Exception e) { }
}
}
}
private void writeTextToProcess(final Process process, final List<String> text) {
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
for (int i = 0; i < text.size(); i++) {
writer.println(text.get(i));
}
}
catch (final Exception e) {
}
finally {
if (writer != null) {
try {
writer.close();
} catch (final Exception e) {}
}
}
}
private boolean copyToClipboard(final List<String> lines) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < lines.size(); i++) {
builder.append(lines.get(i));
builder.append("\n"); //$NON-NLS-1$
}
if (fClipboard == null) {
fClipboard = new Clipboard(Display.getCurrent());
}
return DNDUtils.setContent(fClipboard,
new String[] { builder.toString() },
new Transfer[] { TextTransfer.getInstance() } );
}
}