/*=============================================================================# # Copyright (c) 2013-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.rj.services.utils; import static de.walware.rj.server.client.AbstractRJComClient.RJ_CLIENT_ID; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.text.MessageFormat; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import de.walware.rj.data.RDataUtil; import de.walware.rj.data.RIntegerStore; import de.walware.rj.data.RVector; import de.walware.rj.data.UnexpectedRDataException; import de.walware.rj.renv.IRPkg; import de.walware.rj.renv.RNumVersion; import de.walware.rj.renv.RPkgType; import de.walware.rj.renv.RPkgUtil; import de.walware.rj.services.FunctionCall; import de.walware.rj.services.RService; /** * Utility to install an R package from a local file. * <p> * Run {@link #install(RService, IProgressMonitor)} to install the package.</p> * <p> * The class can be reused.</p> * * @since de.walware.rj.services 2.0 */ public class RPkgInstallation { private final IRPkg pkgInfo; private final File file; public RPkgInstallation(final File file) throws CoreException { if (file == null) { throw new NullPointerException(); } this.pkgInfo = RPkgUtil.checkPkgFileName(file.getName()); this.file = file; } public IRPkg getPkg() { return this.pkgInfo; } protected String getPkgFileName() { return this.file.getName(); } protected void uploadPkgFile(final String target, final RService r, final IProgressMonitor monitor) throws CoreException, IOException { FileInputStream in = null; try { in = new FileInputStream(this.file); r.uploadFile(in, this.file.length(), target, 0, monitor); } finally { if (in != null) { try { in.close(); } catch (final IOException e) {} } } } public void install(final RService r, final IProgressMonitor monitor) throws CoreException { final String source = getPkgFileName(); final RPkgType pkgType = RPkgUtil.checkPkgType(source, r.getPlatform()); Exception error = null; String serverFile = null; String libLoc = null; try { { final RVector<RIntegerStore> data = RDataUtil.checkRIntVector(r.evalData( "rj:::.renv.isValidLibLoc(.libPaths()[1])", monitor )); //$NON-NLS-1$ final int state = RDataUtil.checkSingleIntValue(data); libLoc = data.getNames().getChar(0); if (state != 0) { throw new CoreException(new Status(IStatus.ERROR, RJ_CLIENT_ID, MessageFormat.format("The library location ''{0}'' is not writable.", libLoc) )); } } { final FunctionCall call = r.createFunctionCall("dir.create"); //$NON-NLS-1$ call.addChar("rpkgs"); //$NON-NLS-1$ call.addLogi("showWarnings", false); //$NON-NLS-1$ call.evalVoid(monitor); serverFile = "rpkgs/" + source; //$NON-NLS-1$ } uploadPkgFile(serverFile, r, monitor); { final FunctionCall call = r.createFunctionCall("install.packages"); //$NON-NLS-1$ call.addChar(serverFile); call.addChar("lib", libLoc); //$NON-NLS-1$ call.addNull("repos"); //$NON-NLS-1$ call.addChar("type", RPkgUtil.getPkgTypeInstallKey(r.getPlatform(), pkgType)); //$NON-NLS-1$ call.evalVoid(monitor); } { final FunctionCall call = r.createFunctionCall("packageDescription"); //$NON-NLS-1$ call.addChar("pkg", this.pkgInfo.getName()); //$NON-NLS-1$ call.addChar("lib.loc", libLoc); //$NON-NLS-1$ call.addChar("fields", "Version"); //$NON-NLS-1$ //$NON-NLS-2$ final RVector<?> data = RDataUtil.checkRVector(call.evalData(monitor)); try { final String s = RDataUtil.checkSingleCharValue(data); final RNumVersion installedVersion = RNumVersion.create(s); if (!installedVersion.equals(this.pkgInfo.getVersion())) { throw new CoreException(new Status(IStatus.ERROR, RJ_CLIENT_ID, MessageFormat.format("Validation of package installation failed: installed package has different version (found= {0}, expected= {1}).", installedVersion.toString(), this.pkgInfo.getVersion().toString() ))); } } catch (final UnexpectedRDataException e) { throw new CoreException(new Status(IStatus.ERROR, RJ_CLIENT_ID, "Validation of package installation failed: no installed package found." )); } } clear(serverFile, r, monitor); serverFile = null; } catch (final IOException e) { error = e; } catch (final CoreException e) { error = e; } catch (final UnexpectedRDataException e) { error = e; } finally { if (serverFile != null) { try { clear(serverFile, r, monitor); } catch (final Exception e) {} } } if (error != null) { throw new CoreException(new Status(IStatus.ERROR, RJ_CLIENT_ID, MessageFormat.format("An error occurred when installing R package from {0}.", source), error )); } } private void clear(final String target, final RService r, final IProgressMonitor monitor) throws CoreException { final FunctionCall call = r.createFunctionCall("file.remove"); //$NON-NLS-1$ call.addChar(target); call.evalVoid(monitor); } }