All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alee.utils.FileUtils Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library 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.
 *
 * WebLookAndFeel library 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 WebLookAndFeel library.  If not, see .
 */

package com.alee.utils;

import com.alee.api.annotations.NotNull;
import com.alee.api.annotations.Nullable;
import com.alee.api.resource.Resource;
import com.alee.managers.language.LM;
import com.alee.managers.proxy.ProxyManager;
import com.alee.utils.compare.Filter;
import com.alee.utils.file.FileComparator;
import com.alee.utils.file.FileDescription;
import com.alee.utils.file.FileDownloadListener;
import com.alee.utils.file.SystemFileListener;
import com.alee.utils.filefilter.AbstractFileFilter;
import com.alee.utils.filefilter.AllFilesFilter;
import com.alee.utils.filefilter.IOFileFilterAdapter;
import com.alee.utils.filefilter.SwingFileFilterAdapter;
import com.alee.utils.swing.WebTimer;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.text.JTextComponent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.security.CodeSource;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This class provides a set of utilities to work with files, file names and their extensions.
 * 

* Note that methods which request information about files from the system has their own caches to improve performance. * If you will need to clear that cache simply call the corresponding clearCache method, for example: * For method "isHidden" you will need to call "clearIsHiddenCache" and all cached values will be reset. * * @author Mikle Garin */ public final class FileUtils { /** * todo 1. File.exists doesn't work in JDK7? Probably should add workaround for that? */ /** * Image cache keys separator. */ private static final String CACHE_KEYS_SEPARATOR = "|"; /** * Number of bytes in 1 kilobyte. */ public static final long KB = 1024; /** * Number of bytes in 1 megabyte. */ public static final long MB = 1024 * KB; /** * Number of bytes in 1 gigabyte. */ public static final long GB = 1024 * MB; /** * Number of bytes in 1 terabyte. */ public static final long TB = 1024 * GB; /** * Number of bytes in 1 petabyte. */ public static final long PB = 1024 * TB; /** * Cached file system view. */ private static final FileSystemView fsv = FileSystemView.getFileSystemView (); /** * Display date format. */ private static final SimpleDateFormat sdf = new SimpleDateFormat ( "dd MMM yyyy HH:mm" ); /** * Default encoding used to read files. */ private static final String defaultEncoding = "UTF-8"; /** * Buffer size for MD5 calculations. */ private static final int MD5_BUFFER_LENGTH = 102400; /** * Buffer size for text reader. */ private static final int TEXT_BUFFER_SIZE = 65536; /** * All illegal file name characters. */ private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '\"', '`', '!', '?', '*', '\\', '<', '>', '|', ':', ';', '.', ',', '%', '$', '@', '#', '^', '{', '}', '[', ']', ']' }; /** * Cache for "isDrive" method result. */ private static final Map isDriveCache = new ConcurrentHashMap (); /** * Cache for "isComputer" method result. */ private static final Map isComputerCache = new ConcurrentHashMap (); /** * Cache for "isCdDrive" method result. */ private static final Map isCdDriveCache = new ConcurrentHashMap (); /** * Cache for "isFile" method result. */ private static final Map isFileCache = new ConcurrentHashMap (); /** * Cache for "isDirectory" method result. */ private static final Map isDirectoryCache = new ConcurrentHashMap (); /** * Cache for "isHidden" method result. */ private static final Map isHiddenCache = new ConcurrentHashMap (); /** * Cache for "getDisplayFileName" method result. */ private static final Map displayFileNameCache = new ConcurrentHashMap (); /** * Cache for "getFileDescription" method result. */ private static final Map fileDescriptionCache = new ConcurrentHashMap (); /** * Cache for "getFileTypeDescription" method result. */ private static final Map fileTypeDescriptionCache = new ConcurrentHashMap (); /** * Cache for "getDisplayFileCreationDate" method result. */ private static final Map displayFileCreationDateCache = new ConcurrentHashMap (); /** * Cache for "getDisplayFileModificationDate" method result. */ private static final Map displayFileModificationDateCache = new ConcurrentHashMap (); /** * File extension icons cache lock. */ private static final Object extensionIconsCacheLock = new Object (); /** * File extension icons cache. */ private static final Map extensionIconsCache = new ConcurrentHashMap (); /** * Resource icons cache. */ private static final Map resourceIconsCache = new ConcurrentHashMap (); /** * Default file tracking updates delay. */ private static final int FILE_TRACKING_DELAY = 5000; /** * File comparator. */ public static final FileComparator FILE_COMPARATOR = new FileComparator (); /** * Private constructor to avoid instantiation. */ private FileUtils () { throw new UtilityException ( "Utility classes are not meant to be instantiated" ); } /** * Returns JAR location URL for the specified class. * * @param jarClass any class from that JAR * @return JAR location URL */ @Nullable public static URL getJarLocationURL ( @NotNull final Class jarClass ) { final CodeSource src = jarClass.getProtectionDomain ().getCodeSource (); return src != null ? src.getLocation () : null; } /** * Returns JAR location File for the specified class. * * @param jarClass any class from that JAR * @return JAR location File */ @Nullable public static File getJarLocationFile ( @NotNull final Class jarClass ) { File file = null; try { final CodeSource src = jarClass.getProtectionDomain ().getCodeSource (); if ( src != null ) { final URL jarUrl = src.getLocation (); final URI uri = jarUrl.toURI (); final String scheme = uri.getScheme (); if ( scheme != null && scheme.equalsIgnoreCase ( "file" ) ) { file = new File ( uri ); } } } catch ( final URISyntaxException e ) { LoggerFactory.getLogger ( FileUtils.class ).error ( e.toString (), e ); } return file; } /** * Clears all caches for specified files. * * @param files files to process */ public static void clearFilesCaches ( @Nullable final File... files ) { if ( files != null && files.length > 0 ) { for ( final File file : files ) { clearFileCaches ( file ); } } } /** * Clears all caches for specified file. * * @param file file to process */ public static void clearFileCaches ( @Nullable final File file ) { if ( file != null ) { clearFileCaches ( file.getAbsolutePath () ); } } /** * Clears all caches for file under the specified path. * * @param path file path */ public static void clearFileCaches ( @NotNull final String path ) { clearDisplayFileNameCache ( path ); clearIsHiddenCache ( path ); clearIsFileCache ( path ); clearIsDirectoryCache ( path ); clearIsComputerCache ( path ); clearIsDriveCache ( path ); clearIsCdDriveCache ( path ); clearFileDescriptionCache ( path ); clearFileTypeDescriptionCache ( path ); clearDisplayFileCreationDateCache ( path ); clearDisplayFileModificationDateCache ( path ); } /** * Returns list of files contained in path of the specified file. *

* For example if you have some file that points to some local file: * "C:\folder\file.txt" * You will get this list of files: * "C:\", "C:\folder\", "C:\folder\file.txt" * * @param file file to process * @return list of files contained in path of the specified file */ @NotNull public static List getFilePath ( @Nullable File file ) { final List path = new ArrayList (); while ( file != null ) { path.add ( 0, file ); file = getParent ( file ); } return path; } /** * Returns file path relative to specified folder or canonical path if file is not inside that folder. * * @param file file to get relative path to * @param folder one of file's parent folders * @return file path relative to specified folder or canonical path if file is not inside that folder */ @NotNull public static String getRelativePath ( @NotNull final File file, @NotNull final File folder ) { return folder.toURI ().relativize ( file.toURI () ).getPath (); } /** * Returns whether specified file's name can be edited. * * @param file file to edit * @return true if specified file's name can be edited, false otherwise */ public static boolean isNameEditable ( @NotNull final File file ) { final File parent = getParent ( file ); return parent != null && parent.canWrite () && file.canWrite (); } /** * Sets file name as text and selects its name part in any text component. * * @param editor text editor to process * @param file file to process */ public static void displayFileName ( @NotNull final JTextComponent editor, @NotNull final File file ) { final String name = file.getName (); editor.setText ( name ); editor.setSelectionStart ( 0 ); editor.setSelectionEnd ( file.isDirectory () ? name.length () : FileUtils.getFileNamePart ( name ).length () ); } /** * Returns system directory for temporary files. * * @return system directory for temporary files */ @NotNull public static File getSystemTemp () { return new File ( getSystemTempPath () ); } /** * Returns path to system directory for temporary files. * * @return path to system directory for temporary files */ @NotNull public static String getSystemTempPath () { return System.getProperty ( "java.io.tmpdir" ); } /** * Grants file execution permission for all users for specified file. * * @param file file for permissions change * @return true if permissions change operation succeed, false otherwise */ public static boolean grantExecutePermissions ( @NotNull final File file ) { boolean granted; try { granted = file.setExecutable ( true, false ); } catch ( final Exception e ) { LoggerFactory.getLogger ( FileUtils.class ).error ( e.toString (), e ); granted = false; } return granted; } /** * Returns normalized file without redundant parts in its path. * * @param file file to normalize * @return normalized file */ @Nullable public static File normalize ( @Nullable final File file ) { File normalized; try { normalized = file != null ? file.getCanonicalFile () : null; } catch ( final IOException e ) { normalized = file; } return normalized; } /** * Returns first available file system root. * * @return first available file system root */ @Nullable public static File getSystemRoot () { final File[] roots = getSystemRoots (); return roots.length > 0 ? roots[ 0 ] : null; } /** * Returns array of available file system roots. * * @return array of available file system roots */ @NotNull public static File[] getSystemRoots () { final File[] systemRoots; synchronized ( fsv ) { systemRoots = fsv.getRoots (); } final File[] roots; if ( systemRoots != null && systemRoots.length > 0 ) { roots = systemRoots; } else { roots = getDiskRoots (); } return roots; } /** * Returns array of available system disks. * * @return array of available system disks */ @NotNull public static File[] getDiskRoots () { final File[] roots = File.listRoots (); int proper = 0; for ( final File root : roots ) { if ( isDirectory ( root ) ) { proper++; } } final File[] properRoots = new File[ proper ]; int currentIndex = 0; for ( final File root : roots ) { if ( isDirectory ( root ) ) { properRoots[ currentIndex ] = root; currentIndex++; } } return properRoots; } /** * Returns directory files array or empty array (instead of null) if no files present. * * @param directory directory to look into * @return directory files array or empty array (instead of null) if no files present */ @NotNull public static File[] listFiles ( @NotNull final File directory ) { return listFiles ( directory, ( FileFilter ) null ); } /** * Returns directory files array or empty array (instead of null) if no files present. * * @param directory directory to look into * @param fileFilter file filter * @return directory files array or empty array (instead of null) if no files present */ @NotNull public static File[] listFiles ( @NotNull final File directory, @Nullable final Filter fileFilter ) { return listFiles ( directory, fileFilter != null ? new FileFilter () { @Override public boolean accept ( @NotNull final File file ) { return fileFilter.accept ( file ); } } : null ); } /** * Returns directory files array or empty array (instead of null) if no files present. * * @param directory directory to look into * @param fileFilter file filter * @return directory files array or empty array (instead of null) if no files present */ @NotNull public static File[] listFiles ( @NotNull final File directory, @Nullable final FileFilter fileFilter ) { final File[] files = fileFilter != null ? directory.listFiles ( fileFilter ) : directory.listFiles (); return files != null ? files : new File[ 0 ]; } /** * Returns MD5 for specified {@link String} data. * * @param data file to process * @return MD5 for specified {@link String} data */ @NotNull public static String computeMD5 ( @NotNull final String data ) { return computeMD5 ( data, MD5_BUFFER_LENGTH ); } /** * Returns MD5 for specified {@link String} data and uses a buffer of the specified length. * * @param data file to process * @param bufferLength buffer length * @return MD5 for specified {@link String} data */ @NotNull public static String computeMD5 ( @NotNull final String data, final int bufferLength ) { return computeMD5 ( new ByteArrayInputStream ( data.getBytes () ), bufferLength ); } /** * Returns MD5 for specified {@link File} content. * * @param resource {@link Resource} to process * @return MD5 for specified {@link File} content */ @NotNull public static String computeMD5 ( @NotNull final Resource resource ) { return computeMD5 ( resource, MD5_BUFFER_LENGTH ); } /** * Returns MD5 for specified {@link File} content and uses a buffer of the specified length. * * @param resource {@link Resource} to process * @param bufferLength buffer length * @return MD5 for specified {@link File} content */ @NotNull public static String computeMD5 ( @NotNull final Resource resource, final int bufferLength ) { return computeMD5 ( resource.getInputStream (), bufferLength ); } /** * Returns MD5 for the data provided by {@link InputStream}. * * @param inputStream data stream to process * @return MD5 for the data provided by {@link InputStream} */ @NotNull public static String computeMD5 ( @NotNull final InputStream inputStream ) { return computeMD5 ( inputStream, MD5_BUFFER_LENGTH ); } /** * Returns MD5 for the data provided by {@link InputStream} and uses a buffer of the specified length. * * @param inputStream data stream to process * @param bufferLength buffer length * @return MD5 for the data provided by {@link InputStream} */ @NotNull public static String computeMD5 ( @NotNull final InputStream inputStream, final int bufferLength ) { final BufferedInputStream bis = new BufferedInputStream ( inputStream ); try { final MessageDigest digest = MessageDigest.getInstance ( "MD5" ); final byte[] buffer = new byte[ bufferLength ]; int bytesRead; while ( ( bytesRead = bis.read ( buffer, 0, buffer.length ) ) > 0 ) { digest.update ( buffer, 0, bytesRead ); } final byte[] md5sum = digest.digest (); final BigInteger bigInt = new BigInteger ( 1, md5sum ); return bigInt.toString ( 16 ); } catch ( final Exception e ) { throw new UtilityException ( "Unable to compute MD5 for InputStream: " + inputStream, e ); } finally { try { bis.close (); } catch ( final Exception ignored ) { // } } } /** * Returns application working directory. * * @return application working directory */ @NotNull public static File getWorkingDirectory () { return new File ( getWorkingDirectoryPath () ); } /** * Returns application working directory. * * @return application working directory */ @NotNull public static String getWorkingDirectoryPath () { return System.getProperty ( "user.dir" ); } /** * Returns user home directory. * * @return user home directory */ @NotNull public static File getUserHome () { return new File ( getUserHomePath () ); } /** * Returns path to user home directory. * * @return path to user home directory */ @NotNull public static String getUserHomePath () { String home = System.getProperty ( "user.home" ); if ( !home.endsWith ( File.separator ) ) { home += File.separator; } return home; } /** * Returns desktop directory if one can be found. * * @return desktop directory if one can be found */ @Nullable public static File getDesktop () { File desktop = null; final File[] roots = fsv.getRoots (); if ( roots.length > 0 ) { // Trying file system roots for ( final File root : roots ) { if ( root.getName ().toLowerCase ( Locale.ROOT ).contains ( "desktop" ) ) { desktop = root; break; } } } if ( desktop == null ) { // Trying common known location final File common = new File ( getUserHome (), "Desktop" ); if ( common.exists () ) { desktop = common; } } return desktop; } /** * Returns desktop directory path if one can be found. * * @return desktop directory path if one can be found */ @Nullable public static String getDesktopPath () { final File desktop = getDesktop (); return desktop != null ? desktop.getAbsolutePath () : null; } /** * Returns whether both files represent the same path in file system or not. * * @param file1 first file to be compared * @param file2 second file to be compared * @return true if both files represent the same path in file system, false otherwise */ public static boolean equals ( @Nullable final File file1, @Nullable final File file2 ) { boolean equals; if ( file1 == null && file2 == null ) { equals = true; } else { try { final boolean notNull = file1 != null && file2 != null; equals = notNull && file1.getCanonicalPath ().equals ( file2.getCanonicalPath () ); } catch ( final IOException e ) { equals = file1.getAbsolutePath ().equals ( file2.getAbsolutePath () ); } } return equals; } /** * Returns whether both list of files have equal files in the same positions or not. * * @param files1 first files list to be compared * @param files2 second files list to be compared * @return true if both list of files have equal files in the same positions, false otherwise */ public static boolean equals ( @NotNull final List files1, @NotNull final List files2 ) { boolean equals; if ( files1.size () == files2.size () ) { equals = true; if ( files1.size () != 0 ) { for ( int i = 0; i < files1.size (); i++ ) { if ( !equals ( files1.get ( i ), files2.get ( i ) ) ) { equals = false; break; } } } } else { equals = false; } return equals; } /** * Returns whether list of files or file paths contains the specified file or not. * * @param files list of files to search in * @param file file to look for * @return true if list of files or file paths contains the specified file, false otherwise */ public static boolean containsFile ( @NotNull final List files, @NotNull final File file ) { boolean contains = false; for ( final Object f : files ) { if ( f instanceof File ) { if ( ( ( File ) f ).getAbsolutePath ().equals ( file.getAbsolutePath () ) ) { contains = true; break; } } else if ( f instanceof String ) { if ( f.equals ( file.getAbsolutePath () ) ) { contains = true; break; } } } return contains; } /** * Returns whether any of the specified file filters accept the file or not. * * @param file file to process * @param filters file filters list * @return true if any of the specified file filters accept the file, false otherwise */ public static boolean isFileAccepted ( @NotNull final File file, @Nullable final List filters ) { boolean accepted; if ( filters != null && filters.size () != 0 ) { accepted = false; for ( final FileFilter fileFilter : filters ) { if ( fileFilter.accept ( file ) ) { accepted = true; break; } } } else { accepted = true; } return accepted; } /** * Returns a valid for any file system file name based on specified name. * * @param name name to process * @return file name valid for any file system */ @NotNull public static String getProperFileName ( @NotNull final String name ) { final StringBuilder newName = new StringBuilder (); for ( int i = 0; i < name.length (); ++i ) { if ( !isIllegalFileNameChar ( name.charAt ( i ) ) ) { newName.append ( name.charAt ( i ) ); } } return newName.toString ().replaceAll ( " ", "_" ); } /** * Returns whether the specified character is illegal or not. * * @param c character to process * @return true the specified character is illegal, false otherwise */ public static boolean isIllegalFileNameChar ( final char c ) { boolean isIllegal = false; for ( final char ILLEGAL_CHARACTER : ILLEGAL_CHARACTERS ) { if ( c == ILLEGAL_CHARACTER ) { isIllegal = true; } } return isIllegal; } /** * Returns file canonical path if its possible or absolute path otherwise. * * @param file file to process * @return file canonical path if its possible or absolute path otherwise */ @NotNull public static String canonicalPath ( @NotNull final File file ) { try { return file.getCanonicalPath (); } catch ( final IOException e ) { throw new UtilityException ( "Unable to retrieve file canonical path: " + file, e ); } } /** * Returns parent {@link File}. * Unlike {@link File#getParentFile()} it doesn't fail on cases when native parent is {@code null}. * Whenever native parent is {@code null} this method will fallback to {@link File#getParent()} path usage. * * @param file {@link File} to return parent {@link File} for * @return parent {@link File} */ @Nullable public static File getParent ( @NotNull final File file ) { final File parent; final File nativeParent = file.getParentFile (); if ( nativeParent != null ) { parent = nativeParent; } else { final String parentPath = file.getParent (); parent = parentPath != null ? new File ( parentPath ) : null; } return parent; } /** * Returns top not-null parent for the specified file. * If file has no parents at all simply returns null. * * @param file file to process * @return top not-null parent for the specified file or null if it has no parent files */ @Nullable public static File getTopParent ( @NotNull final File file ) { File result = null; File parent = getParent ( file.getAbsoluteFile () ); while ( parent != null ) { result = parent; parent = getParent ( parent ); } return result; } /** * Returns whether the specified child file is one of parent file children or not. * * @param parent parent file * @param child child file * @return true if the specified child file is one of parent file children, false otherwise */ public static boolean isParent ( @Nullable final File parent, @Nullable File child ) { boolean isParent; if ( child == parent ) { isParent = false; } else if ( child == null ) { isParent = false; } else if ( parent == null ) { isParent = true; } else if ( child.equals ( parent ) ) { isParent = false; } else { isParent = false; child = child.getAbsoluteFile (); File cp = getParent ( child ); while ( cp != null ) { if ( cp.equals ( parent ) ) { isParent = true; break; } cp = getParent ( cp ); } } return isParent; } /** * Returns file name without extension. * * @param file file to process * @return file name without extension */ @NotNull public static String getFileNamePart ( @Nullable final File file ) { return file != null ? getFileNamePart ( file.getName () ) : ""; } /** * Returns file name without extension. * * @param name file name to trim * @return file name without extension */ @NotNull public static String getFileNamePart ( @Nullable final String name ) { final String namePart; if ( TextUtils.notEmpty ( name ) ) { final int first = name.indexOf ( "." ); final int last = name.lastIndexOf ( "." ); namePart = last == -1 || first == 0 && first == last ? name : name.substring ( 0, last ); } else { namePart = ""; } return namePart; } /** * Returns file extension either with or without dot. * * @param file file to process * @param withDot whether return the extension with dot, or not * @return file extension */ @NotNull public static String getFileExtPart ( @Nullable final File file, final boolean withDot ) { return file != null ? getFileExtPart ( file.getName (), withDot ) : ""; } /** * Returns file extension either with or without dot. * * @param name file name to process * @param withDot whether return the extension with dot, or not * @return file extension */ @NotNull public static String getFileExtPart ( @Nullable final String name, final boolean withDot ) { final String ext; if ( TextUtils.notEmpty ( name ) ) { final int i = name.lastIndexOf ( "." ); ext = i == -1 ? "" : withDot ? name.substring ( i ) : name.substring ( i + 1 ); } else { ext = ""; } return ext; } /** * Returns shortened file name. * * @param name file name to shorten * @return shortened file name */ @NotNull public static String getShortFileName ( @Nullable final String name ) { return getShortFileName ( name, 30 ); } /** * Returns shortened to the specified length file name. * Note that file extension length is not counted. * * @param name file name to shorten * @param length maximum allowed file name length * @return shortened file name */ @NotNull public static String getShortFileName ( @Nullable final String name, final int length ) { String shortName = name != null ? name : ""; if ( length >= 2 ) { final String newName = getFileNamePart ( name ); if ( newName.length () > length ) { shortName = newName.substring ( 0, length - 2 ) + "..." + getFileExtPart ( name, false ); } } return shortName; } /** * Returns sorted list of files. * * @param files list of files to sort * @return sorted list of files */ @Nullable public static List sortFiles ( @Nullable final List files ) { if ( files != null ) { Collections.sort ( files, FILE_COMPARATOR ); } return files; } /** * Returns sorted array of files. * * @param files array of files to sort * @return sorted array of files */ @Nullable public static File[] sortFiles ( @Nullable final File[] files ) { if ( files != null ) { Arrays.sort ( files, FILE_COMPARATOR ); } return files; } /** * Returns available file name in the specified directory and which is similar the specified name. * * @param dir directory path to check * @param name file name to check * @return available file name */ @NotNull public static String getAvailableName ( @NotNull final String dir, @NotNull final String name ) { return getAvailableName ( new File ( dir ), name ); } /** * Returns available file name in the specified directory and which is similar the specified name. * * @param dir directory to check * @param name file name to check * @return available file name */ @NotNull public static String getAvailableName ( @NotNull final File dir, @NotNull final String name ) { final List exist = new ArrayList (); final File[] files = dir.listFiles (); if ( files != null ) { for ( final File file : files ) { exist.add ( file.getName () ); } } return getAvailableName ( exist, name ); } /** * Returns available file name that is not contained in the existing names list. * * @param existingNames list of existing file names * @param name file name to check * @return available file name that is not contained in the existing names list */ @NotNull public static String getAvailableName ( @NotNull final List existingNames, @NotNull final String name ) { String availableName = name; if ( existingNames.contains ( availableName ) ) { // Gathering name parts final int dot = availableName.lastIndexOf ( "." ); final String nameStart = dot != -1 ? availableName.substring ( 0, dot ).trim () : availableName; final String nameExt = dot != -1 ? availableName.substring ( availableName.lastIndexOf ( "." ) ) : null; final int ob = nameStart.lastIndexOf ( "(" ); final int cb = nameStart.lastIndexOf ( ")" ); String nameReal = null; Integer index = null; if ( ob < cb && cb == nameStart.length () - 1 ) { try { nameReal = nameStart.substring ( 0, ob ); index = Integer.parseInt ( nameStart.substring ( ob + 1, cb ) ); index++; } catch ( final Exception ignored ) { // } } // Choosing new name int i = 1; while ( existingNames.contains ( availableName ) ) { if ( nameReal != null && index != null ) { availableName = nameReal + "(" + index + ")" + nameExt; index++; } else { availableName = nameStart + " (" + i + ")" + ( nameExt != null ? nameExt : "" ); i++; } } } return availableName; } /** * Converts objects array into list of files. * Non-file type objects will be simply ignored. * * @param object file object * @return list of files */ @NotNull public static List toFilesList ( @Nullable final Object... object ) { final List files = new ArrayList ( object != null ? object.length : 0 ); for ( final Object file : files ) { if ( file instanceof File ) { files.add ( ( File ) file ); } } return files; } /** * Deletes all specified files. * * @param files files to delete */ public static void deleteFiles ( @NotNull final Object... files ) { for ( final Object object : files ) { if ( object instanceof File ) { deleteFile ( ( File ) object ); } } } /** * Deletes all specified files. * * @param files files to delete */ public static void deleteFiles ( @NotNull final List files ) { for ( final Object object : files ) { if ( object instanceof File ) { deleteFile ( ( File ) object ); } } } /** * Deletes file or directory completely. * All child files and directories will be removed first in case directory is deleted. * * @param file file to delete */ public static void deleteFile ( @NotNull final File file ) { if ( file.exists () ) { if ( file.isFile () ) { if ( !file.delete () ) { file.deleteOnExit (); } } else if ( file.isDirectory () ) { final File[] files = file.listFiles (); if ( files != null ) { for ( final File child : files ) { deleteFile ( child ); } } if ( !file.delete () ) { file.deleteOnExit (); } } } } /** * Deletes all child files and directories for specified directory. * Directory itself will not be deleted. * * @param dir directory to clear */ public static void clearDirectory ( @NotNull final File dir ) { if ( dir.exists () ) { if ( dir.isDirectory () ) { final File[] files = dir.listFiles (); if ( files != null ) { for ( final File child : files ) { deleteFile ( child ); } } } } } /** * Returns transformed file filter. * * @param fileFilter IO file filter * @return transformed file filter */ @NotNull public static AbstractFileFilter transformFileFilter ( @NotNull final FileFilter fileFilter ) { final AbstractFileFilter abstractFileFilter; if ( fileFilter instanceof AbstractFileFilter ) { abstractFileFilter = ( AbstractFileFilter ) fileFilter; } else { abstractFileFilter = new IOFileFilterAdapter ( fileFilter, AllFilesFilter.ICON, LM.get ( "weblaf.file.filter.custom" ) ); } return abstractFileFilter; } /** * Returns transformed file filter. * * @param fileFilter Swing file filter * @return transformed file filter. */ @NotNull public static AbstractFileFilter transformFileFilter ( @NotNull final javax.swing.filechooser.FileFilter fileFilter ) { final AbstractFileFilter abstractFileFilter; if ( fileFilter instanceof AbstractFileFilter ) { abstractFileFilter = ( AbstractFileFilter ) fileFilter; } else { abstractFileFilter = new SwingFileFilterAdapter ( fileFilter, AllFilesFilter.ICON ); } return abstractFileFilter; } /** * Returns actual Swing file filter from the specified filter. * * @param fileFilter WebLaF file filter * @return actual Swing file filter from the specified filter */ @Nullable public static javax.swing.filechooser.FileFilter getSwingFileFilter ( @Nullable final AbstractFileFilter fileFilter ) { return fileFilter != null && fileFilter instanceof SwingFileFilterAdapter ? ( ( SwingFileFilterAdapter ) fileFilter ).getFileFilter () : fileFilter; } /** * Returns filtered files list. * * @param files files collection to filter * @param fileFilter file filter * @return filtered files list */ @NotNull public static List filterFiles ( @NotNull final Collection files, @NotNull final AbstractFileFilter fileFilter ) { final List filteredFiles = new ArrayList ( files.size () ); for ( final File file : files ) { if ( fileFilter.accept ( file ) ) { filteredFiles.add ( file ); } } return filteredFiles; } /** * Returns filtered files list. * * @param files files collection to filter * @param fileFilter file filter * @return filtered files list */ @NotNull public static List filterFiles ( @NotNull final Collection files, @NotNull final Filter fileFilter ) { final List filteredFiles = new ArrayList ( files.size () ); for ( final File file : files ) { if ( fileFilter.accept ( file ) ) { filteredFiles.add ( file ); } } return filteredFiles; } /** * Returns complete file description. * * @param file file to process * @param fileSize file size * @return complete file description */ @NotNull public static FileDescription createFileDescription ( @NotNull final File file, @Nullable final String fileSize ) { // File name final String name = getDisplayFileName ( file ); // File or image size final String size = file.isFile () ? getDisplayFileSize ( file ) + ( fileSize != null ? " (" + fileSize + ")" : "" ) : null; // File type description final String description = getFileTypeDescription ( file ); // Modification date // long modified = file.lastModified (); // String date = modified != 0 ? /*"
" +*/ sdf.format ( new Date ( modified ) ) : null; return new FileDescription ( name, size, description, null /*date*/ ); } /** * Returns file size to display. * * @param file file to process * @return file size to display */ @NotNull public static String getDisplayFileSize ( @NotNull final File file ) { // todo Cache this value return getFileSizeString ( file.length () ); } /** * Returns file size to display. * * @param file file to process * @param digits number of digits after the dot * @return file size to display */ @NotNull public static String getDisplayFileSize ( @NotNull final File file, final int digits ) { // todo Cache file length value return getFileSizeString ( file.length (), digits ); } /** * Returns file size to display. * * @param size size of the file * @return file size to display */ @NotNull public static String getFileSizeString ( final long size ) { return getFileSizeString ( size, 2 ); } /** * Returns file size to display. * * @param size size of the file * @param digits number of digits after the dot * @return file size to display */ @NotNull public static String getFileSizeString ( final long size, final int digits ) { final String fileSizeString; final DecimalFormat df = new DecimalFormat ( digits > 0 ? "#." + TextUtils.createString ( "#", digits ) : "#" ); if ( size < KB ) { fileSizeString = df.format ( size ) + " " + LM.get ( "weblaf.file.size.b" ); } else if ( size < MB ) { fileSizeString = df.format ( ( float ) size / KB ) + " " + LM.get ( "weblaf.file.size.kb" ); } else if ( size < GB ) { fileSizeString = df.format ( ( float ) size / MB ) + " " + LM.get ( "weblaf.file.size.mb" ); } else if ( size < TB ) { fileSizeString = df.format ( ( float ) size / GB ) + " " + LM.get ( "weblaf.file.size.gb" ); } else if ( size < PB ) { fileSizeString = df.format ( ( float ) size / TB ) + " " + LM.get ( "weblaf.file.size.tb" ); } else { fileSizeString = df.format ( ( float ) size / PB ) + " " + LM.get ( "weblaf.file.size.pb" ); } return fileSizeString; } /** * Copies src directory content into dst directory and returns whether operation succeed or not. * Also ignores any exceptions that might occur during the copy process. * * @param src source directory path * @param dst destination directory path * @return true if copy operation succeed, false otherwise */ public static boolean copyDirectory ( @NotNull final String src, @NotNull final String dst ) { return copyDirectory ( src, dst, false ); } /** * Copies src directory content into dst directory and returns whether operation succeed or not. * Whether to stop copy operation if any exception occurs or not is set by stopOnFail argument. * * @param src source directory path * @param dst destination directory path * @param stopOnFail whether to stop copy operation if any exception occurs or not * @return true if copy operation succeed, false otherwise */ public static boolean copyDirectory ( @NotNull final String src, @NotNull final String dst, final boolean stopOnFail ) { return copyDirectory ( new File ( src ), new File ( dst ), stopOnFail ); } /** * Copies src directory content into dst directory and returns whether operation succeed or not. * Also ignores any exceptions that might occur during the copy process. * * @param srcDir source directory * @param dstDir destination directory * @return true if copy operation succeed, false otherwise */ public static boolean copyDirectory ( @NotNull final File srcDir, @NotNull final File dstDir ) { return copyDirectory ( srcDir, dstDir, false ); } /** * Copies src directory content into dst directory and returns whether operation succeed or not. * Whether to stop copy operation if any exception occurs or not is set by stopOnFail argument. * * @param srcDir source directory * @param dstDir destination directory * @param stopOnFail whether to stop copy operation if any exception occurs or not * @return true if copy operation succeed, false otherwise */ public static boolean copyDirectory ( @NotNull final File srcDir, @NotNull final File dstDir, final boolean stopOnFail ) { // todo Actually ignore exceptions as well if stopOnFail = false boolean success; if ( srcDir.exists () && srcDir.isDirectory () ) { // Ensure destination directory exists and perform copy if ( ensureDirectoryExists ( dstDir ) ) { // Copying all subdirectories and sub-files success = true; final File[] files = srcDir.listFiles (); if ( files != null ) { for ( final File file : files ) { final String copied = dstDir.getAbsolutePath () + File.separator + file.getName (); if ( file.isDirectory () ) { success = copyDirectory ( file.getAbsolutePath (), copied ) && success; if ( !success && stopOnFail ) { break; } } else { success = copyFile ( file.getAbsolutePath (), copied ) && success; if ( !success && stopOnFail ) { break; } } } } } else { success = false; } } else { success = false; } return success; } /** * Copies source file content into destination file. * If destination directory doesn't exist it will be created in the process. * If destination file doesn't exist it will be also created in the process. * * @param src source file path * @param dst destination file path * @return true if copy operation succeed, false otherwise */ public static boolean copyFile ( @Nullable final String src, @Nullable final String dst ) { final File srcFile = src != null ? new File ( src ) : null; final File dstFile = dst != null ? new File ( dst ) : null; return copyFile ( srcFile, dstFile ); } /** * Copies source file content into destination file. * If destination directory doesn't exist it will be created in the process. * If destination file doesn't exist it will be also created in the process. * * @param srcFile source file * @param dstFile destination file * @return true if copy operation succeed, false otherwise */ public static boolean copyFile ( @Nullable final File srcFile, @Nullable final File dstFile ) { boolean success = false; if ( srcFile != null && srcFile.exists () && srcFile.isFile () && dstFile != null ) { try { // Creating destination directory if needed if ( ensureDirectoryExists ( getParent ( dstFile ) ) ) { final FileChannel srcFC = new FileInputStream ( srcFile ).getChannel (); final FileChannel dstFC = new FileOutputStream ( dstFile ).getChannel (); success = copyFile ( srcFC, dstFC ); } } catch ( final FileNotFoundException ignored ) { } } return success; } /** * Copies file data from source file channel into destination file channel. * * @param srcFC source file channel * @param dstFC destination file channel * @return true if copy operation succeed, false otherwise */ public static boolean copyFile ( @NotNull final FileChannel srcFC, @NotNull final FileChannel dstFC ) { boolean success; try { dstFC.transferFrom ( srcFC, 0, srcFC.size () ); srcFC.close (); dstFC.close (); success = true; } catch ( final IOException e ) { success = false; } return success; } /** * Returns {@link String} content read from the {@link Resource}. * * @param resource {@link Resource} * @return {@link String} content read from the {@link Resource} */ @NotNull public static String readToString ( @NotNull final Resource resource ) { return readToString ( resource, defaultEncoding ); } /** * Returns {@link String} content read from the {@link Resource}. * * @param resource {@link Resource} * @param encoding content encoding * @return {@link String} content read from the {@link Resource} */ @NotNull public static String readToString ( @NotNull final Resource resource, @NotNull final String encoding ) { return readToString ( resource.getInputStream (), encoding ); } /** * Returns content read from the input stream. * * @param inputStream text content input stream * @return text content */ @NotNull public static String readToString ( @NotNull final InputStream inputStream ) { return readToString ( inputStream, defaultEncoding ); } /** * Returns content read from the input stream. * * @param inputStream text content input stream * @param encoding stream data encoding * @return content */ @NotNull public static String readToString ( @NotNull final InputStream inputStream, @NotNull final String encoding ) { try { return readToString ( new InputStreamReader ( inputStream, encoding ) ); } catch ( final Exception e ) { throw new UtilityException ( "Unable to read InputStream to string: " + inputStream, e ); } finally { try { inputStream.close (); } catch ( final IOException ignored ) { // Ignore this exception } } } /** * Returns content read from the specified reader. * * @param reader text content reader * @return content */ @NotNull public static String readToString ( @NotNull final Reader reader ) { try { int charsRead; final char[] buffer = new char[ TEXT_BUFFER_SIZE ]; final StringBuilder sb = new StringBuilder (); while ( ( charsRead = reader.read ( buffer, 0, TEXT_BUFFER_SIZE ) ) != -1 ) { sb.append ( buffer, 0, charsRead ); } return sb.toString (); } catch ( final Exception e ) { throw new UtilityException ( "Unable to read Reader to string: " + reader, e ); } finally { try { reader.close (); } catch ( final IOException ignored ) { // Ignore this exception } } } /** * Writes text to the specified file overwriting any content inside the file. * If file or even its directory doesn't exist - they will be created. * * @param text text to write * @param file file to write text into */ public static void writeStringToFile ( @NotNull final String text, @NotNull final File file ) { writeStringToFile ( text, file, defaultEncoding ); } /** * Writes text to the specified file overwriting any content inside the file. * If file or even its directory doesn't exist - they will be created. * * @param text text to write * @param file file to write text into * @param encoding file encoding */ public static void writeStringToFile ( @NotNull final String text, @NotNull final File file, @NotNull final String encoding ) { if ( !file.exists () || !file.isDirectory () ) { final File parent = getParent ( file ); if ( parent != null ) { // Creating directories if necessary parent.mkdirs (); // Writing text to file PrintWriter writer = null; try { writer = new PrintWriter ( file, encoding ); writer.write ( text ); } catch ( final Exception e ) { throw new UtilityException ( "Unable to write string to file: " + file, e ); } finally { if ( writer != null ) { writer.close (); } } } else { throw new UtilityException ( "Unable to determine file location: " + file ); } } else { throw new UtilityException ( "Specified file points to existing folder!" ); } } /** * Returns list of all file paths in this directory and all subdirectories. * * @param dir path of directory to process * @return list of file paths */ @NotNull public static List getSubPaths ( @NotNull final String dir ) { return getSubPaths ( new File ( dir ) ); } /** * Returns list of all file paths in this directory and all subdirectories. * * @param dir directory to process * @return list of file paths */ @NotNull public static List getSubPaths ( @NotNull final File dir ) { return getSubPaths ( dir, "" ); } /** * Returns list of all file paths in this directory and all subdirectories. * * @param dir directory to process * @param path path to current position * @return list of file paths */ @NotNull public static List getSubPaths ( @NotNull final File dir, @NotNull final String path ) { return getSubPaths ( dir, path, new ArrayList () ); } /** * Returns list of all file paths in this directory and all subdirectories. * * @param dir directory to process * @param path path to current position * @param paths list of collected paths * @return list of file paths */ @NotNull public static List getSubPaths ( @NotNull final File dir, @NotNull final String path, @NotNull final List paths ) { final File[] files = dir.listFiles (); if ( files != null ) { for ( final File file : files ) { if ( file.isFile () ) { paths.add ( path + file.getName () ); } else if ( file.isDirectory () ) { getSubPaths ( file, path + file.getName () + File.separator, paths ); } } } return paths; } /** * Downloads file from the specified url to destination file and returns it if download succeed. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dstFile destination file * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final File dstFile ) { return downloadFile ( url, dstFile, false, null, 3000, null ); } /** * Downloads file from the specified url to destination file and returns it if download succeed. * You can observe and manipulate the download process by providing a file download listener. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dstFile destination file * @param listener file download process listener * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final File dstFile, @Nullable final FileDownloadListener listener ) { return downloadFile ( url, dstFile, false, null, 3000, listener ); } /** * Downloads file from the specified url to destination file and returns it if download succeed. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dst destination file path * @param encodeUrl whether encode the source url or not * @param contentType content type limitation * @param timeout connection and read timeout * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final String dst, final boolean encodeUrl, @Nullable final String contentType, final int timeout ) { return downloadFile ( url, new File ( dst ), encodeUrl, contentType, timeout, null ); } /** * Downloads file from the specified url to destination file and returns it if download succeed. * You can observe and manipulate the download process by providing a file download listener. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dst destination file path * @param encodeUrl whether encode the source url or not * @param contentType content type limitation * @param timeout connection and read timeout * @param listener file download process listener * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final String dst, final boolean encodeUrl, @Nullable final String contentType, final int timeout, @Nullable final FileDownloadListener listener ) { return downloadFile ( url, new File ( dst ), encodeUrl, contentType, timeout, listener ); } /** * Downloads file from the specified url to destination file and returns it if download succeed. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dstFile destination file * @param encodeUrl whether encode the source url or not * @param contentType content type limitation * @param timeout connection and read timeout * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final File dstFile, final boolean encodeUrl, @Nullable final String contentType, final int timeout ) { return downloadFile ( url, dstFile, encodeUrl, contentType, timeout, null ); } /** * Downloads file from the specified url to destination file and returns it if download succeed. * You can observe and manipulate the download process by providing a file download listener. * todo Instead of multiple methods create DownloadParameters class that would contain all of the settings * * @param url file source url * @param dstFile destination file * @param encodeUrl whether encode the source url or not * @param contentType content type limitation * @param timeout connection and read timeout * @param listener file download process listener * @return downloaded file if download succeed */ @NotNull public static File downloadFile ( @NotNull final String url, @NotNull final File dstFile, final boolean encodeUrl, @Nullable final String contentType, final int timeout, @Nullable final FileDownloadListener listener ) { try { // Creating connection final URL encodedUrl = new URL ( encodeUrl ? WebUtils.encodeUrl ( url ) : url ); final URLConnection uc = ProxyManager.getURLConnection ( encodedUrl ); // Configuring timeouts if ( timeout != 0 ) { uc.setConnectTimeout ( timeout ); uc.setReadTimeout ( timeout ); } // Checking stop flag if ( listener != null && listener.shouldStopDownload () ) { deleteFile ( dstFile ); listener.fileDownloadAborted (); throw new UtilityException ( "File download was aborted" ); } // Content type limitation if ( contentType != null ) { final String ct = uc.getContentType (); if ( !ct.contains ( contentType ) ) { deleteFile ( dstFile ); if ( listener != null ) { listener.fileDownloadAborted (); } throw new UtilityException ( "File download was aborted due to content type not matching requested content type" ); } } // Notifying about file size if ( listener != null ) { listener.sizeDetermined ( uc.getContentLength () ); // Checking stop flag if ( listener.shouldStopDownload () ) { deleteFile ( dstFile ); listener.fileDownloadAborted (); throw new UtilityException ( "File download was aborted" ); } } // Opening file stream final InputStream in = uc.getInputStream (); final FileOutputStream out = new FileOutputStream ( dstFile ); // Checking stop flag if ( listener != null && listener.shouldStopDownload () ) { out.flush (); out.close (); in.close (); deleteFile ( dstFile ); listener.fileDownloadAborted (); throw new UtilityException ( "File download was aborted" ); } // Downloading content part by part final byte[] buf = new byte[ 50 * 1024 ]; int totalBytesRead = 0; int bytesRead; while ( ( bytesRead = in.read ( buf ) ) != -1 ) { if ( listener != null ) { totalBytesRead += bytesRead; listener.partDownloaded ( totalBytesRead ); // Checking stop flag if ( listener.shouldStopDownload () ) { out.flush (); out.close (); in.close (); deleteFile ( dstFile ); listener.fileDownloadAborted (); throw new UtilityException ( "File download was aborted" ); } } out.write ( buf, 0, bytesRead ); } out.flush (); out.close (); in.close (); // Informing about completed download if ( listener != null ) { listener.fileDownloaded ( dstFile ); } return dstFile; } catch ( final Exception e ) { // Informing about failed download if ( listener != null ) { listener.fileDownloadFailed ( e ); } throw new UtilityException ( "Unable to download file from URL: " + url, e ); } } /** * Returns file size, located at the specified url. * * @param url file location url * @return file size */ public static int getFileSize ( @NotNull final String url ) { try { return getFileSize ( new URL ( url ) ); } catch ( final Exception e ) { throw new UtilityException ( "Unable to retrieve file size for URL: " + url, e ); } } /** * Returns file size, located at the specified url. * * @param url file location url * @return file size */ public static int getFileSize ( @NotNull final URL url ) { try { // Creating URLConnection final URLConnection uc = ProxyManager.getURLConnection ( url ); // todo This size is limited to maximum of 2GB, should retrieve long instead // Retrieving file size return uc.getContentLength (); } catch ( final Exception e ) { throw new UtilityException ( "Unable to retrieve file size for URL: " + url, e ); } } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir path to directory to process * @param extension file extensions list * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final String dir, @NotNull final List extension ) { return findFilesRecursively ( new File ( dir ), extension ); } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir directory to process * @param extension file extensions list * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final File dir, @NotNull final List extension ) { return findFilesRecursively ( dir, extension, true ); } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir path to directory to process * @param extension file extensions list * @param withDot whether extensions contain dot or not * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final String dir, @NotNull final List extension, final boolean withDot ) { return findFilesRecursively ( new File ( dir ), extension, withDot ); } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir directory to process * @param extension file extensions list * @param withDot whether extensions contain dot or not * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final File dir, @NotNull final List extension, final boolean withDot ) { return findFilesRecursively ( dir, extension, withDot, new ArrayList () ); } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir path to directory to process * @param extension file extensions list * @param withDot whether extensions contain dot or not * @param found list in which found files should be stored * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final String dir, @NotNull final List extension, final boolean withDot, @NotNull final List found ) { return findFilesRecursively ( new File ( dir ), extension, withDot, found ); } /** * Returns list of files with specified extensions found in the specified directory and its subdirectories. * * @param dir directory to process * @param extension file extensions list * @param withDot whether extensions contain dot or not * @param found list in which found files should be stored * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final File dir, @NotNull final List extension, final boolean withDot, @NotNull final List found ) { return findFilesRecursively ( dir, new FileFilter () { @Override public boolean accept ( @NotNull final File file ) { return file.isFile () && extension.contains ( getFileExtPart ( file.getName (), withDot ) ); } }, found ); } /** * Returns list of files accepted by file filter found in the specified directory and its subdirectories. * * @param dir path to directory to process * @param filter file filter * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final String dir, @NotNull final FileFilter filter ) { return findFilesRecursively ( new File ( dir ), filter ); } /** * Returns list of files accepted by file filter found in the specified directory and its subdirectories. * * @param dir directory to process * @param filter file filter * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final File dir, @NotNull final FileFilter filter ) { return findFilesRecursively ( dir, filter, new ArrayList () ); } /** * Returns list of files accepted by file filter found in the specified directory and its subdirectories. * * @param dir path to directory to process * @param filter file filter * @param found list in which found files should be stored * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final String dir, @NotNull final FileFilter filter, @NotNull final List found ) { return findFilesRecursively ( new File ( dir ), filter, found ); } /** * Returns list of files accepted by file filter found in the specified directory and its subdirectories. * * @param dir directory to process * @param filter file filter * @param found list in which found files should be stored * @return list of found files */ @NotNull public static List findFilesRecursively ( @NotNull final File dir, @NotNull final FileFilter filter, @NotNull final List found ) { if ( dir.exists () && dir.isDirectory () ) { final File[] files = dir.listFiles (); if ( files != null ) { for ( final File file : files ) { if ( filter.accept ( file ) ) { found.add ( file ); } if ( file.isDirectory () ) { findFilesRecursively ( file, filter, found ); } } } } return found; } /** * Returns true if directory exists or was successfully created during this check, false otherwise. * * @param dir path to directory to check * @return true if directory exists or was successfully created during this check, false otherwise */ public static boolean ensureDirectoryExists ( @Nullable final String dir ) { return dir != null && ensureDirectoryExists ( new File ( dir ) ); } /** * Returns true if directory exists or was successfully created during this check, false otherwise. * * @param dir directory to check * @return true if directory exists or was successfully created during this check, false otherwise */ public static boolean ensureDirectoryExists ( @Nullable final File dir ) { return dir != null && ( dir.exists () || dir.mkdirs () ); } /** * Clears cache for "isDrive" method. */ public static void clearIsDriveCache () { isDriveCache.clear (); } /** * Clears cache for "isDrive" method for specified file path. * * @param absolutePath path to clear file isDrive mark cache for */ public static void clearIsDriveCache ( @NotNull final String absolutePath ) { isDriveCache.remove ( absolutePath ); } /** * Returns whether the specified file points to system hard drive or not. * * @param file file to process * @return true if the specified file points to system hard drive, false otherwise */ public static boolean isDrive ( @NotNull final File file ) { final boolean isDrive; final String absolutePath = file.getAbsolutePath (); if ( isDriveCache.containsKey ( absolutePath ) ) { isDrive = isDriveCache.get ( absolutePath ); } else if ( file.exists () ) { synchronized ( fsv ) { isDrive = fsv.isDrive ( file ); } isDriveCache.put ( absolutePath, isDrive ); } else { isDrive = false; } return isDrive; } /** * Clears cache for "isComputer" method. */ public static void clearIsComputerCache () { isComputerCache.clear (); } /** * Clears cache for "isComputer" method for specified file path. * * @param absolutePath path to clear file isComputer mark cache for */ public static void clearIsComputerCache ( @NotNull final String absolutePath ) { isComputerCache.remove ( absolutePath ); } /** * Returns whether the specified file points to system hard drive or not. * * @param file file to process * @return true if the specified file points to system hard drive, false otherwise */ public static boolean isComputer ( @NotNull final File file ) { final boolean isComputer; final String absolutePath = file.getAbsolutePath (); if ( isComputerCache.containsKey ( absolutePath ) ) { isComputer = isComputerCache.get ( absolutePath ); } else if ( file.exists () ) { synchronized ( fsv ) { isComputer = fsv.isComputerNode ( file ); } isComputerCache.put ( absolutePath, isComputer ); } else { isComputer = false; } return isComputer; } /** * Clears cache for "isCdDrive" method. */ public static void clearIsCdDriveCache () { isCdDriveCache.clear (); } /** * Clears cache for "isCdDrive" method for specified file path. * * @param absolutePath path to clear file isCdDrive mark cache for */ public static void clearIsCdDriveCache ( @NotNull final String absolutePath ) { isCdDriveCache.remove ( absolutePath ); } /** * Returns whether the specified file points to system CD/DVD/Bluray drive or not. * This method bases on file type description and might not work on some systems which does not provide it. * This method caches its result to improve its performance when used in various renderers. * * @param file file to process * @return true if the specified file points to system CD, DVD or Bluray drive, false otherwise */ public static boolean isCdDrive ( @NotNull final File file ) { final boolean isCdDrive; final String absolutePath = file.getAbsolutePath (); if ( isCdDriveCache.containsKey ( absolutePath ) ) { isCdDrive = isCdDriveCache.get ( absolutePath ); } else if ( file.exists () ) { if ( file.getParent () == null ) { final String sysDes = getFileTypeDescription ( file ); final String description; if ( TextUtils.notEmpty ( sysDes ) ) { description = sysDes.toLowerCase ( Locale.ROOT ); } else { description = file.getName (); } isCdDrive = description.contains ( "cd" ) || description.contains ( "dvd" ) || description.contains ( "blu-ray" ) || description.contains ( "bluray" ); } else { isCdDrive = false; } isCdDriveCache.put ( absolutePath, isCdDrive ); } else { isCdDrive = false; } return isCdDrive; } /** * Clears cache for "isFile" method. */ public static void clearIsFileCache () { isFileCache.clear (); } /** * Clears cache for "isFile" method for specified file path. * * @param absolutePath path to clear file isFile mark cache for */ public static void clearIsFileCache ( @NotNull final String absolutePath ) { isFileCache.remove ( absolutePath ); } /** * Returns whether the specified file is actually a file (and not a directory, disk or some system folder) or not. * * @param file file to process * @return true if the specified file is actually a file, false otherwise */ public static boolean isFile ( @Nullable final File file ) { boolean isFile = false; if ( file != null ) { final String absolutePath = file.getAbsolutePath (); if ( isFileCache.containsKey ( absolutePath ) ) { isFile = isFileCache.get ( absolutePath ); } else if ( file.exists () ) { isFile = file.isFile (); isFileCache.put ( absolutePath, isFile ); } } return isFile; } /** * Clears cache for "isDirectory" method. */ public static void clearIsDirectoryCache () { isDirectoryCache.clear (); } /** * Clears cache for "isDirectory" method for specified file path. * * @param absolutePath path to clear file isDirectory mark cache for */ public static void clearIsDirectoryCache ( @NotNull final String absolutePath ) { isDirectoryCache.remove ( absolutePath ); } /** * Returns whether the specified file is directory or not. * * @param file file to process * @return true if the specified file is directory, false otherwise */ public static boolean isDirectory ( @Nullable final File file ) { boolean isDirectory = false; if ( file != null ) { final String absolutePath = file.getAbsolutePath (); if ( isDirectoryCache.containsKey ( absolutePath ) ) { isDirectory = isDirectoryCache.get ( absolutePath ); } else if ( file.exists () ) { isDirectory = file.isDirectory (); isDirectoryCache.put ( absolutePath, isDirectory ); } } return isDirectory; } /** * Clears cache for "isHidden" method. */ public static void clearIsHiddenCache () { isHiddenCache.clear (); } /** * Clears cache for "isHidden" method for specified file path. * * @param absolutePath path to clear file hidden mark cache for */ public static void clearIsHiddenCache ( @NotNull final String absolutePath ) { isHiddenCache.remove ( absolutePath ); } /** * Returns whether the specified file is hidden or not. * * @param file file to process * @return true if the specified file is hidden, false otherwise */ public static boolean isHidden ( @Nullable final File file ) { boolean isHidden = false; if ( file != null ) { final String absolutePath = file.getAbsolutePath (); if ( isHiddenCache.containsKey ( absolutePath ) ) { isHidden = isHiddenCache.get ( absolutePath ); } else if ( file.exists () ) { final File absoluteFile = file.getAbsoluteFile (); isHidden = getParent ( absoluteFile ) != null && absoluteFile.isHidden (); isHiddenCache.put ( absolutePath, isHidden ); } } return isHidden; } /** * Clears cache for "getFileDescription" method. */ public static void clearFileDescriptionCache () { fileDescriptionCache.clear (); } /** * Clears cache for "getFileDescription" method for specified file path. * * @param absolutePath path to clear file description cache */ public static void clearFileDescriptionCache ( @NotNull final String absolutePath ) { fileDescriptionCache.remove ( absolutePath ); } /** * Returns complete file description. * * @param file file to process * @param fileSize file size on disk * @return complete file description */ public static FileDescription getFileDescription ( @NotNull final File file, @Nullable final String fileSize ) { final FileDescription fileDescription; final String absolutePath = file.getAbsolutePath (); if ( fileDescriptionCache.containsKey ( absolutePath ) ) { fileDescription = fileDescriptionCache.get ( absolutePath ); } else if ( file.exists () ) { fileDescription = createFileDescription ( file, fileSize ); fileDescriptionCache.put ( absolutePath, fileDescription ); } else { fileDescription = new FileDescription ( "Unknown", "0", "", null ); } return fileDescription; } /** * Returns appropriate file name based on provided text. * * @param text text to trim * @return appropriate file name based on provided text */ @NotNull public static String appropriateFileName ( @NotNull final String text ) { return appropriateFileName ( text, "" ); } /** * Returns appropriate file name based on provided text. * * @param text text to trim * @param replacement replacement for each invalid symbol * @return appropriate file name based on provided text */ @NotNull public static String appropriateFileName ( @NotNull final String text, @NotNull final String replacement ) { return text.replaceAll ( "[^ a-zA-Zа-яА-Я0-9.-]", replacement ); } /** * Clears cache for "getDisplayFileName" method. */ public static void clearDisplayFileNameCache () { displayFileNameCache.clear (); } /** * Clears cache for "getDisplayFileName" method for specified file path. * * @param absolutePath path path path to clear file display name cache for */ public static void clearDisplayFileNameCache ( @NotNull final String absolutePath ) { displayFileNameCache.remove ( absolutePath ); } /** * Returns file name to display. * * @param file file to process * @return file name to display */ @NotNull public static String getDisplayFileName ( @NotNull final File file ) { String name; final String absolutePath = file.getAbsolutePath (); if ( displayFileNameCache.containsKey ( absolutePath ) ) { name = displayFileNameCache.get ( absolutePath ); } else if ( file.exists () ) { synchronized ( fsv ) { name = fsv.getSystemDisplayName ( file ); } if ( TextUtils.isBlank ( name ) ) { name = getFileTypeDescription ( file ); } displayFileNameCache.put ( absolutePath, name ); } else if ( !file.exists () ) { displayFileNameCache.put ( absolutePath, file.getName () ); name = file.getName (); } else { name = file.getName (); } return name; } /** * Clears cache for "getDisplayFileCreationDate" method. */ public static void clearDisplayFileCreationDateCache () { displayFileCreationDateCache.clear (); } /** * Clears cache for "getDisplayFileCreationDate" method for specified file path. * * @param absolutePath path path to clear file creation date cache for */ public static void clearDisplayFileCreationDateCache ( @NotNull final String absolutePath ) { displayFileCreationDateCache.remove ( absolutePath ); } /** * Returns file modification date to display. * * @param file file to process * @return file modification date to display */ @NotNull public static String getDisplayFileCreationDate ( @NotNull final File file ) { final String date; final String absolutePath = file.getAbsolutePath (); if ( displayFileCreationDateCache.containsKey ( absolutePath ) ) { date = displayFileCreationDateCache.get ( absolutePath ); } else if ( file.exists () ) { date = sdf.format ( new Date ( file.lastModified () ) ); displayFileCreationDateCache.put ( absolutePath, date ); } else { date = ""; } return date; } /** * Clears cache for "getDisplayFileModificationDate" method. */ public static void clearDisplayFileModificationDateCache () { displayFileModificationDateCache.clear (); } /** * Clears cache for "getDisplayFileModificationDate" method for specified file path. * * @param absolutePath path path to clear file modification date cache for */ public static void clearDisplayFileModificationDateCache ( @NotNull final String absolutePath ) { displayFileModificationDateCache.remove ( absolutePath ); } /** * Returns file modification date to display. * * @param file file to process * @return file modification date to display */ @NotNull public static String getDisplayFileModificationDate ( @NotNull final File file ) { final String date; final String absolutePath = file.getAbsolutePath (); if ( displayFileModificationDateCache.containsKey ( absolutePath ) ) { date = displayFileModificationDateCache.get ( absolutePath ); } else if ( file.exists () ) { date = sdf.format ( new Date ( file.lastModified () ) ); displayFileModificationDateCache.put ( absolutePath, date ); } else { date = ""; } return date; } /** * Clears cache for "getFileTypeDescription" method. */ public static void clearFileTypeDescriptionCache () { fileTypeDescriptionCache.clear (); } /** * Clears cache for "getFileTypeDescription" method for specified file path. * * @param absolutePath path to clear file type description cache for */ public static void clearFileTypeDescriptionCache ( @NotNull final String absolutePath ) { fileTypeDescriptionCache.remove ( absolutePath ); } /** * Returns file type description. * * @param file file to process * @return file type description */ @NotNull public static String getFileTypeDescription ( @Nullable final File file ) { String description = ""; if ( file != null ) { final String absolutePath = file.getAbsolutePath (); if ( fileTypeDescriptionCache.containsKey ( absolutePath ) ) { description = fileTypeDescriptionCache.get ( absolutePath ); } else if ( file.exists () ) { synchronized ( fsv ) { description = fsv.getSystemTypeDescription ( file ); } if ( description == null ) { description = ""; } fileTypeDescriptionCache.put ( absolutePath, absolutePath ); } } return description; } /** * Returns system file icon. * * @param file file to process * @return system file icon */ @Nullable public static Icon getFileIcon ( @Nullable final File file ) { return getFileIcon ( file, false ); } /** * Returns either large or small system file icon. * * @param file file to process * @param large whether return large icon or not * @return either large or small system file icon */ @Nullable public static Icon getFileIcon ( @Nullable final File file, final boolean large ) { // This way of icon retrieval is disabled due to inaccurate icon sizes on Win Vista/7/8 // if ( SystemUtils.isWindows () ) // { // if ( file == null ) // { // return null; // } // // ShellFolder sf; // try // { // sf = ShellFolder.getShellFolder ( file ); // } // catch ( FileNotFoundException e ) // { // return null; // } // // Image img = sf.getIcon ( large ); // if ( img != null ) // { // return new ImageIcon ( img, sf.getFolderType () ); // } // else // { // return null; // } // } // else // { return getStandardFileIcon ( file, large ); // } } /** * Returns either large or small file icon from a standard icons set. * * @param file file to process * @param large whether return large icon or not * @return either large or small file icon */ @Nullable public static Icon getStandardFileIcon ( @Nullable final File file, final boolean large ) { return getStandardFileIcon ( file, large, true ); } /** * Returns either large or small file icon from a standard icons set. * * @param file file to process * @param large whether return large icon or not * @param enabled whether enabled icon or not * @return either large or small file icon */ @Nullable public static Icon getStandardFileIcon ( @Nullable final File file, final boolean large, final boolean enabled ) { Icon icon = null; if ( file != null ) { // todo Properly lock operations for all cached file methods // Retrieving required icon extension or type String extension; if ( !isDirectory ( file ) ) { extension = getFileExtPart ( file.getName (), false ).trim ().toLowerCase ( Locale.ROOT ); if ( extension.trim ().equals ( "" ) ) { extension = file.getAbsolutePath (); } } else if ( isCdDrive ( file ) ) { extension = "cd_drive"; } else if ( isDrive ( file ) ) { extension = "drive"; } else if ( isComputer ( file ) ) { extension = "computer"; } else { extension = "folder"; } // Constructing icon cache key final float opacity = isHidden ( file ) ? 0.5f : 1f; final String key = getStandardFileIconCacheKey ( extension, large, opacity, enabled ); // Retrieving icon final boolean contains; synchronized ( extensionIconsCacheLock ) { contains = extensionIconsCache.containsKey ( key ); } if ( contains ) { synchronized ( extensionIconsCacheLock ) { icon = extensionIconsCache.get ( key ); } } else { // Retrieving file type icon icon = getStandardFileIcon ( large, extension, opacity ); if ( icon == null ) { // Simply use unknown file icon icon = getStandardFileIcon ( large, "file", opacity ); } // Caching the resulting icon if ( enabled ) { // Cache enabled icon if ( icon != null ) { synchronized ( extensionIconsCacheLock ) { extensionIconsCache.put ( key, icon ); } } } else { // Cache enabled icon final String keyEnabled = getStandardFileIconCacheKey ( extension, large, opacity, true ); if ( icon != null ) { synchronized ( extensionIconsCacheLock ) { extensionIconsCache.put ( keyEnabled, icon ); } } // Cache disabled icon if ( icon != null ) { icon = ImageUtils.getDisabledCopy ( icon ); synchronized ( extensionIconsCacheLock ) { extensionIconsCache.put ( key, icon ); } } } } } return icon; } /** * Returns standard file icon cache key. * * @param extension file extension or identifier * @param large whether large icon used or not * @param opacity icon opacity * @param enabled whether enabled icon or not * @return standard file icon cache key */ @NotNull private static String getStandardFileIconCacheKey ( @NotNull final String extension, final boolean large, final float opacity, final boolean enabled ) { return extension + CACHE_KEYS_SEPARATOR + large + CACHE_KEYS_SEPARATOR + opacity + CACHE_KEYS_SEPARATOR + enabled; } /** * Returns either large or small icon for the specified extension from a standard icons set. * * @param large whether return large icon or not * @param extension file extension * @param opacity icon opacity * @return either large or small icon for the specified extension */ @Nullable public static Icon getStandardFileIcon ( final boolean large, @NotNull final String extension, final float opacity ) { final String path = "icons/extensions/" + ( large ? "32" : "16" ) + "/file_extension_" + extension + ".png"; return getIconResource ( FileUtils.class, path, opacity ); } /** * Returns resource icon. * Note that returned icon will be cached using its placement. * * @param nearClass class near which the icon is located * @param resource icon location * @return resource icon */ @Nullable public static Icon getIconResource ( @NotNull final Class nearClass, @NotNull final String resource ) { return getIconResource ( nearClass, resource, 1f ); } /** * Returns resource icon with the specified opacity. * Note that returned icon will be cached using its placement and opacity value. * * @param nearClass class near which the icon is located * @param resource icon location * @param opacity custom icon opacity * @return resource icon */ @Nullable public static Icon getIconResource ( @NotNull final Class nearClass, @NotNull final String resource, final float opacity ) { Icon icon; final String key = nearClass.getCanonicalName () + CACHE_KEYS_SEPARATOR + resource + CACHE_KEYS_SEPARATOR + opacity; if ( resourceIconsCache.containsKey ( key ) ) { icon = resourceIconsCache.get ( key ); } else { final URL url = nearClass.getResource ( resource ); if ( url != null ) { icon = new ImageIcon ( url ); if ( opacity < 1f ) { icon = ImageUtils.createTransparentCopy ( icon, opacity ); } } else { icon = null; } if ( icon != null ) { resourceIconsCache.put ( key, icon ); } } return icon; } /** * Starts tracking file for possible changes. * * @param file file to track * @param listener system file listener * @return tracking timer */ @NotNull public static WebTimer trackFile ( @NotNull final File file, @NotNull final SystemFileListener listener ) { return trackFile ( file, listener, FILE_TRACKING_DELAY ); } /** * Starts tracking file for possible changes. * * @param file file to track * @param listener system file listener * @param delay delay between checks for changes * @return tracking timer */ @NotNull public static WebTimer trackFile ( @NotNull final File file, @NotNull final SystemFileListener listener, final long delay ) { final WebTimer tracker = new WebTimer ( "File tracker - " + file.getName (), delay, 0 ); tracker.addActionListener ( new ActionListener () { private Long lastModified = null; @Override public void actionPerformed ( @NotNull final ActionEvent e ) { if ( file.exists () ) { final long lm = file.lastModified (); if ( lastModified != lm ) { listener.modified ( file ); lastModified = lm; } } else { listener.unbound ( file ); tracker.stop (); } } } ); tracker.setUseDaemonThread ( true ); return tracker; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy