| /*=============================================================================# |
| # 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() } ); |
| } |
| |
| } |