| /*=============================================================================# |
| # Copyright (c) 2009, 2019 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.internal.rhelp.server.update; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import static org.eclipse.statet.rhelp.server.Application.BUNDLE_ID; |
| |
| import java.util.NoSuchElementException; |
| |
| import javax.security.auth.login.LoginException; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.rmi.RMIRegistry; |
| import org.eclipse.statet.jcommons.rmi.RMIRegistryManager; |
| import org.eclipse.statet.jcommons.runtime.ClassLoaderUtils; |
| import org.eclipse.statet.jcommons.status.ErrorStatus; |
| import org.eclipse.statet.jcommons.status.ProgressMonitor; |
| import org.eclipse.statet.jcommons.status.StatusException; |
| |
| import org.eclipse.statet.rhelp.server.Application; |
| import org.eclipse.statet.rj.RjException; |
| import org.eclipse.statet.rj.renv.core.REnv; |
| import org.eclipse.statet.rj.renv.core.REnvConfiguration; |
| import org.eclipse.statet.rj.server.util.RJContext; |
| import org.eclipse.statet.rj.servi.RServi; |
| import org.eclipse.statet.rj.servi.RServiUtils; |
| 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; |
| |
| |
| @NonNullByDefault |
| public class REnvServiController { |
| |
| |
| private static final int LOCAL_RENV= 1; |
| private static final int POOL= 3; |
| |
| private static class Config { |
| |
| private final int mode; |
| private @Nullable String address; |
| private @Nullable RServiNodeManager localR; |
| |
| public Config(final int mode) { |
| this.mode= mode; |
| } |
| |
| } |
| |
| private static final Config NO_CONFIG= new Config(0); |
| |
| |
| private final REnv rEnv; |
| |
| private @Nullable RServiNodeConfig localConfig; |
| |
| private Config current= NO_CONFIG; |
| |
| |
| public REnvServiController(final REnv rEnv) { |
| this.rEnv= rEnv; |
| } |
| |
| |
| public void configure() throws StatusException { |
| final REnvConfiguration rEnvConfig= this.rEnv.get(REnvConfiguration.class); |
| |
| final RServiNodeConfig rServiConfig= new RServiNodeConfig(); |
| rServiConfig.load(rEnvConfig); |
| |
| try { |
| final Class<?> handlerClass= Class.forName("org.springframework.boot.loader.jar.Handler"); |
| final String url= ClassLoaderUtils.getClassLocationUrlString(handlerClass); |
| rServiConfig.addToClasspath(ClassLoaderUtils.toJClassPathEntryString(url)); |
| rServiConfig.setJavaArgs("-Djava.protocol.handler.pkgs=org.springframework.boot.loader"); //$NON-NLS-1$ |
| } |
| catch (final ClassNotFoundException e) { |
| final String url= ClassLoaderUtils.getClassLocationUrlString(REnvServiController.class); |
| if (!url.startsWith("file:")) { |
| throw new StatusException(new ErrorStatus(Application.BUNDLE_ID, |
| "An error occurred when configuring protocol handler for fat jar.", |
| e )); |
| } |
| } |
| |
| this.localConfig= rServiConfig; |
| } |
| |
| public void startR(final ProgressMonitor m) throws StatusException { |
| startLocal(new Config(LOCAL_RENV), m); |
| } |
| |
| public void stopR() { |
| set(NO_CONFIG); |
| } |
| |
| public void setPool(final String poolAddress) { |
| final Config config= new Config(POOL); |
| config.address= poolAddress; |
| |
| set(config); |
| } |
| |
| private void startLocal(final Config config, |
| final ProgressMonitor m) throws StatusException { |
| nonNullAssert(config); |
| |
| final RServiNodeConfig rServiConfig= this.localConfig; |
| if (rServiConfig == null) { |
| throw new IllegalStateException("R is not yet configured."); |
| } |
| |
| try { |
| RJContext.class.getProtectionDomain().getCodeSource().getLocation(); |
| |
| final RJContext context= new RJContext(RJContext.detectRJLibPaths()); |
| // 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(m); |
| |
| final RServiNodeFactory nodeFactory= RServiImpl.createLocalNodeFactory( |
| this.rEnv.getId(), context ); |
| nodeFactory.setRegistry(registry); |
| nodeFactory.setConfig(rServiConfig); |
| |
| final RServiNodeManager localR= RServiImpl.createNodeManager( |
| this.rEnv.getId(), registry, nodeFactory ); |
| localR.start(); |
| config.localR= localR; |
| |
| set(config); |
| } |
| catch (final RjException e) { |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "Local R instance could not created.", e )); |
| } |
| } |
| |
| private void set(final Config config) { |
| Config previous; |
| synchronized (this) { |
| previous= this.current; |
| this.current= config; |
| } |
| |
| if (previous != null && previous.localR != null) { |
| previous.localR.stop(); |
| } |
| } |
| |
| |
| @SuppressWarnings("null") |
| public RServi getRServi(final String task) throws StatusException { |
| final Config config= this.current; |
| final String key= this.rEnv.getId() + "->" + task; |
| |
| try { |
| switch (config.mode) { |
| case LOCAL_RENV: |
| return RServiUtils.getRServi(config.localR, key); |
| case POOL: |
| return RServiUtils.getRServi(config.address, key); |
| } |
| } |
| catch (final StatusException e) { |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "R not available, please check the configuration.", e )); |
| } |
| catch (final LoginException e) { |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "R not available, please check the configuration.", e )); |
| } |
| catch (final NoSuchElementException e) { |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "R currently not available, please try again later.", e )); |
| } |
| throw new StatusException(new ErrorStatus(BUNDLE_ID, |
| "R is not configured, please check the configuration." )); |
| } |
| |
| } |