/* * Copyright (c) 2009 The Jackson Laboratory * * This software was developed by Gary Churchill's Lab at The Jackson * Laboratory (see http://research.jax.org/faculty/churchill). * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software. If not, see <http://www.gnu.org/licenses/>. */ package org.jax.r.rintegration; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipInputStream; import org.jax.util.ConfigurationUtilities; import org.jax.util.TypeSafeSystemProperties; import org.jax.util.io.FileUtilities; /** * Contains basic functionality common to most platforms. * @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A> */ public abstract class AbstractPlatformSpecificRFunctions implements PlatformSpecificRFunctions { /** * the jri natives directory */ private static final String JRI_NATIVES_BASE_DIR_NAME = "jri-natives"; /** * the prefix for the JRI R dependency directory */ private static final String JRI_R_DEPENDENCY_VERSION_PREFIX = "r-"; /** * our logger... */ private static final Logger LOG = Logger.getLogger( AbstractPlatformSpecificRFunctions.class.getName()); // /** // * {@inheritDoc} // */ // public boolean updateSettingsForRInstallation( // VirtualMachineSettings settingsToUpdate, // RInstallation installation) // { // File matchingNativeDir = this.getMatchingJriNativeDir( // installation); // if(matchingNativeDir == null) // { // LOG.severe( // "could not find matching JRI natives directory " + // "for R version " + installation.getRVersion()); // return false; // } // else // { // if(LOG.isLoggable(Level.FINE)) // { // LOG.fine( // "adding directory \"" + // matchingNativeDir.getAbsolutePath() + // "\" to " + // TypeSafeSystemProperties.JAVA_HOME_PROP_NAME); // LOG.fine( // "setting environment var: " + // RInstallation.R_HOME_ENV_KEY + " to " + // installation.getRHomeDirectory().getAbsolutePath()); // } // settingsToUpdate.prependToJavaLibraryPath( // matchingNativeDir.getAbsolutePath()); // settingsToUpdate.getEnvironment().put( // RInstallation.R_HOME_ENV_KEY, // installation.getRHomeDirectory().getAbsolutePath()); // // return true; // } // } /** * {@inheritDoc} */ public String[] getSupportedRSuperVersions() { File[] jriNativeDirs = this.getJriNativeDirs(); if(jriNativeDirs == null) { return null; } else { ArrayList<String> supportedRSuperVersions = new ArrayList<String>(jriNativeDirs.length); for(File currDepDir: jriNativeDirs) { String currDepDirString = currDepDir.getName(); if(currDepDirString.startsWith(JRI_R_DEPENDENCY_VERSION_PREFIX)) { String versionSubstring = currDepDirString.substring( JRI_R_DEPENDENCY_VERSION_PREFIX.length()); supportedRSuperVersions.add(versionSubstring); } } return supportedRSuperVersions.toArray( new String[supportedRSuperVersions.size()]); } } private File[] getJriNativeDirs() { try { ConfigurationUtilities configUtilities = new ConfigurationUtilities(); File baseDir = configUtilities.getBaseDirectory(); File jriNativesBaseDir = new File( baseDir, JRI_NATIVES_BASE_DIR_NAME); if(!jriNativesBaseDir.exists()) { LOG.fine( "restoring JRI natives to: " + jriNativesBaseDir.getAbsolutePath()); this.restoreJriNatives(configUtilities); } // confirm that the directory now exists if(!jriNativesBaseDir.isDirectory()) { LOG.severe( "expected " + jriNativesBaseDir.getAbsolutePath() + " to be a directory. " + jriNativesBaseDir.getAbsolutePath() + " either does not exist or is a non-directory file."); return null; } else { File platformSpecificJRINativesDir = new File( jriNativesBaseDir, TypeSafeSystemProperties.getOsFamily().getUniqueFamilyNamePrefix()); if(!platformSpecificJRINativesDir.isDirectory()) { LOG.severe( "directory doesn't exist " + platformSpecificJRINativesDir.getAbsolutePath()); return null; } else { return platformSpecificJRINativesDir.listFiles(); } } } catch(IOException ex) { LOG.log(Level.SEVERE, "caught exception initializing configuration utilities", ex); return null; } } /** * Get the JRI native directory that matches the given installation. This * file can be used as a part of the java.library.path * @param installation * the R installation that we're looking up a JRI directory for * @return * the matching JRI directory or null if we can't find any * JRI natives to match the given R installation (eg. if * none of the versions are compatible) */ protected File getMatchingJriNativeDir( RInstallation installation) { VersionStringComparator versionComp = VersionStringComparator.getInstance(); for(File currNativeDir: this.getJriNativeDirs()) { if(currNativeDir.getName().startsWith(JRI_R_DEPENDENCY_VERSION_PREFIX)) { String versionSubstring = currNativeDir.getName().substring( JRI_R_DEPENDENCY_VERSION_PREFIX.length()); if(versionComp.isSuperversionOf( versionSubstring, installation.getRVersion())) { // we found the directory! return currNativeDir; } } } // could not match the version in the given installation return null; } /** * @param configUtilities */ private void restoreJriNatives(ConfigurationUtilities configUtilities) { // now expand the jri natives ZipInputStream jriNativesZipIn = new ZipInputStream( this.getClass().getResourceAsStream( "/JRI-" + TypeSafeSystemProperties.getOsFamily().getUniqueFamilyNamePrefix() + "-natives.zip")); try { configUtilities.getBaseDirectory().mkdirs(); FileUtilities.unzipToDirectory( jriNativesZipIn, configUtilities.getBaseDirectory()); jriNativesZipIn.close(); } catch(IOException ex) { LOG.log(Level.SEVERE, "failed to restore JRI natives", ex); } } }