/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.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.gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.Policy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import com.rapidminer.FileProcessLocation;
import com.rapidminer.NoOpUserError;
import com.rapidminer.Process;
import com.rapidminer.ProcessLocation;
import com.rapidminer.RapidMiner;
import com.rapidminer.RepositoryProcessLocation;
import com.rapidminer.core.io.data.source.DataSourceFactoryRegistry;
import com.rapidminer.gui.actions.OpenAction;
import com.rapidminer.gui.autosave.AutoSave;
import com.rapidminer.gui.dialog.EULADialog;
import com.rapidminer.gui.docking.RapidDockableContainerFactory;
import com.rapidminer.gui.internal.GUIStartupListener;
import com.rapidminer.gui.license.LicenseTools;
import com.rapidminer.gui.look.RapidLookAndFeel;
import com.rapidminer.gui.look.fc.BookmarkIO;
import com.rapidminer.gui.look.ui.RapidDockingUISettings;
import com.rapidminer.gui.plotter.PlotterPanel;
import com.rapidminer.gui.safemode.SafeMode;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.gui.tools.dialogs.DecisionRememberingConfirmDialog;
import com.rapidminer.gui.tools.logging.LogHandlerModel;
import com.rapidminer.gui.tools.logging.LogModel;
import com.rapidminer.gui.tools.logging.LogModelRegistry;
import com.rapidminer.gui.tools.logging.LogViewer;
import com.rapidminer.gui.viewer.MetaDataViewerTableModel;
import com.rapidminer.license.LicenseManagerRegistry;
import com.rapidminer.parameter.ParameterTypeBoolean;
import com.rapidminer.parameter.ParameterTypeCategory;
import com.rapidminer.parameter.ParameterTypeColor;
import com.rapidminer.parameter.ParameterTypeInt;
import com.rapidminer.repository.MalformedRepositoryLocationException;
import com.rapidminer.repository.RepositoryLocation;
import com.rapidminer.repository.RepositoryManager;
import com.rapidminer.security.PluginSandboxPolicy;
import com.rapidminer.security.PluginSecurityManager;
import com.rapidminer.studio.io.data.internal.file.LocalFileDataSourceFactory;
import com.rapidminer.studio.io.data.internal.file.binary.BinaryDataSourceFactory;
import com.rapidminer.studio.io.data.internal.file.csv.CSVDataSourceFactory;
import com.rapidminer.studio.io.data.internal.file.excel.ExcelDataSourceFactory;
import com.rapidminer.tools.FileSystemService;
import com.rapidminer.tools.I18N;
import com.rapidminer.tools.LaunchListener;
import com.rapidminer.tools.LaunchListener.RemoteControlHandler;
import com.rapidminer.tools.LogService;
import com.rapidminer.tools.ParameterService;
import com.rapidminer.tools.SystemInfoUtilities;
import com.rapidminer.tools.SystemInfoUtilities.OperatingSystem;
import com.rapidminer.tools.Tools;
import com.rapidminer.tools.plugin.Plugin;
import com.rapidminer.tools.update.internal.UpdateManagerRegistry;
import com.rapidminer.tools.usagestats.CallToActionScheduler;
import com.rapidminer.tools.usagestats.UsageStatistics;
import com.rapidminer.tools.usagestats.UsageStatsTransmissionDialog;
import com.vlsolutions.swing.docking.DockableContainerFactory;
import com.vlsolutions.swing.docking.ui.DockingUISettings;
/**
* The main class if RapidMiner is started in GUI mode. This class keeps a reference to the
* {@link MainFrame} and some other GUI relevant information and methods.
*
* @author Ingo Mierswa, Simon Fischer
*/
public class RapidMinerGUI extends RapidMiner {
public static final String PROPERTY_GEOMETRY_X = "rapidminer.gui.geometry.x";
public static final String PROPERTY_GEOMETRY_Y = "rapidminer.gui.geometry.y";
public static final String PROPERTY_GEOMETRY_EXTENDED_STATE = "rapidminer.gui.geometry.extendedstate";
public static final String PROPERTY_GEOMETRY_WIDTH = "rapidminer.gui.geometry.width";
public static final String PROPERTY_GEOMETRY_HEIGHT = "rapidminer.gui.geometry.height";
public static final String PROPERTY_GEOMETRY_DIVIDER_MAIN = "rapidminer.gui.geometry.divider.main";
public static final String PROPERTY_GEOMETRY_DIVIDER_EDITOR = "rapidminer.gui.geometry.divider.editor";;
public static final String PROPERTY_GEOMETRY_DIVIDER_LOGGING = "rapidminer.gui.geometry.divider.logging";
public static final String PROPERTY_GEOMETRY_DIVIDER_GROUPSELECTION = "rapidminer.gui.geometry.divider.groupselection";
public static final String PROPERTY_EXPERT_MODE = "rapidminer.gui.expertmode";
public static final String PROPERTY_SHOW_PARAMETER_HELP = "rapidminer.gui.show_parameter_help";
// GUI Properties
public static final String PROPERTY_RAPIDMINER_GUI_MAX_STATISTICS_ROWS = "rapidminer.gui.max_statistics_rows";
public static final String PROPERTY_RAPIDMINER_GUI_MAX_SORTABLE_ROWS = "rapidminer.gui.max_sortable_rows";
public static final String PROPERTY_RAPIDMINER_GUI_MAX_DISPLAYED_VALUES = "rapidminer.gui.max_displayed_values";
public static final String PROPERTY_RAPIDMINER_GUI_SNAP_TO_GRID = "rapidminer.gui.snap_to_grid";
/**
* The property name for "Maximum number of states in the undo list."
*
* @since 7.5
*/
public static final String PROPERTY_RAPIDMINER_GUI_UNDOLIST_SIZE = "rapidminer.gui.undolist.size";
public static final String PROPERTY_AUTOWIRE_INPUT = "rapidminer.gui.autowire_input";
public static final String PROPERTY_AUTOWIRE_OUTPUT = "rapidminer.gui.autowire_output";
public static final String PROPERTY_RESOLVE_RELATIVE_REPOSITORY_LOCATIONS = "rapidminer.gui.resolve_relative_repository_locations";
public static final String PROPERTY_CLOSE_RESULTS_BEFORE_RUN = "rapidminer.gui.close_results_before_run";
public static final String PROPERTY_ADD_BREAKPOINT_RESULTS_TO_HISTORY = "rapidminer.gui.add_breakpoint_results_to_history";
public static final String PROPERTY_CONFIRM_EXIT = "rapidminer.gui.confirm_exit";
public static final String PROPERTY_RUN_REMOTE_NOW = "rapidminer.gui.run_process_on_rapidanalytics_now";
public static final String PROPERTY_OPEN_IN_FILEBROWSER = "rapidminer.gui.entry_open_in_filebrowser";
public static final String PROPERTY_CLOSE_ALL_RESULTS_NOW = "rapidminer.gui.close_all_results_without_confirmation";
public static final String PROPERTY_FETCH_DATA_BASE_TABLES_NAMES = "rapidminer.gui.fetch_data_base_table_names";
public static final String PROPERTY_DISCONNECT_ON_DISABLE = "rapidminer.gui.disconnect_on_disable";
/** determines if a warning notification bubble is shown when no result ports are connected */
public static final String PROPERTY_SHOW_NO_RESULT_WARNING = "rapidminer.gui.no_result_port_connected";
public static final String PROPERTY_TRANSFER_USAGESTATS = "rapidminer.gui.transfer_usagestats";
public static final String[] PROPERTY_TRANSFER_USAGESTATS_ANSWERS = { "ask", "always", "never" };
public static final String PROPERTY_DRAG_TARGET_HIGHLIGHTING = "rapidminer.gui.drag_target_highlighting";
public static final String[] PROPERTY_DRAG_TARGET_HIGHLIGHTING_VALUES = { "full", "border", "none" };
public static final int DRAG_TARGET_HIGHLIGHTING_FULL = 0;
// GUI flag key for caching
public static final String IS_GUI_PROCESS = "com.rapidminer.gui.isGUIProcess";
// Update Properties
public static final String PROPERTY_RAPIDMINER_GUI_PURCHASED_NOT_INSTALLED_CHECK = "rapidminer.update.purchased.not_installed.check";
public static final String PROPERTY_RAPIDMINER_GUI_UPDATE_CHECK = "rapidminer.update.check";
static {
// GUI Parameters
RapidMiner.registerParameter(
new ParameterTypeInt(PROPERTY_RAPIDMINER_GUI_MAX_STATISTICS_ROWS, "", 1, Integer.MAX_VALUE, 100000));
RapidMiner.registerParameter(
new ParameterTypeInt(PROPERTY_RAPIDMINER_GUI_MAX_SORTABLE_ROWS, "", 1, Integer.MAX_VALUE, 100000));
RapidMiner.registerParameter(new ParameterTypeInt(PROPERTY_RAPIDMINER_GUI_MAX_DISPLAYED_VALUES, "", 1,
Integer.MAX_VALUE, MetaDataViewerTableModel.DEFAULT_MAX_DISPLAYED_VALUES));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_RAPIDMINER_GUI_SNAP_TO_GRID, "", true));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_AUTOWIRE_INPUT, "", false));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_AUTOWIRE_OUTPUT, "", false));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_RESOLVE_RELATIVE_REPOSITORY_LOCATIONS, "", true));
RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_CLOSE_RESULTS_BEFORE_RUN, "",
DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.TRUE));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_ADD_BREAKPOINT_RESULTS_TO_HISTORY, "", false));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_CONFIRM_EXIT, "", false));
RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_OPEN_IN_FILEBROWSER, "",
DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.ASK));
RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_CLOSE_ALL_RESULTS_NOW, "",
DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.ASK));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_FETCH_DATA_BASE_TABLES_NAMES, "", true));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_DISCONNECT_ON_DISABLE, "", true));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_SHOW_NO_RESULT_WARNING, "", true));
RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_TRANSFER_USAGESTATS, "",
RapidMinerGUI.PROPERTY_TRANSFER_USAGESTATS_ANSWERS, UsageStatsTransmissionDialog.ALWAYS));
RapidMiner.registerParameter(new ParameterTypeCategory(PROPERTY_DRAG_TARGET_HIGHLIGHTING, "",
PROPERTY_DRAG_TARGET_HIGHLIGHTING_VALUES, DRAG_TARGET_HIGHLIGHTING_FULL));
// GUI Parameters MainFrame
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_MATRIXPLOT_SIZE, "", 1,
Integer.MAX_VALUE, 200));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_ROWS_MAXIMUM, "", 1,
Integer.MAX_VALUE, PlotterPanel.DEFAULT_MAX_NUMBER_OF_DATA_POINTS));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_DEFAULT_MAXIMUM, "", -1,
Integer.MAX_VALUE, 100000));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_LEGEND_CLASSLIMIT, "",
-1, Integer.MAX_VALUE, 10));
RapidMiner.registerParameter(
new ParameterTypeColor(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_LEGEND_MINCOLOR, "", java.awt.Color.blue));
RapidMiner.registerParameter(
new ParameterTypeColor(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_LEGEND_MAXCOLOR, "", java.awt.Color.red));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_COLORS_CLASSLIMIT, "",
-1, Integer.MAX_VALUE, 10));
RapidMiner.registerParameter(
new ParameterTypeInt(PROPERTY_RAPIDMINER_GUI_UNDOLIST_SIZE, "", 1, Integer.MAX_VALUE, 100));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_ATTRIBUTEEDITOR_ROWLIMIT, "", -1,
Integer.MAX_VALUE, 50));
RapidMiner.registerParameter(new ParameterTypeBoolean(MainFrame.PROPERTY_RAPIDMINER_GUI_BEEP_SUCCESS, "", false));
RapidMiner.registerParameter(new ParameterTypeBoolean(MainFrame.PROPERTY_RAPIDMINER_GUI_BEEP_ERROR, "", false));
RapidMiner.registerParameter(new ParameterTypeBoolean(MainFrame.PROPERTY_RAPIDMINER_GUI_BEEP_BREAKPOINT, "", false));
RapidMiner.registerParameter(new ParameterTypeInt(MainFrame.PROPERTY_RAPIDMINER_GUI_MESSAGEVIEWER_ROWLIMIT, "", -1,
Integer.MAX_VALUE, LogViewer.DEFAULT_LOG_ENTRY_NUMBER));
RapidMiner.registerParameter(new ParameterTypeCategory(MainFrame.PROPERTY_RAPIDMINER_GUI_SAVE_BEFORE_RUN, "",
DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.FALSE));
RapidMiner.registerParameter(
new ParameterTypeBoolean(MainFrame.PROPERTY_RAPIDMINER_GUI_SAVE_ON_PROCESS_CREATION, "", false));
RapidMiner.registerParameter(new ParameterTypeCategory(MainFrame.PROPERTY_RAPIDMINER_GUI_AUTO_SWITCH_TO_RESULTVIEW,
"", DecisionRememberingConfirmDialog.PROPERTY_VALUES, DecisionRememberingConfirmDialog.TRUE));
RapidMiner.registerParameter(new ParameterTypeCategory(MainFrame.PROPERTY_RAPIDMINER_GUI_LOG_LEVEL, "",
LogViewer.SELECTABLE_LEVEL_NAMES, LogViewer.DEFAULT_LEVEL_INDEX));
// Update Parameters
RapidMiner.registerParameter(
new ParameterTypeBoolean(PROPERTY_RAPIDMINER_GUI_PURCHASED_NOT_INSTALLED_CHECK, "", true));
RapidMiner.registerParameter(new ParameterTypeBoolean(PROPERTY_RAPIDMINER_GUI_UPDATE_CHECK, "", true));
// ---------- Load bundled fonts----------- -----------------
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("fonts/OpenSans-Light.ttf")));
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("fonts/OpenSans.ttf")));
ge.registerFont(
Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("fonts/OpenSans-Semibold.ttf")));
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("fonts/OpenSans-Bold.ttf")));
ge.registerFont(
Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("fonts/OpenSans-ExtraBold.ttf")));
} catch (Exception e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.MainFrame.font_load_failed", e.getMessage());
}
// ----------------------------------------------------------
}
private static final int NUMBER_OF_RECENT_FILES = 8;
private static MainFrame mainFrame;
private static LinkedList<ProcessLocation> recentFiles = new LinkedList<>();
private static SafeMode safeMode;
private static LogModel defaultLogModel;
private static List<GUIStartupListener> startupListener = new LinkedList<>();
private static boolean startupStarted = false;
private static AutoSave autosave = new AutoSave();
/**
* This thread listens for System shutdown and cleans up after shutdown. This included saving
* the recent file list and other GUI properties.
*/
private static class ShutdownHook extends Thread {
@Override
public void run() {
LogService.getRoot().log(Level.INFO, "com.rapidminer.gui.RapidMinerGUI.running_shutdown_sequence");
RapidMinerGUI.saveRecentFileList();
RapidMinerGUI.saveGUIProperties();
UsageStatistics.getInstance().save();
RepositoryManager.shutdown();
UsageStatsTransmissionDialog.transmitOnShutdown();
CallToActionScheduler.INSTANCE.shutdown();
}
}
// private static UpdateManager updateManager = new CommunityUpdateManager();
public synchronized void run(final String openLocation) throws Exception {
startupStarted = true;
// check if resources were copied
URL logoURL = Tools.getResource("rapidminer_logo.png");
if (logoURL == null) {
LogService.getRoot().log(Level.SEVERE, "com.rapidminer.gui.RapidMinerGUI.finding_resources_error");
RapidMiner.quit(RapidMiner.ExitMode.ERROR);
}
// Initialize Docking UI -- important must be done as early as possible!
DockingUISettings.setInstance(new RapidDockingUISettings());
DockableContainerFactory.setFactory(new RapidDockableContainerFactory());
// inform listeners that splash is about to be shown
for (GUIStartupListener sl : startupListener) {
try {
sl.splashWillBeShown();
} catch (RuntimeException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.startup_listener_error", e);
}
}
RapidMiner.showSplash();
RapidMiner.splashMessage("basic");
// initialize RapidMiner
// As side effect this also initialized the ConstraintManager
// with the default product and constraints
RapidMiner.init();
// store (possibly new) active license (necessary, since no
// ACTIVE_LICENSE_CHANGED event is fired on startup)
LicenseManagerRegistry.INSTANCE.get().getAllActiveLicenses().forEach((l) -> {
LicenseTools.storeActiveLicenseProperties(l);
});
// init logging GUI
defaultLogModel = new LogHandlerModel(LogService.getRoot(),
SwingTools.createIcon("16/" + I18N.getGUIMessage("gui.logging.default.icon")),
I18N.getGUIMessage("gui.logging.default.label"), false);
// set log level for our own log to the defined one
String levelName = ParameterService.getParameterValue(MainFrame.PROPERTY_RAPIDMINER_GUI_LOG_LEVEL);
Level logViewLevel = Level.INFO;
if (levelName != null) {
logViewLevel = Level.parse(levelName);
}
defaultLogModel.setLogLevel(logViewLevel);
LogService.getRoot().setLevel(logViewLevel);
LogModelRegistry.INSTANCE.register(defaultLogModel);
RapidMiner.splashMessage("workspace");
RapidMiner.splashMessage("plaf");
setupToolTipManager();
setupGUI();
// check whether current EULA has been accepted
if (!EULADialog.getEULAAccepted()) {
// show EULA dialog
RapidMiner.splashMessage("eula");
SwingTools.invokeAndWait(new Runnable() {
@Override
public void run() {
EULADialog dialog = new EULADialog();
dialog.setVisible(true);
}
});
}
RapidMiner.splashMessage("history");
loadRecentFileList();
RepositoryManager.getInstance(null).createRepositoryIfNoneIsDefined();
RapidMiner.splashMessage("create_frame");
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
setMainFrame(new MainFrame());
}
});
RapidMiner.splashMessage("gui_properties");
loadGUIProperties(mainFrame);
RapidMiner.splashMessage("plugin_gui");
Plugin.initPluginGuis(mainFrame);
// only load the perspective here after all plugins have registered their dockables
// otherwise you may end up breaking the perspective and VLDocking exists in invalid states
// and explodes into the smoking piece of crap it is
mainFrame.getPerspectiveController().showPerspective(PerspectiveModel.DESIGN);
autosave.init();
// inform listeners that the Mainframe was initialized
for (GUIStartupListener sl : startupListener) {
try {
sl.mainFrameInitialized(mainFrame);
} catch (RuntimeException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.startup_listener_error", e);
}
}
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
getMainFrame().finishInitialization();
}
});
RapidMiner.splashMessage("show_frame");
mainFrame.setVisible(true);
RapidMiner.splashMessage("checks");
Plugin.initFinalChecks();
RapidMiner.splashMessage("ready");
// set log model back to default log of Studio
// otherwise the last extension log is active
mainFrame.getLogViewer().getLogSelectionModel().setSelectedLogModel(RapidMinerGUI.getDefaultLogModel());
RapidMiner.hideSplash();
// inform listeners that the Splash screen was hidden
for (GUIStartupListener sl : startupListener) {
try {
sl.splashWasHidden();
} catch (RuntimeException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.startup_listener_error", e);
}
}
UsageStatsTransmissionDialog.init();
if (openLocation != null) {
if (!RepositoryLocation.isAbsolute(openLocation)) {
SwingTools.showVerySimpleErrorMessage("malformed_repository_location", openLocation);
} else {
OpenAction.open(openLocation, false);
}
}
// check for updates
Plugin.initPluginUpdateManager();
// inform listeners that GUI startup has finished
for (GUIStartupListener sl : startupListener) {
try {
sl.startupCompleted();
} catch (RuntimeException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.startup_listener_error", e);
}
}
// register data source factories
DataSourceFactoryRegistry.INSTANCE.register(new LocalFileDataSourceFactory());
// Register file data source factories: binary data source factory is registered first,
// since it is the first choice for unknown formats.
DataSourceFactoryRegistry.INSTANCE.register(new BinaryDataSourceFactory());
DataSourceFactoryRegistry.INSTANCE.register(new ExcelDataSourceFactory());
DataSourceFactoryRegistry.INSTANCE.register(new CSVDataSourceFactory());
// init CTA event storage and rule checking system only after all other systems have been
// started to avoid overlaying CTA mesages during startup
CallToActionScheduler.INSTANCE.init();
}
private void setupToolTipManager() {
// setup tool tip text manager
ToolTipManager manager = ToolTipManager.sharedInstance();
manager.setDismissDelay(25000); // original: 4000
manager.setInitialDelay(1500); // original: 750
manager.setReshowDelay(50); // original: 500
}
/**
* This default implementation only setup the tool tip durations. Subclasses might override this
* method.
*/
protected void setupGUI() throws NoOpUserError {
System.setProperty(BookmarkIO.PROPERTY_BOOKMARKS_DIR, FileSystemService.getUserRapidMinerDir().getAbsolutePath());
System.setProperty(BookmarkIO.PROPERTY_BOOKMARKS_FILE, ".bookmarks");
try {
if (SystemInfoUtilities.getOperatingSystem() == OperatingSystem.OSX) {
// to support OS Xs menu bar shown in the OS X menu bar,
// we have to load the default system look and feel
// to exchange the MenuBarUI from RapidLookAndFeel with the
// default OS X look and feel UI class.
// See here for more information:
// http://www.pushing-pixels.org/2008/07/13/swing-applications-and-mac-os-x-menu-bar.html
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Map<String, Object> macUIDefaults = new HashMap<>();
macUIDefaults.put("MenuBarUI", UIManager.get("MenuBarUI"));
UIManager.setLookAndFeel(new RapidLookAndFeel(macUIDefaults));
} else {
UIManager.setLookAndFeel(new RapidLookAndFeel());
}
} catch (Exception e) {
LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapidminer.gui.RapidMinerGUI.setting_up_modern_look_and_feel_error"), e);
}
}
public static void setMainFrame(final MainFrame mf) {
mainFrame = mf;
}
public static MainFrame getMainFrame() {
return mainFrame;
}
/**
* Checks whether the repository location belongs to the currently loaded process.
*
* @param location
* Repository location to check.
* @return true if the process belonging to this entry is currently presented on the GUI, false
* otherwise.
*/
public static boolean isMainFrameProcessLocation(RepositoryLocation location) {
if (getMainFrame() != null && getMainFrame().getProcess() != null) {
RepositoryLocation currentProcessLocation = getMainFrame().getProcess().getRepositoryLocation();
if (location.equals(currentProcessLocation)) {
return true;
}
}
return false;
}
/**
* Resets the location of the MainFrame process without reloading it. Use only if the currently
* displayed process is stored in repository, and got renamed or moved.
*
* @param repositoryLocation
* The new process location.
*/
public static void resetProcessLocation(RepositoryProcessLocation repositoryLocation) {
getMainFrame().getProcess().setProcessLocation(repositoryLocation);
getMainFrame().setTitle();
addToRecentFiles(repositoryLocation);
getMainFrame().updateRecentFileList();
}
public static void useProcessFile(final Process process) {
ProcessLocation location = process.getProcessLocation();
addToRecentFiles(location);
}
public static void addToRecentFiles(final ProcessLocation location) {
if (location != null) {
while (recentFiles.contains(location)) {
recentFiles.remove(location);
}
recentFiles.addFirst(location);
while (recentFiles.size() > NUMBER_OF_RECENT_FILES) {
recentFiles.removeLast();
}
saveRecentFileList();
}
}
public static List<ProcessLocation> getRecentFiles() {
return recentFiles;
}
/**
* Returns the default {@link LogModel} for RapidMiner Studio.
*
* @return
*/
public static LogModel getDefaultLogModel() {
return defaultLogModel;
}
/**
* @return the object that handles autosave information
*/
public static AutoSave getAutoSave() {
return autosave;
}
private static void loadRecentFileList() {
File file = FileSystemService.getUserConfigFile("history");
if (!file.exists()) {
return;
}
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
recentFiles.clear();
String line = null;
while ((line = in.readLine()) != null) {
if (line.startsWith("file ")) {
recentFiles.add(new FileProcessLocation(new File(line.substring(5))));
} else if (line.startsWith("repository ")) {
try {
recentFiles.add(new RepositoryProcessLocation(new RepositoryLocation(line.substring(11))));
} catch (MalformedRepositoryLocationException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unparseable_line", line);
}
} else {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unparseable_line", line);
}
}
} catch (IOException e) {
LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapidminer.gui.RapidMinerGUI.reading_history_file_error"), e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapidminer.gui.RapidMinerGUI.reading_history_file_error"), e);
}
}
}
}
private static void saveRecentFileList() {
File file = FileSystemService.getUserConfigFile("history");
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(file));
for (ProcessLocation loc : recentFiles) {
out.println(loc.toHistoryFileString());
}
} catch (IOException e) {
SwingTools.showSimpleErrorMessage("cannot_write_history_file", e);
} finally {
if (out != null) {
out.close();
}
}
}
private static void saveGUIProperties() {
Properties properties = new Properties();
MainFrame mainFrame = getMainFrame();
if (mainFrame != null) {
properties.setProperty(PROPERTY_GEOMETRY_X, "" + (int) mainFrame.getLocation().getX());
properties.setProperty(PROPERTY_GEOMETRY_Y, "" + (int) mainFrame.getLocation().getY());
properties.setProperty(PROPERTY_GEOMETRY_WIDTH, "" + mainFrame.getWidth());
properties.setProperty(PROPERTY_GEOMETRY_HEIGHT, "" + mainFrame.getHeight());
properties.setProperty(PROPERTY_GEOMETRY_EXTENDED_STATE, "" + mainFrame.getExtendedState());
properties.setProperty(PROPERTY_SHOW_PARAMETER_HELP, "" + mainFrame.getPropertyPanel().isShowParameterHelp());
properties.setProperty(PROPERTY_EXPERT_MODE, "" + mainFrame.getPropertyPanel().isExpertMode());
File file = FileSystemService.getUserConfigFile("gui.properties");
OutputStream out = null;
try {
out = new FileOutputStream(file);
properties.store(out, "RapidMiner Studio GUI properties");
} catch (IOException e) {
LogService.getRoot().log(Level.WARNING, I18N.getMessage(LogService.getRoot().getResourceBundle(),
"com.rapidminer.gui.RapidMinerGUI.writing_gui_properties_error", e.getMessage()), e);
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
}
}
mainFrame.getResultDisplay().clearAll();
// mainFrame.getApplicationPerspectiveController().saveAll();
mainFrame.getPerspectiveController().saveAll();
}
}
private static void loadGUIProperties(final MainFrame mainFrame) {
Properties properties = new Properties();
File file = FileSystemService.getUserConfigFile("gui.properties");
if (file.exists()) {
InputStream in = null;
try {
in = new FileInputStream(file);
properties.load(in);
} catch (IOException e) {
setDefaultGUIProperties();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
throw new Error(e); // should not occur
}
}
try {
mainFrame.setLocation(Integer.parseInt(properties.getProperty(PROPERTY_GEOMETRY_X)),
Integer.parseInt(properties.getProperty(PROPERTY_GEOMETRY_Y)));
mainFrame.setSize(new Dimension(Integer.parseInt(properties.getProperty(PROPERTY_GEOMETRY_WIDTH)),
Integer.parseInt(properties.getProperty(PROPERTY_GEOMETRY_HEIGHT))));
int extendedState;
if (properties.getProperty(PROPERTY_GEOMETRY_EXTENDED_STATE) == null) {
extendedState = Frame.NORMAL;
} else {
extendedState = Integer.parseInt(properties.getProperty(PROPERTY_GEOMETRY_EXTENDED_STATE));
}
mainFrame.setExtendedState(extendedState);
mainFrame.getPropertyPanel()
.setExpertMode(Boolean.valueOf(properties.getProperty(PROPERTY_EXPERT_MODE)).booleanValue());
// If the property is not set we want the parameter help to be shown
String showHelpProperty = properties.getProperty(PROPERTY_SHOW_PARAMETER_HELP);
if (showHelpProperty == null || showHelpProperty.isEmpty()) {
mainFrame.getPropertyPanel().setShowParameterHelp(true);
} else {
mainFrame.getPropertyPanel().setShowParameterHelp(Boolean.valueOf(showHelpProperty).booleanValue());
}
} catch (NumberFormatException e) {
setDefaultGUIProperties();
}
} else {
setDefaultGUIProperties();
}
}
/**
* This method sets some default GUI properties. This method can be invoked if the properties
* file was not found or produced any error messages (which might happen after version changes).
*/
private static void setDefaultGUIProperties() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
mainFrame.setLocation((int) (0.05d * screenSize.getWidth()), (int) (0.05d * screenSize.getHeight()));
mainFrame.setSize((int) (0.9d * screenSize.getWidth()), (int) (0.9d * screenSize.getHeight()));
mainFrame.getPropertyPanel().setExpertMode(false);
}
public static void main(String[] args) throws Exception {
Policy.setPolicy(new PluginSandboxPolicy());
System.setSecurityManager(new PluginSecurityManager());
RapidMiner.addShutdownHook(new ShutdownHook());
setExecutionMode(
System.getProperty(PROPERTY_HOME_REPOSITORY_URL) == null ? ExecutionMode.UI : ExecutionMode.WEBSTART);
boolean shouldLaunch = true;
if (!LaunchListener.defaultLaunchWithArguments(args, new RemoteControlHandler() {
@Override
public boolean handleArguments(final String[] args) {
LogService.getRoot().log(Level.INFO, "com.rapidminer.gui.RapidMinerGUI.received_message",
Arrays.toString(args));
mainFrame.requestFocus();
if (args.length >= 1) {
String arg = args[0];
if (arg.startsWith(RapidMiner.RAPIDMINER_URL_PREFIX)) {
handleRapidMinerURL(args[0]);
} else if (!args[0].trim().isEmpty()) {
OpenAction.open(args[0], false);
}
}
return true;
}
})) {
// always start if there are no args so user can start new Studio instances at will
shouldLaunch = args.length == 0;
}
if (shouldLaunch) {
safeMode = new SafeMode();
safeMode.launchStarts();
launch(args);
safeMode.launchComplete();
} else {
LogService.getRoot().log(Level.CONFIG, "com.rapidminer.gui.RapidMinerGUI.other_instance_up");
}
}
private static void launch(final String[] args) throws Exception {
String openLocation = null;
String rapidminerURL = null;
if (args.length > 0) {
if (args.length != 1) {
System.out.println("java " + RapidMinerGUI.class.getName() + " [processfile]");
return;
}
if (args[0].startsWith(RapidMiner.RAPIDMINER_URL_PREFIX)) {
rapidminerURL = args[0];
} else if (!args[0].trim().isEmpty()) {
openLocation = args[0];
}
}
RapidMiner.setInputHandler(new GUIInputHandler());
new RapidMinerGUI().run(openLocation);
if (rapidminerURL != null) {
handleRapidMinerURL(rapidminerURL);
}
}
/**
* @return the safeMode
*/
public static SafeMode getSafeMode() {
return safeMode;
}
public enum DragHighlightMode {
FULL, BORDER, NONE
}
public static DragHighlightMode getDragHighlighteMode() {
String dragParameter = ParameterService.getParameterValue(PROPERTY_DRAG_TARGET_HIGHLIGHTING);
if (dragParameter.equals(PROPERTY_DRAG_TARGET_HIGHLIGHTING_VALUES[0])) {
return DragHighlightMode.FULL;
} else if (dragParameter.equals(PROPERTY_DRAG_TARGET_HIGHLIGHTING_VALUES[1])) {
return DragHighlightMode.BORDER;
} else {
return DragHighlightMode.NONE;
}
}
public static Color getBodyHighlightColor() {
return new Color(255, 255, 242);
}
public static Color getBorderHighlightColor() {
return SwingTools.RAPIDMINER_ORANGE;
}
/**
* Called with rapidminer:// URLs passed as command line arguments. Currently the only supported
* pattern is rapidminer://extension/{extensionkey} to install an extension with the given name.
*
* This method just logs a warning method if it cannot handle the rapidminer:// URL for
* syntactical reasons.
*
* @throws IllegalArgumentException
* if this is not a rapidminer:// url
*/
private static void handleRapidMinerURL(String urlStr) {
URI url;
try {
url = new URI(urlStr);
} catch (URISyntaxException e) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.malformed_rapidminer_url",
new Object[] { urlStr, e.getMessage() });
return;
}
if (!"rapidminer".equals(url.getScheme())) {
// in this case we should not be called, so throw
throw new IllegalArgumentException("Can handle only " + RapidMiner.RAPIDMINER_URL_PREFIX + " URLs!");
}
String path = url.getPath();
if (path.startsWith("/")) {
path = path.substring(1);
}
String components[] = path.split("/");
if (components.length < 2) {
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unknown_rapidminer_url",
new Object[] { urlStr });
return;
}
switch (components[0]) {
case "extension":
String extensionKey = components[1];
// asynchronous
try {
UpdateManagerRegistry.INSTANCE.get().showUpdateDialog(false, extensionKey);
} catch (URISyntaxException | IOException e) {
LogService.getRoot().log(Level.WARNING,
"com.rapidminer.gui.RapidMinerGUI.error_connecting_to_updateserver", e);
}
break;
default:
LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.RapidMinerGUI.unknown_rapidminer_url",
new Object[] { urlStr });
return;
}
}
/**
* Register a {@link GUIStartupListener}.
*
* @param listener
* the listener to register
* @throws IllegalStateException
* if the startup process has already been started
*/
public static synchronized void registerStartupListener(GUIStartupListener listener) {
if (startupStarted) {
throw new IllegalStateException("Cannot register a Startup listener after startup has been started");
}
startupListener.add(listener);
}
}