/** * 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.io.remote; import java.io.File; import java.io.IOException; import javax.swing.Icon; import javax.swing.JFileChooser; import javax.swing.UIManager; import javax.swing.filechooser.FileSystemView; import com.rapidminer.gui.properties.celleditors.value.RemoteFileValueCellEditor; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.operator.UserError; /** * This file system view is used for files that are not on the hard drive. It works with * {@link RemoteFile}s and overwrites the methods of {@link FileSystemView} that access the hard * drive. It can be used with a {@link JFileChooser} to select {@link RemoteFile}s as if they were * normal files. * * @author Gisa Schaefer * @since 6.1.0 */ public abstract class RemoteFileSystemView extends FileSystemView { /** flag which controls that an error while getting files is only shown once */ private boolean errorShown = false; /** * Determines if the given file is a root in the navigable tree(s). Examples: Windows 98 has one * root, the Desktop folder. DOS has one root per drive letter, <code>C:\</code>, * <code>D:\</code>, etc. Unix has one root, the <code>"/"</code> directory. * * The default implementation checks if the given file agrees with the one specified by * {@link #getRootDirectory()}. * */ @Override public boolean isRoot(File f) { return getRootDirectory().equals(f); } /** * Name of a file, directory, or folder as it would be displayed in a system file browser. * Example from Windows: the "M:\" directory displays as "CD-ROM (M:)" * * The default implementation returns the name of the file. * */ @Override public String getSystemDisplayName(File f) { return f == null ? null : f.getName(); } /** * Type description for a file, directory, or folder as it would be displayed in a system file * browser. Example from Windows: the "Desktop" folder is described as "Desktop". * * The default implementation returns either "Folder" for a directory or "ABC-File" for a file * with name "somefile.abc". */ @Override public String getSystemTypeDescription(File f) { if (f.isDirectory()) { return "Folder"; } int separatorPosition = f.getName().lastIndexOf("."); String fileending = ""; if (separatorPosition > -1) { fileending = f.getName().substring(separatorPosition + 1).toUpperCase() + "-"; } return fileending + "File"; } /** * Icon for a file, directory, or folder as it would be displayed in a system file browser. The * default implementation returns the standard icon of either a folder or a file. * */ @Override public Icon getSystemIcon(File f) { return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon"); } /** * Checks whether folder is the same as file.getParentFile(). */ @Override public boolean isParent(File folder, File file) { return folder.equals(file.getParentFile()); } /** * @return a File object constructed with * <code>{@link #createFileObject}(parent, fileName)</code>. */ @Override public File getChild(File parent, String fileName) { return createFileObject(parent, fileName); } /** * {@inheritDoc} The default implementation always returns <code>true</code>. */ @Override public boolean isFileSystem(File f) { return true; } /** * {@inheritDoc} The default implementation always returns <code>null</code>. */ @Override public File createNewFolder(File containingDir) throws IOException { return null; } /** * {@inheritDoc} The default implementation always returns <code>false</code>. */ @Override public boolean isHiddenFile(File f) { return false; } /** * {@inheritDoc} The default implementation checks if the given file agrees with the one * specified by {@link #getRootDirectory()}. */ @Override public boolean isFileSystemRoot(File dir) { return getRootDirectory().equals(dir); } @Override public boolean isComputerNode(File dir) { return false; } /** * {@inheritDoc} The default implementation returns the directory specified by * {@link #getRootDirectory()}. */ @Override public File[] getRoots() { return new File[] { getRootDirectory() }; } /** * Returns the directory specified by {@link #getRootDirectory()}. */ @Override public File getHomeDirectory() { return getRootDirectory(); } /** * {@inheritDoc} The default implementation returns the directory specified by * {@link #getRootDirectory()}. */ @Override public File getDefaultDirectory() { return getRootDirectory(); } @Override public File createFileObject(File dir, String filename) { if (dir == null) { return new RemoteFile(filename); } else { return new RemoteFile(dir, filename); } } @Override public File createFileObject(String path) { return new RemoteFile(path); } /** * {@inheritDoc} The default implementation does this via {@link #getRemoteFiles}. */ @Override public File[] getFiles(File dir, boolean useFileHiding) { try { RemoteFile directory = new RemoteFile(dir.getPath()); final RemoteFile[] remoteFiles = getRemoteFiles(directory); errorShown = false; return remoteFiles; } catch (UserError | IOException e) { // needed since getFiles is called twice in a row by the file chooser if (!errorShown) { SwingTools.showSimpleErrorMessage("cannot_open_remote_folder", e); errorShown = true; } return new File[0]; } } /** * @return the parent directory of <code>dir</code>, or <code>null</code> if <code>dir</code> is * <code>null</code> or the directory specified by {@link #getRootDirectory()}. */ @Override public File getParentDirectory(File dir) { if (dir == null || dir.equals(getRootDirectory()) || dir.getParentFile() == null || dir.getParentFile().getPath() == null) { return null; } return new RemoteFile(dir.getParentFile().getPath(), true); } /** * Returns the root directory of the remote file system. * * @return the remote file that is the root of the remote file system */ public abstract RemoteFile getRootDirectory(); /** * Gets the list of {@link RemoteFile}s inside the directory dir. * * @param dir * the directory * @return the files in the directory dir * @throws IOException * when fetching the content of the remote directory fails * @throws UserError * when fetching the content of the remote directory fails */ public abstract RemoteFile[] getRemoteFiles(RemoteFile dir) throws IOException, UserError; /** * Returns a flag for whether new folders can be created, <code>false</code> by default. This * flag is used by the {@link FileChooserUI} to decide if the control elements for creating a * new folder are shown. * */ public boolean isCreatingNewFolderEnabled() { return false; } /** * Returns a flag for whether files can be renamed, <code>false</code> by default. This flag is * used by the {@link FileChooserUI} to decide if the control elements for renaming files are * shown. * */ public boolean isRenamingEnabled() { return false; } /** * Checks whether the parent of the given file exists. * * Used to open the folder in the {@link JFileChooser} if it exists. The default implementation * returns false, which leads to opening the root folder in the {@link JFileChooser}. Is not * related to {@link RemoteFile#exists()} * * @param file * which should be checked * @return if the parent of the given file exists */ public boolean parentExists(String file) { return false; } /** * Returns a flag for whether files can be deleted, <code>false</code> by default. This flag is * used by the {@link FileChooserUI} to decide if the control elements for deleting files are * shown. * */ public boolean isDeletingEnabled() { return false; } /** * Method for checking the remote file system before the file chooser is opened. Used in * {@link RemoteFileValueCellEditor} before the file chooser is created. */ public abstract void checkFileSystemAvailability() throws UserError; /** * Returns the normalized path name of the file. The default implementation returns just * <code>file.getPath()</code>. This should be overwritten if the path of a file resulting from * the file chooser should not depend on the local file system. * */ public String getNormalizedPathName(File file) { return file.getPath(); } }