/*=============================================================================# # Copyright (c) 2008-2016 Stephan Wahlbrink (WalWare.de) and others. # 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: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.statet.r.internal.console.ui.launching; import static de.walware.rj.server.srvext.ServerUtil.RJ_DATA_ID; import static de.walware.rj.server.srvext.ServerUtil.RJ_SERVER_ID; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.regex.Pattern; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.IVMInstall3; import org.eclipse.jdt.launching.JavaLaunchDelegate; import de.walware.ecommons.debug.core.util.LaunchUtils; import de.walware.ecommons.net.RMIAddress; import de.walware.statet.nico.core.runtime.ToolRunner; import de.walware.rj.server.srvext.ERJContext; import de.walware.rj.server.srvext.ServerUtil; import de.walware.statet.r.core.renv.IREnvConfiguration; import de.walware.statet.r.internal.console.ui.RConsoleUIPlugin; import de.walware.statet.r.launching.ui.REnvTab; /** * Launches RJ Server using JDT java launch mechanism */ public class RJEngineLaunchDelegate extends JavaLaunchDelegate { private static final String[] CLASSPATH_LIBS = new String[] { RJ_SERVER_ID, RJ_DATA_ID, "org.eclipse.swt", //$NON-NLS-1$ }; private static final String[] CODEBASE_LIBS = new String[] { RJ_SERVER_ID, }; private static final Pattern PATH_PATTERN = Pattern.compile("\\" + File.pathSeparatorChar); //$NON-NLS-1$ private final String fAddress; private final IREnvConfiguration fRenv; private final String[] fCodebaseLibs; private ERJContext fServerContext; private File fWorkingDirectory; private IProgressMonitor fMonitor; private String fLibPreloadVar; private String fLibPreloadFile; public RJEngineLaunchDelegate(final String address, final boolean requireCodebase, final IREnvConfiguration renv) throws CoreException { fAddress = address; fRenv = renv; fCodebaseLibs = (requireCodebase) ? CODEBASE_LIBS : null; fServerContext = new ERJContext(); setLibPreload(true); } @Override public void launch(final ILaunchConfiguration configuration, String mode, final ILaunch launch, final IProgressMonitor monitor) throws CoreException { fMonitor = (monitor != null) ? monitor : new NullProgressMonitor(); if (mode.equals(ILaunchManager.DEBUG_MODE)) { // TODO add configuration option (-> source lookup support for Java) mode = ILaunchManager.RUN_MODE; } super.launch(configuration, mode, launch, fMonitor); } @Override public IPath getWorkingDirectoryPath(final ILaunchConfiguration configuration) throws CoreException { final IFileStore workingDirectory = REnvTab.getWorkingDirectory(configuration); return URIUtil.toPath(workingDirectory.toURI()); } @Override public File verifyWorkingDirectory(final ILaunchConfiguration configuration) throws CoreException { return fWorkingDirectory = super.verifyWorkingDirectory(configuration); } public IFileStore getWorkingDirectory() { if (fWorkingDirectory != null) { return EFS.getLocalFileSystem().fromLocalFile(fWorkingDirectory); } return null; } public void setLibPreload(final boolean enable) { if (enable) { if (Platform.getOS().equals(Platform.OS_WIN32)) { fLibPreloadVar = null; fLibPreloadFile = null; } else if (Platform.getOS().equals(Platform.OS_MACOSX)) { fLibPreloadVar = null; // fLibPreloadFile = "DYLD_INSERT_LIBRARIES"; //$NON-NLS-1$ fLibPreloadFile = "libjsig.dylib"; //$NON-NLS-1$ } else { // *nix fLibPreloadVar = "LD_PRELOAD"; //$NON-NLS-1$ fLibPreloadFile = "libjsig.so"; //$NON-NLS-1$ } } else { fLibPreloadVar = null; fLibPreloadFile = null; } } @Override public String[] getEnvironment(final ILaunchConfiguration configuration) throws CoreException { final IVMInstall vmInstall = getVMInstall(configuration); // already verified final Map<String, String> additional = new HashMap<>(); final File location = vmInstall.getInstallLocation(); if (location != null) { additional.put("JAVA_HOME", location.getAbsolutePath()); //$NON-NLS-1$ } @SuppressWarnings("unchecked") final Map<String, String> envp = LaunchUtils.createEnvironment(configuration, new Map[] { additional, fRenv.getEnvironmentsVariables() }); if (fLibPreloadVar != null) { String value = envp.get(fLibPreloadVar); if (value == null || !value.contains("libjsig")) { //$NON-NLS-1$ final String path = ((IVMInstall3) vmInstall).evaluateSystemProperties( new String[] { "java.library.path" }, fMonitor).get("java.library.path"); //$NON-NLS-1$ //$NON-NLS-2$ if (path != null) { final String[] pathList = PATH_PATTERN.split(path); for (int i = 0; i < pathList.length; i++) { final File file = new File(pathList[i], fLibPreloadFile); if (file.exists()) { final String s = file.getAbsolutePath(); if (s.indexOf(' ') < 0) { // whitespace is separator char if (value != null && value.length() > 0) { value = s + ' ' + value; } else { value = s; } envp.put(fLibPreloadVar, value); } break; } } } } } return LaunchUtils.toKeyValueStrings(envp); } @Override public String[] getClasspath(final ILaunchConfiguration configuration) throws CoreException { final String[] rjLibs = fServerContext.searchRJLibs(CLASSPATH_LIBS); final LinkedHashSet<String> classpath = new LinkedHashSet<>(); classpath.addAll(Arrays.asList(super.getClasspath(configuration))); classpath.addAll(Arrays.asList(rjLibs)); return classpath.toArray(new String[classpath.size()]); } @Override public String getVMArguments(final ILaunchConfiguration configuration) throws CoreException { final String args = super.getVMArguments(configuration); final StringBuilder s = new StringBuilder(" "); //$NON-NLS-1$ if (args != null) { s.append(args); } if (s.indexOf(" -Djava.security.policy=") < 0) { //$NON-NLS-1$ try { final URL intern = Platform.getBundle(RJ_SERVER_ID).getEntry("/localhost.policy"); //$NON-NLS-1$ final URL java = FileLocator.resolve(intern); s.append(" -Djava.security.policy="); //$NON-NLS-1$ s.append('"'); s.append(java.toString()); s.append('"'); } catch (final IOException e) { RConsoleUIPlugin.log(new Status(IStatus.ERROR, RConsoleUIPlugin.PLUGIN_ID, -1, "An error trying to resolve path to security policy", e )); //$NON-NLS-1$ } } if (s.indexOf(" -Djava.rmi.server.hostname=") < 0) { //$NON-NLS-1$ s.append(" -Djava.rmi.server.hostname="); //$NON-NLS-1$ s.append(RMIAddress.LOOPBACK.getHostAddress()); } if (fCodebaseLibs != null && s.indexOf(" -Djava.rmi.server.codebase=") < 0) { //$NON-NLS-1$ s.append(" -Djava.rmi.server.codebase=\""); //$NON-NLS-1$ final String[] rjLibs = fServerContext.searchRJLibs(fCodebaseLibs); s.append(ServerUtil.concatCodebase(rjLibs)); s.append("\""); //$NON-NLS-1$ } if (!ToolRunner.captureLogOnly(configuration) && s.indexOf(" -Dde.walware.rj.verbose=") < 0 ) { //$NON-NLS-1$ s.append(" -Dde.walware.rj.verbose=true"); //$NON-NLS-1$ } if (Platform.getOS().equals(Platform.OS_MACOSX) && s.indexOf(" -d32") < 0 && s.indexOf(" -d64") < 0) { //$NON-NLS-1$ //$NON-NLS-2$ final String rArch = fRenv.getSubArch(); if (rArch != null) { if (rArch.equals("i386") || rArch.equals("i586") || rArch.equals("i686")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ s.append(" -d32"); //$NON-NLS-1$ } else if (rArch.equals("x86_64")) { //$NON-NLS-1$ s.append(" -d64"); //$NON-NLS-1$ } } } return s.substring(1); } @Override public String getMainTypeName(final ILaunchConfiguration configuration) throws CoreException { return "de.walware.rj.server.RMIServerControl"; //$NON-NLS-1$ } @Override public String getProgramArguments(final ILaunchConfiguration configuration) throws CoreException { final StringBuilder args = new StringBuilder("start"); //$NON-NLS-1$ args.append(' '); args.append(fAddress); args.append(" -auth=none"); //$NON-NLS-1$ args.append(" -embedded"); //$NON-NLS-1$ args.append(" -plugins="); //$NON-NLS-1$ args.append("awt,"); //$NON-NLS-1$ if (Platform.getOS().equals(Platform.OS_WIN32)) { args.append("swt,"); //$NON-NLS-1$ } return args.toString(); } @Override protected void prepareStopInMain(final ILaunchConfiguration configuration) throws CoreException { } }