/*=============================================================================#
# 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 GNU Lesser General Public License
# v2.1 or newer, which accompanies this distribution, and is available at
# http://www.gnu.org/licenses/lgpl.html
#
# Contributors:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.rj.server.jri.loader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UIManager;
import de.walware.rj.RjInitFailedException;
import de.walware.rj.server.Server;
import de.walware.rj.server.srvImpl.AbstractServerControl;
import de.walware.rj.server.srvImpl.InternalEngine;
import de.walware.rj.server.srvext.ExtServer;
import de.walware.rj.server.srvext.ServerRuntimePlugin;
import de.walware.rj.server.srvext.ServerUtil;
public final class JRIServerLoader {
public JRIServerLoader() {
}
public InternalEngine loadServer(final AbstractServerControl control, final Map<String, String> args,
final Server publicServer, final ServerRuntimePlugin plugin) throws Exception {
final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
try {
final boolean verbose = args.containsKey("verbose");
if (verbose) {
JRIClassLoader.setDebug(1000);
}
final JRIClassLoader loader = JRIClassLoader.getRJavaClassLoader();
if (verbose) {
loader.setDefaultAssertionStatus(true);
}
// Add JR classpath entry to rJava ClassLoader
// If this does not work, you can add in your command line to the rjava.class.path property
final String myClassResource = getClass().getName().replace('.', '/')+".class";
final URL url = getClass().getClassLoader().getResource(myClassResource);
String myClasspath = null;
if (url != null) {
String s = url.toExternalForm();
s = URLDecoder.decode(s, System.getProperty("file.encoding"));
if (s.endsWith(myClassResource)) {
s = s.substring(0, s.length()-myClassResource.length());
if (s.startsWith("jar:") && s.endsWith("!/")) {
s = s.substring(4, s.length()-2);
}
if (s.startsWith("file:")) {
s = s.substring(5);
}
myClasspath = s;
loader.addClassPath(s);
}
}
final InternalEngine engine;
try {
Thread.currentThread().setContextClassLoader(loader);
loader.loadRJavaClass("org.rosuda.JRI.REXP");
loader.loadRJavaClass("org.rosuda.JRI.RMainLoopCallbacks");
final Class<?> rEngineClazz = loader.loadRJavaClass("org.rosuda.JRI.Rengine");
final Method versionMethod = rEngineClazz.getMethod("getVersion");
final long version = ((Long) versionMethod.invoke(null)).longValue();
String serverClazzName = "de.walware.rj.server.jri.JRIServer";
final Class<? extends InternalEngine> serverClazz = (Class<? extends InternalEngine>) loader.loadRJavaClass(serverClazzName);
loader.loadRJavaClass(serverClazzName + "$InitCallbacks");
loader.loadRJavaClass(serverClazzName + "$HotLoopCallbacks");
engine = serverClazz.newInstance();
}
catch (final ClassNotFoundException e) {
Logger.getLogger("de.walware.rj.server.jri").log(Level.INFO, "Perhaps autodetection of RJ classpath entry failed: " +
((myClasspath != null) ? myClasspath : "-"));
throw e;
}
final int[] rjVersion = ServerUtil.RJ_VERSION;
final int[] implVersion = engine.getVersion();
if (implVersion.length < 2
|| implVersion[0] != rjVersion[0] || implVersion[1] != rjVersion[1]) {
final StringBuilder sb = new StringBuilder();
sb.append("The version of the loaded RJ server engine ");
ServerUtil.prettyPrintVersion(implVersion, sb);
sb.append(" is not compatible to RJ version ");
ServerUtil.prettyPrintVersion(rjVersion, sb);
sb.append(".");
sb.append(" Make sure that the correct R package 'rj' is installed and in the R library path.");
throw new RjInitFailedException(sb.toString());
}
final ExtServer localServer = (ExtServer) engine;
localServer.init(control, publicServer, loader);
// plugins
final List<String> plugins = ServerUtil.getArgValueList(args.get("plugins"));
if (plugins.contains("awt")) {
UIManager.put("ClassLoader", loader);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (final Throwable e) {
}
}
if (plugins.contains("swt")) {
localServer.addPlugin((ServerRuntimePlugin) Class.forName("de.walware.rj.server.srvstdext.SWTPlugin").newInstance());
}
if (plugin != null) {
localServer.addPlugin(plugin);
}
return engine;
}
finally {
try {
Thread.currentThread().setContextClassLoader(oldLoader);
}
catch (final Throwable e) { }
}
}
}