/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.tools; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.LinkedList; import java.util.List; import java.util.Properties; import com.rapidminer.RapidMiner; import com.rapidminer.Version; import com.rapidminer.gui.look.fc.Bookmark; import com.rapidminer.gui.look.fc.BookmarkIO; import com.rapidminer.gui.tools.VersionNumber; /** * This class loads the yalrc property files and provides methods to access * them. It also provides methods to create files relative to the RapidMiner home * directory. As the {@link #getProperty(String)} method throws an exception if * the parameter is not set, the <code>System.getProperty(String)</code> * methods should be used if this is not desired. * * @author Simon Fischer, Ingo Mierswa * @version $Id: ParameterService.java,v 2.19 2006/03/21 15:35:53 ingomierswa * Exp $ */ public class ParameterService { /** * Tries to find the rapidminer.home directory if the property is not set and sets * it. */ public static void ensureRapidMinerHomeSet() { String home = System.getProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME); if (home != null) { LogService.getGlobal().log(RapidMiner.PROPERTY_RAPIDMINER_HOME + " is '" + home + "'.", LogService.INIT); } else { LogService.getGlobal().log("Property " + RapidMiner.PROPERTY_RAPIDMINER_HOME+ " is not set. Guessing.", LogService.INIT); String classpath = System.getProperty("java.class.path"); String pathComponents[] = classpath.split(File.pathSeparator); boolean found = false; for (int i = 0; i < pathComponents.length; i++) { String path = pathComponents[i].trim(); if (path.endsWith("rapidminer.jar")) { File jar = new File(path).getAbsoluteFile(); String message = "Trying parent directory of '" + jar + "'..."; File dir = jar.getParentFile(); if (dir != null) { dir = dir.getParentFile(); if (dir != null) { message += "gotcha!"; System.setProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME, dir.getAbsolutePath()); } else { message += "failed"; } } else { message += "failed"; } LogService.getGlobal().log(message, LogService.INIT); } } if (!found) { String message = "Trying base directory of classes (build) '"; URL url = ParameterService.class.getClassLoader().getResource("."); if (url != null) { try { File dir = new File(new URI(url.toString())); if (dir.exists()) { dir = dir.getParentFile(); message += dir + "'..."; if (dir != null) { message += "gotcha!"; try { System.setProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME, dir.getCanonicalPath()); } catch (IOException e) { System.setProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME, dir.getAbsolutePath()); } } else { message += "failed"; } } else { message += "failed"; } } catch (URISyntaxException e) { message += "failed"; } } else { message += "failed"; } LogService.getGlobal().log(message, LogService.INIT); } } getProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME); // throws exception if necessary } /** Invokes {@link #init(InputStream, boolean)} with a null stream meaning that * the core operators.xml is loaded and with addWekaOperators = true. * Registers the operators from the stream and reads the rc file. */ public static void init() { init(null, true); } /** Registers the operators from the stream and reads the rc file. If the stream * is null this method tries to read the core operators.xml. */ public static void init(InputStream operatorsXMLStream, boolean addWekaOperators) { init(operatorsXMLStream, null, addWekaOperators); } /** Registers the operators from the stream and reads the rc file. If the stream * is null this method tries to read the core operators.xml. */ public static void init(InputStream operatorsXMLStream, InputStream additionalXMLStream, boolean addWekaOperators) { loadRCFile(); // core operators InputStream operatorDescriptionStream = operatorsXMLStream; if (operatorDescriptionStream == null) { URL operatorURL = OperatorService.getMainOperators(); try { if (operatorURL != null) { operatorDescriptionStream = operatorURL.openStream(); } else { LogService.getGlobal().log("Cannot find 'operators.xml'.", LogService.ERROR); } } catch (IOException e) { LogService.getGlobal().log("Cannot read 'operators.xml'.", LogService.ERROR); } } if (operatorDescriptionStream != null) OperatorService.registerOperators("operators.xml", operatorDescriptionStream, null, addWekaOperators); try { // we opened the stream ourself --> close it if ((operatorDescriptionStream != null) && (operatorsXMLStream == null)) operatorDescriptionStream.close(); } catch (IOException e1) { // do nothing } // additional operators from init method if (additionalXMLStream != null) { OperatorService.registerOperators("Additional Operators from Init", additionalXMLStream, null, addWekaOperators); } // additional operators from starting parameter String additionalOperators = System.getProperty(RapidMiner.PROPERTY_RAPIDMINER_OPERATORS_ADDITIONAL); if ((additionalOperators != null) && (additionalOperators.length() > 0)) { String[] additionalOperatorFileNames = additionalOperators.split(File.pathSeparator); for (int i = 0; i < additionalOperatorFileNames.length; i++) { File additionalOperatorFile = new File(additionalOperatorFileNames[i]); if (additionalOperatorFile.exists()) { try { OperatorService.registerOperators(additionalOperatorFile.getPath(), new FileInputStream(additionalOperatorFile), null, addWekaOperators); } catch (IOException e) { LogService.getGlobal().log("Cannot read '" + additionalOperatorFile + "'.", LogService.ERROR); } } else { LogService.getGlobal().log("Cannot find operator description file '" + additionalOperatorFileNames[i] + "'", LogService.ERROR); } } } } /** Returns the user workspace (if one was set). Might return null if no workspace * definition can be found. This method also creates the workspace directory if * the file does not exist. */ public static File getUserWorkspace() { File workspaceLocationFile = getUserConfigFile("workspace"); if (!workspaceLocationFile.exists()) { return null; } else { BufferedReader in = null; String workspacePath = null; try { in = new BufferedReader(new FileReader(workspaceLocationFile)); workspacePath = in.readLine(); } catch (IOException e) { // does nothing } finally { if (in != null) { try { in.close(); } catch (IOException e) { // cannot happen } } } if (workspacePath != null) { File workspace = new File(workspacePath); if (!workspace.exists()) { boolean creationResult = workspace.mkdir(); if (!creationResult) { LogService.getGlobal().logWarning("Cannot create workspace directory: " + workspace); return null; } } return workspace; } else { return null; } } } /** Sets the current user workspace to this file. If the directory does not exist * it will be created. The absolute path is also written into the corresponding * user config file. Additionally, the favorites for the file chooser * will be extended by the workspace and sample links if appropriate. */ public static final void setUserWorkspace(File workspace) { if (!workspace.exists()) { boolean result = workspace.mkdir(); if (!result) LogService.getGlobal().logWarning("Unable to create workspace directory: " + workspace); } // copy sample files File newSampleDir = new File(workspace, "sample"); if (newSampleDir.exists()) { Tools.delete(newSampleDir); boolean creationResult = newSampleDir.mkdir(); if (!creationResult) { LogService.getGlobal().logWarning("Cannot create user sample directory: " + newSampleDir); } } File globalSampleDir = ParameterService.getSampleDir(); try { Tools.copy(globalSampleDir, newSampleDir); } catch (IOException e1) { LogService.getGlobal().logWarning("Cannot copy sample directory to workspace: " + e1.getMessage()); } // add basic bookmarks for new workspace List<Bookmark> bookmarks = null; File bookmarksFile = new File(ParameterService.getUserRapidMinerDir(), ".bookmarks"); if (bookmarksFile.exists()) { bookmarks = BookmarkIO.readBookmarks(bookmarksFile); boolean changedWorkspace = false; boolean changedSamples = false; boolean changedSampleData = false; if (bookmarks != null) { for (Bookmark bookmark : bookmarks) { // change existing entries if (bookmark.getName().equals("Workspace")) { bookmark.setPath(workspace.getAbsolutePath()); changedWorkspace = true; } else if (bookmark.getName().equals("Samples")) { if (newSampleDir.exists()) { bookmark.setPath(newSampleDir.getAbsolutePath()); } changedSamples = true; } else if (bookmark.getName().equals("Sample Data")) { File newSampleDataDir = new File(newSampleDir, "data"); if (newSampleDataDir.exists()) { bookmark.setPath(newSampleDataDir.getAbsolutePath()); } changedSampleData = true; } } if (!changedWorkspace) { Bookmark workspaceBookmark = new Bookmark("Workspace", workspace.getAbsolutePath()); bookmarks.add(workspaceBookmark); } if (!changedSamples) { if (newSampleDir.exists()) { Bookmark sampleBookmark = new Bookmark("Samples", newSampleDir.getAbsolutePath()); bookmarks.add(sampleBookmark); } } if (!changedSampleData) { File newSampleDataDir = new File(newSampleDir, "data"); if (newSampleDataDir.exists()) { Bookmark sampleDataBookmark = new Bookmark("Sample Data", newSampleDataDir.getAbsolutePath()); bookmarks.add(sampleDataBookmark); } } } } if (bookmarks == null) { // favorites file not existing --> create new one containing workspace links bookmarks = new LinkedList<Bookmark>(); Bookmark workspaceBookmark = new Bookmark("Workspace", workspace.getAbsolutePath()); bookmarks.add(workspaceBookmark); if (newSampleDir.exists()) { Bookmark sampleBookmark = new Bookmark("Samples", newSampleDir.getAbsolutePath()); bookmarks.add(sampleBookmark); } File newSampleDataDir = new File(newSampleDir, "data"); if (newSampleDataDir.exists()) { Bookmark sampleDataBookmark = new Bookmark("Sample Data", newSampleDataDir.getAbsolutePath()); bookmarks.add(sampleDataBookmark); } } // write bookmarks file BookmarkIO.writeBookmarks(bookmarks, bookmarksFile); // write workspace location into user config file File workspaceLocationFile = getUserConfigFile("workspace"); PrintWriter workspaceOut = null; try { workspaceOut = new PrintWriter(new FileWriter(workspaceLocationFile)); workspaceOut.println(workspace.getAbsolutePath()); } catch (IOException e) { LogService.getGlobal().logWarning("Cannot write workspace location: " + e.getMessage()); } finally { if (workspaceOut != null) workspaceOut.close(); } } public static void copyMainUserConfigFile(VersionNumber oldVersion, VersionNumber newVersion) { Properties oldProperties = readPropertyFile(getVersionedUserConfigFile(oldVersion, "rapidminerrc" + "." + System.getProperty("os.name"))); writeProperties(oldProperties, getMainUserConfigFile()); } private static Properties readPropertyFile(File file) { Properties properties = new Properties(); if (file.exists()) { InputStream in = null; try { in = new FileInputStream(file); properties.load(in); } catch (IOException e) { LogService.getGlobal().logWarning("Cannot read main user properties: " + e.getMessage()); } finally { if (in != null) { try { in.close(); } catch (IOException e) { LogService.getGlobal().logWarning("Cannot close connection to user properties: " + e.getMessage()); } } } } return properties; } private static void writeProperties(Properties properties, File file) { PrintWriter out = null; try { out = new PrintWriter(new FileWriter(getMainUserConfigFile())); for (Object keyName : properties.keySet()) { String typeKey = (String)keyName; String typeValue = properties.getProperty(typeKey); if (typeValue != null) { System.setProperty(typeKey, typeValue); out.println(typeKey + " = " + typeValue); } } } catch (IOException e) { LogService.getGlobal().logWarning("Cannot write user properties: " + e.getMessage()); } finally { if (out != null) { out.close(); } } } public static void writePropertyIntoMainUserConfigFile(String key, String value) { // read old configuration Properties userProperties = readPropertyFile(getMainUserConfigFile()); // set new property userProperties.setProperty(key, value); System.setProperty(key, value); // write complete configuration back into the file writeProperties(userProperties, getMainUserConfigFile()); } /** Returns the main user configuration file containing the version number and the OS. */ public static File getMainUserConfigFile() { return ParameterService.getUserConfigFile("rapidminerrc" + "." + System.getProperty("os.name")); } /** Returns the configuration file in the user dir .rapidminer and automatically adds * the current version number if it is a rc file. */ public static File getUserConfigFile(String name) { return getVersionedUserConfigFile(new VersionNumber(Version.getLongVersion()), name); } public static File getVersionedUserConfigFile(VersionNumber versionNumber, String name) { String configName = name; if (configName.startsWith("rapidminerrc")) { if (versionNumber != null) configName = versionNumber.toString().replaceAll("\\.", "_") + "_" + configName; } return new File(getUserRapidMinerDir(), configName); } public static File getUserRapidMinerDir() { File homeDir = new File(System.getProperty("user.home")); File userHomeDir = new File(homeDir, ".rapidminer"); if (!userHomeDir.exists()) { LogService.getGlobal().log("Creating directory '" + userHomeDir + "'", LogService.INIT); boolean result = userHomeDir.mkdir(); if (!result) LogService.getGlobal().logWarning("Unable to create user home rapidminer directory " + userHomeDir); } return userHomeDir; } private static void loadRCFile() { File globalRC = getConfigFile("rapidminerrc"); loadAllRCFiles(globalRC.getPath()); loadAllRCFiles(getUserConfigFile("rapidminerrc").getAbsolutePath()); loadAllRCFiles(new File(new File(System.getProperty("user.dir")), "rapidminerrc").getAbsolutePath()); String localRC = System.getProperty(RapidMiner.PROPERTY_RAPIDMINER_RC_FILE); if (localRC != null) loadRCFile(localRC); else LogService.getGlobal().log("Trying rapidminer.rcfile. Property not specified...skipped", LogService.INIT); } private static void loadAllRCFiles(String rcFileName) { loadRCFile(rcFileName); loadRCFile(rcFileName + "." + System.getProperty("os.name")); } private static void loadRCFile(String rcFileName) { if (rcFileName == null) return; File rcFile = new File(rcFileName); if (!rcFile.exists()) { LogService.getGlobal().log("Trying rcfile '" + rcFile + "'...skipped", LogService.INIT); return; } InputStream in = null; try { in = new FileInputStream(rcFile); System.getProperties().load(in); LogService.getGlobal().log("Read rcfile '" + rcFile + "'.", LogService.INIT); } catch (IOException e) { LogService.getGlobal().log("Cannot load rcfile: " + rcFile, LogService.ERROR); } finally { if (in != null) { try { in.close(); } catch (IOException e) { LogService.getGlobal().logError("Cannot close stream to rcfile: " + e.getMessage()); } } } } // -------------------- parameters -------------------- /** * Returns a system property and throws a runtime exception if the property * is not set. */ private static String getProperty(String key) { String property = System.getProperty(key); if (property == null) { throw new RuntimeException("Property '" + key + "' not set!"); } return property; } public static File getRapidMinerHome() { return new File(getProperty(RapidMiner.PROPERTY_RAPIDMINER_HOME)); } public static File getConfigFile(String name) { File home = getRapidMinerHome(); return new File(home, "etc" + File.separator + name); } public static File getLibraryFile(String name) { File home = getRapidMinerHome(); return new File(home, "lib" + File.separator + name); } public static File getSampleFile(String filename) { File home = getRapidMinerHome(); return new File(home, "sample" + File.separator + filename); } public static File getUserSampleFile(String filename) { File workspace = getUserWorkspace(); return new File(workspace, "sample" + File.separator + filename); } public static File getSourceFile(String filename) { File home = getRapidMinerHome(); return new File(home, "src" + File.separator + filename); } public static File getPluginDir() { return getLibraryFile("plugins"); } public static File getSampleDir() { File home = getRapidMinerHome(); return new File(home, "sample"); } // -------------------- tools -------------------- /** * Returns true if value is "true", "yes", "y" or "on". Returns false if * value is "false", "no", "n" or "off". Otherwise returns <tt>deflt</tt>. */ public static boolean booleanValue(String value, boolean deflt) { if (value == null) return deflt; if (value.equals("true")) return true; else if (value.equals("yes")) return true; else if (value.equals("y")) return true; else if (value.equals("on")) return true; else if (value.equals("false")) return false; else if (value.equals("no")) return false; else if (value.equals("n")) return false; else if (value.equals("off")) return false; return deflt; } }