| /*=============================================================================# |
| # Copyright (c) 2009, 2018 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.rj.servi.rcpdemo; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.NoSuchElementException; |
| |
| import javax.security.auth.login.LoginException; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.jcommons.lang.Disposable; |
| |
| import org.eclipse.statet.ecommons.rmi.core.RMIRegistry; |
| import org.eclipse.statet.ecommons.rmi.core.RMIRegistryManager; |
| import org.eclipse.statet.ecommons.ts.core.Tool; |
| import org.eclipse.statet.ecommons.ts.core.ToolRunnable; |
| |
| import org.eclipse.statet.internal.rj.servi.rcpdemo.Activator; |
| import org.eclipse.statet.rj.RjException; |
| import org.eclipse.statet.rj.eclient.graphics.comclient.ERClientGraphicActionsFactory; |
| import org.eclipse.statet.rj.rsetups.RSetup; |
| import org.eclipse.statet.rj.rsetups.RSetupUtil; |
| import org.eclipse.statet.rj.server.RjsComConfig; |
| import org.eclipse.statet.rj.server.client.RClientGraphicFactory; |
| import org.eclipse.statet.rj.server.osgi.ERJContext; |
| import org.eclipse.statet.rj.servi.RServi; |
| import org.eclipse.statet.rj.servi.RServiUtil; |
| import org.eclipse.statet.rj.servi.node.RServiImpl; |
| import org.eclipse.statet.rj.servi.node.RServiNodeConfig; |
| import org.eclipse.statet.rj.servi.node.RServiNodeFactory; |
| import org.eclipse.statet.rj.servi.node.RServiNodeManager; |
| |
| |
| public class RServiManager implements Disposable { |
| |
| |
| private static final int LOCAL_INST= 1; |
| private static final int LOCAL_RSETUP= 2; |
| private static final int POOL= 3; |
| |
| private static class Config { |
| |
| private int mode; |
| private String address; |
| |
| } |
| |
| |
| private final String name; |
| |
| private Config config= new Config(); |
| |
| private RServiNodeManager localR; |
| |
| private RServiSession currentSession; |
| private final List<RServiSession> runningSessions= new ArrayList<>(); |
| |
| |
| public RServiManager(final String appId, final RClientGraphicFactory graphicFactory) { |
| this.name= appId; |
| |
| RjsComConfig.setProperty("rj.servi.graphicFactory", graphicFactory); |
| RjsComConfig.setProperty("rj.servi.comClientGraphicActionsFactory", |
| new ERClientGraphicActionsFactory() ); |
| } |
| |
| |
| public void setLocalInst(final String rHome) throws CoreException { |
| closeRServiSession(); |
| |
| final Config config= new Config(); |
| config.mode= LOCAL_INST; |
| config.address= rHome; |
| this.config= config; |
| |
| final RServiNodeConfig rConfig= new RServiNodeConfig(); |
| rConfig.setRHome(rHome); |
| rConfig.setEnableVerbose(true); |
| |
| startLocal(rConfig); |
| } |
| |
| public void setRSetup(final String setupId) throws CoreException { |
| closeRServiSession(); |
| |
| final Config config= new Config(); |
| config.mode= LOCAL_RSETUP; |
| config.address= setupId; |
| this.config= config; |
| |
| final RSetup setup= RSetupUtil.loadSetup(setupId, null); |
| if (setup == null) { |
| throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, "No R setup with specified id found.")); |
| } |
| |
| final RServiNodeConfig rConfig= new RServiNodeConfig(); |
| rConfig.setRHome(setup.getRHome()); |
| setLibs(setup.getRLibsSite(), rConfig, "R_LIBS_SITE"); |
| setLibs(setup.getRLibs(), rConfig, "R_LIBS"); |
| setLibs(setup.getRLibsUser(), rConfig, "R_LIBS_USER"); |
| rConfig.setEnableVerbose(true); |
| |
| startLocal(rConfig); |
| } |
| |
| public void setPool(final String poolAddress) { |
| closeRServiSession(); |
| |
| final Config config= new Config(); |
| config.mode= POOL; |
| config.address= poolAddress; |
| this.config= config; |
| } |
| |
| |
| private void setLibs(final List<String> locations, final RServiNodeConfig rConfig, final String varName) { |
| if (locations != null && locations.size() > 0) { |
| final StringBuilder sb= new StringBuilder(locations.get(0)); |
| for (int i= 0; i < locations.size(); i++) { |
| sb.append(File.pathSeparatorChar); |
| sb.append(locations.get(i)); |
| } |
| rConfig.getEnvironmentVariables().put(varName, sb.toString()); |
| } |
| } |
| |
| private void startLocal(final RServiNodeConfig rConfig) throws CoreException { |
| startLocal(rConfig, new NullProgressMonitor()); // TODO real monitor, e.g. in a Job |
| } |
| |
| private void startLocal(final RServiNodeConfig rConfig, |
| final IProgressMonitor monitor) throws CoreException { |
| if (rConfig == null) { |
| throw new NullPointerException("rConfig"); |
| } |
| if (monitor == null) { |
| throw new NullPointerException("monitor"); |
| } |
| try { |
| final ERJContext context= new ERJContext(); |
| if (System.getSecurityManager() == null) { |
| if (System.getProperty("java.security.policy") == null) { |
| final String policyFile= context.getServerPolicyFilePath(); |
| System.setProperty("java.security.policy", policyFile); |
| } |
| System.setSecurityManager(new SecurityManager()); |
| } |
| |
| final RMIRegistry registry= RMIRegistryManager.INSTANCE.getEmbeddedPrivateRegistry(monitor); |
| |
| final RServiNodeFactory nodeFactory= RServiImpl.createLocalNodeFactory(this.name, context); |
| nodeFactory.setRegistry(registry); |
| nodeFactory.setConfig(rConfig); |
| |
| final RServiNodeManager newLocalR= RServiImpl.createNodeManager(this.name, registry, nodeFactory); |
| newLocalR.start(); |
| if (this.localR != null) { |
| this.localR.stop(); |
| this.localR= null; |
| } |
| this.localR= newLocalR; |
| } |
| catch (final RjException e) { |
| throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Local R instance could not created.", e)); |
| } |
| } |
| |
| |
| public synchronized Tool getRServiSession() throws CoreException { |
| if (this.currentSession == null) { |
| final RServi servi= getRServi("session"); |
| this.currentSession= new RServiSession(servi) { |
| @Override |
| protected void terminated() { |
| synchronized (RServiManager.this.runningSessions) { |
| RServiManager.this.runningSessions.remove(this); |
| } |
| } |
| }; |
| synchronized (this.runningSessions) { |
| this.runningSessions.add(this.currentSession); |
| } |
| } |
| return this.currentSession; |
| } |
| |
| private void closeRServiSession() { |
| if (this.currentSession != null) { |
| this.currentSession.close(false); |
| this.currentSession= null; |
| } |
| } |
| |
| |
| public void schedule(final ToolRunnable runnable) throws CoreException { |
| final Tool session= getRServiSession(); |
| final IStatus status; |
| if (session != null) { |
| status= session.getQueue().add(runnable); |
| } |
| else { |
| status= new Status(IStatus.ERROR, Activator.BUNDLE_ID, |
| "R engine not available."); |
| } |
| if (!status.isOK()) { |
| throw new CoreException(status); |
| } |
| } |
| |
| public void scheduleDemo(final ToolRunnable runnable) { |
| try { |
| schedule(runnable); |
| } |
| catch (final CoreException e) { |
| final Status status= new Status(e.getStatus().getSeverity(), Activator.BUNDLE_ID, |
| "Cannot schedule '" + runnable.getLabel() + "'", e); |
| StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.LOG); |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| this.config= new Config(); |
| final RServiSession[] sessions; |
| synchronized (this.runningSessions) { |
| sessions= this.runningSessions.toArray(new RServiSession[this.runningSessions.size()]); |
| } |
| for (final RServiSession session : sessions) { |
| session.close(true); |
| } |
| } |
| |
| private RServi getRServi(final String task) throws CoreException { |
| final Config config= this.config; |
| final String key= this.name + "-" + task; |
| |
| try { |
| switch (config.mode) { |
| case LOCAL_INST: |
| case LOCAL_RSETUP: |
| return RServiUtil.getRServi(this.localR, key); |
| case POOL: |
| return RServiUtil.getRServi(config.address, key); |
| } |
| } |
| catch (final CoreException e) { |
| throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, "R not available, please check the configuration.", e)); |
| } |
| catch (final LoginException e) { |
| throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, "R not available, please check the configuration.", e)); |
| } |
| catch (final NoSuchElementException e) { |
| throw new CoreException(new Status(IStatus.INFO, Activator.BUNDLE_ID, "R currently not available, please try again later.", e)); |
| } |
| throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, "R is not configured, please check the configuration.")); |
| } |
| |
| } |