--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.Closeable;\r
+import java.io.File;\r
+import java.io.FileFilter;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
+import java.io.OutputStream;\r
+import java.io.RandomAccessFile;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URI;\r
+import java.net.URL;\r
+import java.nio.channels.FileChannel;\r
+import java.nio.charset.Charset;\r
+import java.nio.file.FileVisitResult;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.SimpleFileVisitor;\r
+import java.nio.file.StandardCopyOption;\r
+import java.nio.file.attribute.BasicFileAttributes;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Deque;\r
+import java.util.LinkedList;\r
+import java.util.Random;\r
+import java.util.zip.DataFormatException;\r
+import java.util.zip.Deflater;\r
+import java.util.zip.Inflater;\r
+import java.util.zip.ZipEntry;\r
+import java.util.zip.ZipException;\r
+import java.util.zip.ZipInputStream;\r
+import java.util.zip.ZipOutputStream;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.adapter.Adapter;\r
+import org.simantics.databoard.adapter.AdapterConstructionException;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.utils.bytes.LEInt;\r
+import org.simantics.utils.strings.FileNameUtils;\r
+\r
+/**\r
+ * Utilities for common file operations.\r
+ *\r
+ * see StreamUtil in databoard for Input/OutputStream reading/writing utils\r
+ * @see FileNameUtils for more utils\r
+ * \r
+ * @author Toni Kalajainen\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class FileUtils {\r
+\r
+ /**\r
+ * Create escaped filename\r
+ * \r
+ * @param name any string\r
+ * @return file compatible string\r
+ */\r
+ public static String escapeFileName(String name) {\r
+ try {\r
+ return java.net.URLEncoder.encode(name, "UTF-8");\r
+ } catch (UnsupportedEncodingException e) {\r
+ // never expected\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Unescape filename into string \r
+ * \r
+ * @param filename \r
+ * @return any string\r
+ */\r
+ public static String unescapeFileName(String filename) {\r
+ try {\r
+ return java.net.URLDecoder.decode(filename, "UTF-8");\r
+ } catch (UnsupportedEncodingException e) {\r
+ // never expected\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+\r
+ public static File ensureParentDirectoryExists(String path) throws IOException {\r
+ return ensureParentDirectoryExists(new File(path));\r
+ }\r
+\r
+ /**\r
+ * Ensures the parent directory pointed by the specified file path exists as a\r
+ * directory.\r
+ * \r
+ * @param path the directory whose existence is to be ensured\r
+ * @return the requested directory\r
+ * @throws IOException if the specified directory cannot be created or\r
+ * already exists as a file\r
+ */\r
+ public static File ensureParentDirectoryExists(File path) throws IOException {\r
+ return ensureDirectoryExists(path.getParentFile());\r
+ }\r
+ \r
+ \r
+ public static File ensureDirectoryExists(String path) throws IOException {\r
+ return ensureDirectoryExists(new File(path));\r
+ }\r
+\r
+ /**\r
+ * Ensures the directory pointed by the specified file path exists as a\r
+ * directory.\r
+ * \r
+ * @param path the directory whose existence is to be ensured\r
+ * @return the requested directory\r
+ * @throws IOException if the specified directory cannot be created or\r
+ * already exists as a file\r
+ */\r
+ public static File ensureDirectoryExists(File path) throws IOException {\r
+ if (path.isDirectory())\r
+ // Already exists, everything OK.\r
+ return path;\r
+\r
+ if (path.exists())\r
+ // Path is not a directory but it exists, fail!\r
+ throw new IOException("file '" + path + "', already exists but it is not a directory");\r
+\r
+ path.mkdirs();\r
+ if (!path.exists())\r
+ // Path is not a directory but it exists, fail!\r
+ throw new IOException("could not create directory '" + path + "' for an unknown reason");\r
+\r
+ // Directory created OK.\r
+ return path;\r
+ }\r
+\r
+ /**\r
+ * Copies the contents of a source file to the destination file.\r
+ * \r
+ * @param sourceFile the source file descriptor\r
+ * @param destFile the destination file descriptor\r
+ * @throws IOException when anything IO-related goes wrong during the copy\r
+ */\r
+ public static void copyFile(File sourceFile, File destFile) throws IOException {\r
+ if (!destFile.exists()) {\r
+ destFile.createNewFile();\r
+ }\r
+\r
+ FileInputStream fis = null;\r
+ FileOutputStream fos = null;\r
+ try {\r
+ fis = new FileInputStream(sourceFile);\r
+ fos = new FileOutputStream(destFile);\r
+ FileChannel source = fis.getChannel();\r
+ FileChannel destination = fos.getChannel();\r
+\r
+ long count = 0;\r
+ long size = source.size();\r
+ while (count < size) {\r
+ count += destination.transferFrom(source, count, size - count);\r
+ }\r
+ } finally {\r
+ if (fis != null) {\r
+ uncheckedClose(fis);\r
+ }\r
+ if (fos != null) {\r
+ uncheckedClose(fos);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Copy file or dir recursively.\r
+ * \r
+ * @param src\r
+ * @param dst\r
+ * @throws IOException\r
+ */\r
+ public static void copy(File src, File dst) throws IOException\r
+ {\r
+ if (src.isDirectory()) {\r
+ if(!dst.exists()) dst.mkdir();\r
+\r
+ for (String file : src.list()) {\r
+ File srcFile = new File(src, file);\r
+ File dstFile = new File(dst, file);\r
+ copy(srcFile,dstFile);\r
+ }\r
+ } else {\r
+ copyFile(src, dst);\r
+ }\r
+ }\r
+ \r
+\r
+// public static File createTempFileFromResource(URL sourceUrl) throws IOException {\r
+// sourceUrl = FileLocator.resolve(sourceUrl);\r
+// File sourceFile;\r
+// try {\r
+// if (sourceUrl.getProtocol().equalsIgnoreCase("file"))\r
+// sourceFile = new File(sourceUrl.getPath());\r
+// else\r
+// sourceFile = new File(sourceUrl.toURI());\r
+// } catch (URISyntaxException e) {\r
+// throw new RuntimeException(e);\r
+// }\r
+//\r
+// File tempFile = File.createTempFile("tmp", ".tmp");\r
+// FileUtils.copyFile(sourceFile, tempFile);\r
+// return tempFile;\r
+// }\r
+\r
+ /**\r
+ * Reads entire binary file\r
+ * @param file file\r
+ * @return contents of binary file\r
+ * @throws IOException on i/o problems\r
+ */\r
+ public static byte[] readFile(File file)\r
+ throws IOException\r
+ {\r
+ try (FileInputStream fis = new FileInputStream(file)) {\r
+ long size = file.length();\r
+ if (size>Integer.MAX_VALUE)\r
+ throw new IOException("File too big");\r
+ int len = (int) size;\r
+ byte data [] = new byte[len];\r
+ int pos = 0;\r
+\r
+ while (pos<size) {\r
+ int read = fis.read(data, pos, len-pos);\r
+ pos += read;\r
+ }\r
+ return data;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Creates and writes a binary file\r
+ * @param file file\r
+ * @param data data\r
+ * @throws IOException on i/o problems\r
+ */\r
+ public static void writeFile(File file, byte[] data)\r
+ throws IOException\r
+ {\r
+// file.createNewFile();\r
+// file.setWritable(true);\r
+ try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {\r
+ raf.setLength(data.length);\r
+ raf.seek(0);\r
+ raf.write(data);\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Fetch the entire contents of the input stream text file, and return it in\r
+ * a String. This style of implementation does not throw Exceptions to the\r
+ * caller.\r
+ * \r
+ * @param stream the stream to completely read in\r
+ */\r
+ public static String getContents(InputStream stream) throws IOException {\r
+ return getContents(stream, Charset.defaultCharset());\r
+ }\r
+\r
+ /**\r
+ * Fetch the entire contents of the input stream text file, and return it in\r
+ * a String. This style of implementation does not throw Exceptions to the\r
+ * caller.\r
+ * \r
+ * @param stream the stream to completely read in\r
+ */\r
+ public static String getContents(InputStream stream, Charset charset, String lineSeparator) throws IOException {\r
+ StringBuilder contents = new StringBuilder();\r
+ BufferedReader input = null;\r
+ try {\r
+ input = new BufferedReader(new InputStreamReader(stream, charset));\r
+\r
+ String line = null;\r
+ while ((line = input.readLine()) != null) {\r
+ contents.append(line);\r
+ contents.append(lineSeparator);\r
+ }\r
+ } finally {\r
+ try {\r
+ if (input != null) {\r
+ // flush and close both "input" and its underlying\r
+ // FileReader\r
+ input.close();\r
+ }\r
+ } catch (IOException ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ return contents.toString();\r
+ }\r
+\r
+ public static String getContents(File f) throws IOException {\r
+ return getContents(f, Charset.defaultCharset());\r
+ }\r
+ \r
+ public static String getContents(File f, Charset charset) throws IOException {\r
+ return getContents(new FileInputStream(f), charset);\r
+ }\r
+\r
+ public static String getContents(InputStream stream, Charset charset) throws IOException {\r
+ return getContents(stream, charset, System.getProperty("line.separator"));\r
+ }\r
+\r
+ public static String getContents(InputStream stream, String lineSeparator) throws IOException {\r
+ return getContents(stream, Charset.defaultCharset(), lineSeparator);\r
+ }\r
+ \r
+ /**\r
+ * Fetch the entire contents of a text file, and return it in a String. This\r
+ * style of implementation does not throw Exceptions to the caller.\r
+ * \r
+ * @param sourcePath is a file which already exists and can be read.\r
+ */\r
+ public static String getContents(String sourcePath) throws IOException {\r
+ return getContents(sourcePath, Charset.defaultCharset(), System.getProperty("line.separator"));\r
+ }\r
+\r
+ public static String getContents(String sourcePath, String lineSeparator) throws IOException {\r
+ return getContents(sourcePath, Charset.defaultCharset(), lineSeparator);\r
+ }\r
+\r
+ public static String getContents(String sourcePath, Charset charset) throws IOException {\r
+ return getContents(sourcePath, charset, System.getProperty("line.separator"));\r
+ }\r
+\r
+ /**\r
+ * Fetch the entire contents of a text file, and return it in a String. This\r
+ * style of implementation does not throw Exceptions to the caller.\r
+ * \r
+ * @param sourcePath is a file which already exists and can be read.\r
+ */\r
+ public static String getContents(String sourcePath, Charset charset, String lineSeparator) throws IOException {\r
+ FileInputStream input = null;\r
+ try {\r
+ input = new FileInputStream(sourcePath);\r
+ return getContents(input, charset, lineSeparator);\r
+ } finally {\r
+ uncheckedClose(input);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the contents of a file which is located inside a given bundle.\r
+ * This works regardless of whether the bundle is jarred or not.\r
+ * \r
+ * @param URL the resource to read in\r
+ * @return the contents of the resource\r
+ * @throws IOException if the file is not found or other io errors occur\r
+ */\r
+ public static String getContents(URL url) throws IOException {\r
+ if (url == null)\r
+ throw new IllegalArgumentException("null URL");\r
+ InputStream input = null;\r
+ try {\r
+ input = url.openStream();\r
+ return FileUtils.getContents(input);\r
+ } finally {\r
+ uncheckedClose(input);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Read a binary file into a java instance. Binary file is a variant, \r
+ * there is a filetype in the header of the file. \r
+ * If requested binding is not the exact binding of the file, an adapter is tried.\r
+ * \r
+ * @param file file\r
+ * @param binding content binding\r
+ * @return instance\r
+ * @throws IOException \r
+ */\r
+ public static Object readFile(InputStream stream, Binding binding) throws IOException {\r
+ Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );\r
+ Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( stream );\r
+\r
+ if (type.equals(binding.type())) {\r
+ return Bindings.getSerializerUnchecked( binding ).deserialize(stream);\r
+ } else {\r
+ try {\r
+ Binding fileContentBinding = Bindings.getMutableBinding(type);\r
+ Adapter adapter = Bindings.adapterFactory.getAdapter(fileContentBinding, binding, true, false);\r
+ Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(stream);\r
+ return adapter.adapt( value );\r
+ } catch (AdapterConstructionException e) {\r
+ throw new IOException(e);\r
+ } catch (AdaptException e) {\r
+ throw new IOException(e);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Deletes all files and sub-directories from the specified directory. If a\r
+ * file is specified, only that fill will be deleted.\r
+ * \r
+ * @param dir\r
+ * @throws IOException\r
+ */\r
+ public static void deleteAll(File dir) throws IOException {\r
+ if (dir.isFile()) {\r
+ dir.delete();\r
+ return;\r
+ }\r
+\r
+ if (dir.isDirectory()) {\r
+ File[] fs = dir.listFiles((FileFilter) null);\r
+ if (fs == null)\r
+ return;\r
+\r
+ for (File f : fs) {\r
+ if (f.isDirectory()) {\r
+ deleteAll(f);\r
+ } else {\r
+ if (!f.delete()) {\r
+ throw new IOException("Could not delete file: " + f.getAbsolutePath());\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!dir.delete()) {\r
+ throw new IOException("Could not delete directory: " + dir.getAbsolutePath());\r
+ }\r
+ } else if (dir.exists()) {\r
+ if (!dir.delete()) {\r
+ throw new IOException("Could not delete file: " + dir.getAbsolutePath());\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Deletes all files and sub-directories from the specified directory. If a\r
+ * file is specified, only that fill will be deleted.\r
+ * \r
+ * If the given directory contains files listed in the filter those files are not deleted\r
+ * \r
+ * @param dir\r
+ * directory from where to start the deletion \r
+ * @param filter\r
+ * filter containing specific file paths not to delete\r
+ * @throws IOException\r
+ */\r
+ public static void deleteAllWithFilter(File dir, ArrayList<String> filter) throws IOException {\r
+ if (dir.isFile()) {\r
+ if (!filter.contains(dir.getAbsolutePath())) {\r
+ dir.delete();\r
+ return; \r
+ }\r
+ }\r
+\r
+ if (dir.isDirectory()) {\r
+ File[] fs = dir.listFiles((FileFilter) null);\r
+ if (fs == null)\r
+ return;\r
+\r
+ for (File f : fs) {\r
+ if (f.isDirectory()) {\r
+ deleteAllWithFilter(f, filter);\r
+ } else {\r
+ if (!filter.contains(f.getAbsolutePath())) {\r
+ if (!f.delete()) {\r
+ throw new IOException("Could not delete file: " + f.getAbsolutePath());\r
+ } \r
+ }\r
+ }\r
+ }\r
+ if (!filter.contains(dir.getAbsolutePath())) {\r
+ if (!dir.delete()) {\r
+ throw new IOException("Could not delete directory: " + dir.getAbsolutePath());\r
+ } \r
+ }\r
+ } else if (dir.exists()) {\r
+ if (filter.contains(dir.getAbsolutePath())) {\r
+ if (!dir.delete()) {\r
+ throw new IOException("Could not delete file: " + dir.getAbsolutePath());\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ public static ArrayList<String> createFileFilter(File dir, ArrayList<String> filter) {\r
+ if (filter == null)\r
+ filter = new ArrayList<String>();\r
+ if (dir.isFile()) {\r
+ filter.add(dir.getAbsolutePath());\r
+ return filter;\r
+ }\r
+ \r
+ if (dir.isDirectory()) {\r
+ File[] fs = dir.listFiles((FileFilter) null);\r
+ if (fs == null)\r
+ return filter;\r
+\r
+ for (File f : fs) {\r
+ if (f.isDirectory()) {\r
+ createFileFilter(f, filter);\r
+ } else {\r
+ filter.add(f.getAbsolutePath());\r
+ }\r
+ }\r
+ filter.add(dir.getAbsolutePath());\r
+ } else if (dir.exists()) {\r
+ filter.add(dir.getAbsolutePath());\r
+ }\r
+ return filter;\r
+ }\r
+\r
+\r
+ /**\r
+ * Delete a directory incl. all files and sub-directories by best effort.\r
+ * Does not throw exceptions if deletion fails, simply tries to delete the\r
+ * provided directory to the best of Java File API's abilities.\r
+ * \r
+ * @param dir\r
+ * directory to delete recursively\r
+ * @boolean <code>true</code> if all files were successfully deleted,\r
+ * <code>false</code> if some or all failed to be deleted\r
+ */\r
+ public static boolean deleteDir(File dir) {\r
+ Logger myLogger = Logger.getLogger(FileUtils.class);\r
+ myLogger.debug("Deleting directory "+dir);\r
+ boolean result = true;\r
+\r
+ if (!dir.isDirectory()) return false;\r
+ File[] fs = dir.listFiles();\r
+ if (fs != null) {\r
+ for (File f : fs) {\r
+ if (f.isDirectory()) result &= deleteDir(f);\r
+ if (f.isFile()) result &= f.delete();\r
+ }\r
+ }\r
+ boolean ok = dir.delete();\r
+// if (!ok) dir.deleteOnExit();\r
+ result &= ok;\r
+ return result;\r
+ }\r
+ \r
+ public static String deleteDirs(File dir) { \r
+ Logger myLogger = Logger.getLogger(FileUtils.class);\r
+ myLogger.debug("Deleting directory "+dir);\r
+ boolean result = true;\r
+\r
+ if (!dir.isDirectory()) \r
+ return dir + " is not a directory!";\r
+ File[] fs = dir.listFiles();\r
+ if (fs != null) {\r
+ for (File f : fs) {\r
+ //System.out.println("file f :" + f);\r
+ if (f.isDirectory()) { \r
+ boolean a = deleteDir(f);\r
+ result &= a;\r
+ }\r
+ if (f.isFile()) {\r
+ boolean a = f.delete();\r
+ result &= a;\r
+ }\r
+ \r
+ }\r
+ }\r
+ boolean ok = dir.delete();\r
+// if (!ok) dir.deleteOnExit();\r
+ result &= ok;\r
+ return "deleteDirs succesful for " + dir + " : " + result;\r
+ }\r
+\r
+ /**\r
+ * Closes a stream and ignores any resulting exception. This is useful\r
+ * when doing stream cleanup in a finally block where secondary exceptions\r
+ * are not worth logging.\r
+ */\r
+ public static void uncheckedClose(Closeable closeable) {\r
+ try {\r
+ if (closeable != null)\r
+ closeable.close();\r
+ } catch (IOException e) {\r
+ //ignore\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Extracts the specified source file in the specified bundle into the\r
+ * specified local directory.\r
+ * \r
+ * @param url the source URL to stream the resource from\r
+ * @param targetFile the target file to write the resource to\r
+ * @param deleteOnExit <code>true</code> to use {@link File#deleteOnExit()}\r
+ * on the resulting file. Note that this does not guarantee that the\r
+ * file is deleted when the JVM exits\r
+ * @return the resulting file\r
+ * @throws FileNotFoundException\r
+ */\r
+ public static File copyResource(URL url, File targetFile, boolean deleteOnExit) throws IOException, FileNotFoundException {\r
+ if (url == null)\r
+ throw new IllegalArgumentException("null url");\r
+\r
+ FileOutputStream os = null;\r
+ InputStream is = null;\r
+ try {\r
+ if (targetFile.exists())\r
+ targetFile.delete();\r
+\r
+ is = url.openStream();\r
+ int read;\r
+ byte [] buffer = new byte [16384];\r
+ os = new FileOutputStream (targetFile);\r
+ while ((read = is.read (buffer)) != -1) {\r
+ os.write(buffer, 0, read);\r
+ }\r
+ os.close ();\r
+ is.close ();\r
+\r
+ // Request removal of the extracted files on JVM exit.\r
+ if (deleteOnExit)\r
+ targetFile.deleteOnExit();\r
+ return targetFile;\r
+ } finally {\r
+ FileUtils.uncheckedClose(os);\r
+ FileUtils.uncheckedClose(is);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Creates the requested location under the system's temporary directories\r
+ * for temporary data storage.\r
+ * \r
+ * @param pathSegments the path segments that are appended to\r
+ * java.io.tmpdir. The path segments musn't contain path separators.\r
+ * @return the resulting temporary directory as a File object\r
+ * @throws IOException if anything goes wrong\r
+ */\r
+ public static File getOrCreateTemporaryDirectory(boolean requireEmptyDirectory, String... pathSegments) throws IOException {\r
+ String separator = System.getProperty("file.separator");\r
+ String tempDir = System.getProperty("java.io.tmpdir");\r
+ if (tempDir == null)\r
+ throw new IllegalStateException("'java.io.tmpdir' property is not defined, is the system TMP environment variable defined?");\r
+\r
+ if (!hasTrailingSeparator(tempDir))\r
+ tempDir = tempDir + separator;\r
+\r
+ for (int i = 0; i < pathSegments.length-1; ++i) {\r
+ if (containsSeparator(pathSegments[i]))\r
+ throw new IllegalArgumentException("path segments contain path separators: " + Arrays.toString(pathSegments));\r
+ tempDir = pathSegments[i] + separator;\r
+ }\r
+\r
+ // Find name for an empty or non-existing temporary directory\r
+ if (pathSegments.length > 0) {\r
+ String lastSegment = pathSegments[pathSegments.length - 1];\r
+ String suffix = "";\r
+ int counter = 0;\r
+ // This loop will not exit until it succeeds or some error occurs.\r
+ while (true) {\r
+ File temp = new File(tempDir + lastSegment + suffix);\r
+\r
+ if (!temp.exists()) {\r
+ // Found non-existent temporary directory!\r
+ if (temp.mkdirs()) {\r
+ // Ok, everything seems to be fine.\r
+ return temp;\r
+ }\r
+ // For some reason the directory could not be created, lets\r
+ // try another name.\r
+ } else {\r
+ // Found an existing temporary file.\r
+ if (temp.isDirectory() && temp.canWrite()) {\r
+ if (requireEmptyDirectory) {\r
+ String[] files = temp.list();\r
+ if (files != null) {\r
+ if (files.length == 0) {\r
+ // Ok, the directory is empty and writable.\r
+ return temp;\r
+ }\r
+ }\r
+ } else {\r
+ return temp;\r
+ }\r
+ // Either the directory was empty or it could not be\r
+ // checked. In any case, don't use the directory.\r
+ }\r
+ }\r
+\r
+ // Try another directory name if no success with this one.\r
+ suffix = Integer.toHexString(counter);\r
+ ++counter;\r
+ }\r
+ }\r
+ return new File(tempDir);\r
+ }\r
+\r
+ private static boolean containsSeparator(String s) {\r
+ return s.contains("/") || s.contains("\\");\r
+ }\r
+\r
+ private static boolean hasTrailingSeparator(String s) {\r
+ return s.endsWith("/") || s.endsWith("\\");\r
+ }\r
+\r
+ /**\r
+ * Very simple compression using ZLib\r
+ * @param input the uncompressed data\r
+ * @return the compressed data\r
+ */\r
+ public static byte[] deflate(byte[] input) {\r
+ // Compress the bytes\r
+ Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);\r
+ compresser.setInput(input);\r
+ compresser.finish();\r
+\r
+ int bufferSize = input.length<16 ? 16 : input.length;\r
+ byte buffer[] = new byte[bufferSize];\r
+ int bufferPos = 0;\r
+ do {\r
+ int compressedDataLength = compresser.deflate(buffer, bufferPos, buffer.length-bufferPos);\r
+ bufferPos += compressedDataLength;\r
+ if (!compresser.finished())\r
+ buffer = Arrays.copyOf(buffer, buffer.length + bufferSize);\r
+ } while (!compresser.finished());\r
+\r
+ byte[] result = new byte[bufferPos+4];\r
+ System.arraycopy(buffer, 0, result, 4, bufferPos);\r
+ byte sizeData[] = LEInt.toBytes(input.length);\r
+ System.arraycopy(sizeData, 0, result, 0, 4);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Very simple decompression using ZLib.\r
+ * @param input the compressed input\r
+ * @return the uncompressed data\r
+ * @throws DataFormatException\r
+ */\r
+ public static byte[] inflate(byte[] input) throws DataFormatException {\r
+ // Decompress the bytes\r
+ int inflatedSize = LEInt.toInt(input);\r
+ Inflater decompresser = new Inflater();\r
+ decompresser.setInput(input, 4, input.length - 4);\r
+ byte[] result = new byte[inflatedSize];\r
+ int resultLength = decompresser.inflate(result);\r
+ assert(resultLength == inflatedSize);\r
+ decompresser.end();\r
+ return result;\r
+ }\r
+\r
+\r
+ public static boolean isValidFileName(String name) {\r
+ File f = new File(name) ;\r
+ if (!f.exists()) {\r
+ try {\r
+ boolean ok = f.createNewFile();\r
+ if (ok)\r
+ f.delete();\r
+ return ok;\r
+ } catch (IOException ioe) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Create a temporary directory\r
+ * \r
+ * @return temporary directory\r
+ */\r
+ public static File createTmpDir()\r
+ {\r
+ String tmp = System.getenv("tmp");\r
+ if (tmp==null) tmp = "c:/temp";\r
+ Random r = new Random();\r
+ String randomName = "simantics-tmp-"+(r.nextInt(10000)+10000);\r
+ File tmpDir = new File(tmp+"/"+randomName);\r
+ tmpDir.deleteOnExit();\r
+ Boolean ok = tmpDir.mkdirs();\r
+ if (!ok) throw new RuntimeException("tmp dir "+tmpDir+" was not created");\r
+ return tmpDir;\r
+ }\r
+ \r
+ public static void compressZip(String sourcePath, String zipDir) throws IOException {\r
+ Logger myLogger = Logger.getLogger(FileUtils.class);\r
+ myLogger.debug("Compressing file " + sourcePath + " to zip " + zipDir + ".");\r
+\r
+ System.out.println("Compressing file " + sourcePath + " to zip " + zipDir + ".");\r
+\r
+ File filesource = new File(sourcePath);\r
+ URI base = filesource.toURI();\r
+ Deque<File> queue = new LinkedList<File>();\r
+ queue.push(filesource);\r
+ try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipDir))) {\r
+ while (!queue.isEmpty()) {\r
+ filesource = queue.pop();\r
+ for (File child : filesource.listFiles()) {\r
+ String name = base.relativize(child.toURI()).getPath();\r
+ if (child.isDirectory()) {\r
+ queue.push(child);\r
+ name = name.endsWith("/") ? name : name + "/";\r
+ zout.putNextEntry(new ZipEntry(name));\r
+ } else {\r
+ zout.putNextEntry(new ZipEntry(name));\r
+ copy(child, zout);\r
+ zout.closeEntry();\r
+ }\r
+ }\r
+ }\r
+ } finally {\r
+ myLogger.debug("Filecompression done.");\r
+ System.out.println("Filecompression done.");\r
+ }\r
+ }\r
+\r
+ private static void copy(File file, ZipOutputStream zout) throws IOException {\r
+ try (InputStream in = new FileInputStream(file)) {\r
+ copy(in, zout);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Extract a zip file into a directory\r
+ * \r
+ * @param zipFile\r
+ * @param dst\r
+ * @throws IOException\r
+ */\r
+ public static void extractZip(File zipFile, File dst) throws IOException {\r
+ Logger myLogger = Logger.getLogger(FileUtils.class);\r
+ myLogger.debug("Extracting zip "+zipFile);\r
+ try (FileInputStream fis = new FileInputStream(zipFile)) {\r
+ extractZip(fis, dst);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Extract a zip file into a directory\r
+ * \r
+ * @param zipInput\r
+ * @param dst directory\r
+ * @throws IOException\r
+ */\r
+ public static void extractZip(InputStream zipInput, File dst) throws IOException {\r
+ Logger myLogger = Logger.getLogger(FileUtils.class);\r
+ byte[] buf = new byte[8192];\r
+ ZipInputStream zis = new ZipInputStream(zipInput);\r
+ ZipEntry entry;\r
+\r
+ entry = zis.getNextEntry();\r
+ while (entry != null) {\r
+ // for each entry to be extracted\r
+ String name = entry.getName();\r
+ myLogger.debug("Extracting "+name);\r
+ File file = new File(dst, name);\r
+\r
+ if (entry.isDirectory())\r
+ {\r
+ if ( !file.exists() ) file.mkdirs();\r
+ } else {\r
+ File parent = file.getParentFile();\r
+ if (!parent.exists()) parent.mkdirs();\r
+ if (!file.exists()) file.createNewFile();\r
+\r
+ FileOutputStream fileoutputstream = new FileOutputStream(file);\r
+ try {\r
+ int n = 0;\r
+ while ((n = zis.read(buf, 0, buf.length)) > -1)\r
+ fileoutputstream.write(buf, 0, n);\r
+ } catch (ZipException e) {\r
+ throw new IOException("Failed to extract '" + name + "'.", e);\r
+ } finally {\r
+ fileoutputstream.close();\r
+ }\r
+ }\r
+\r
+ zis.closeEntry();\r
+ entry = zis.getNextEntry();\r
+ }// while\r
+\r
+ zis.close();\r
+ }\r
+\r
+ // Test inflate & deflate\r
+ public static void main(String[] args) {\r
+ try {\r
+ // Test compression\r
+ String str = "abcdefghijklmnopqrstuvwxyz";\r
+ byte data[] = str.getBytes();\r
+ System.out.println("Data:\t"+data.length);\r
+ byte deflated[] = deflate(data);\r
+ System.out.println("Deflated:\t"+deflated.length);\r
+ byte inflated[] = inflate(deflated);\r
+ System.out.println("Inflated:\t"+inflated.length);\r
+ String str2 = new String(inflated);\r
+ System.out.println("Strings are equal: "+str.endsWith(str2));\r
+ } catch (DataFormatException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public static File[] listFilesByExtension(File directory, final String extension) {\r
+ return directory.listFiles(new ExtensionFilter(extension));\r
+ }\r
+ \r
+ /**\r
+ * Copy the content of the input stream into the output stream, using a temporary\r
+ * byte array buffer whose size is defined by {@link #IO_BUFFER_SIZE}.\r
+ *\r
+ * @param in The input stream to copy from.\r
+ * @param out The output stream to copy to.\r
+ *\r
+ * @throws IOException If any error occurs during the copy.\r
+ */\r
+ private static final int IO_BUFFER_SIZE = 64 * 1024;\r
+\r
+ public static void copy(InputStream in, OutputStream out) throws IOException {\r
+ byte[] b = new byte[IO_BUFFER_SIZE];\r
+ int read;\r
+ while (true) {\r
+ read = in.read(b);\r
+ if (read < 0)\r
+ break;\r
+ out.write(b, 0, read);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param in\r
+ * @param out\r
+ * @param maxBytesToCopy the maximum amount of bytes to copy\r
+ * @return the amount of bytes copied\r
+ * @throws IOException\r
+ */\r
+ public static long copy(InputStream in, OutputStream out, long maxBytesToCopy) throws IOException {\r
+ byte[] b = new byte[IO_BUFFER_SIZE];\r
+ int read = 0;\r
+ while (read < maxBytesToCopy) {\r
+ int l = (int) Math.min((long) IO_BUFFER_SIZE, maxBytesToCopy-read);\r
+ int r = in.read(b, 0, l);\r
+ if (r < 0)\r
+ break;\r
+ out.write(b, 0, r);\r
+ read += r;\r
+ }\r
+ return read;\r
+ }\r
+\r
+ public static void delete(Path databaseLocation) throws IOException {\r
+ Files.walkFileTree(databaseLocation, new DeleteDirectoriesVisitor());\r
+ }\r
+ \r
+ public static void copy(Path from, Path to) throws IOException {\r
+ Files.walkFileTree(from, new CopyDirectoriesVisitor(from, to));\r
+ }\r
+ \r
+ public static class DeleteDirectoriesVisitor extends SimpleFileVisitor<Path> {\r
+ \r
+ @Override\r
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {\r
+ Files.delete(file);\r
+ if (Files.exists(file))\r
+ throw new IOException("Could not delete file " + file.toAbsolutePath().toString());\r
+ return FileVisitResult.CONTINUE;\r
+ }\r
+ \r
+ @Override\r
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {\r
+ if (exc != null)\r
+ throw exc;\r
+ Files.delete(dir);\r
+ if (Files.exists(dir))\r
+ throw new IOException("Could not delete file " + dir.toAbsolutePath().toString());\r
+ return FileVisitResult.CONTINUE;\r
+ }\r
+ }\r
+ \r
+ public static class CopyDirectoriesVisitor extends SimpleFileVisitor<Path> {\r
+ \r
+ private final Path fromPath;\r
+ private final Path toPath;\r
+ \r
+ public CopyDirectoriesVisitor(Path fromPath, Path toPath) {\r
+ this.fromPath = fromPath;\r
+ this.toPath = toPath;\r
+ }\r
+ \r
+ @Override\r
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {\r
+ Path targetPath = toPath.resolve(fromPath.relativize(dir));\r
+ if(!Files.exists(targetPath)){\r
+ Files.createDirectory(targetPath);\r
+ }\r
+ return FileVisitResult.CONTINUE;\r
+ }\r
+\r
+ @Override\r
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {\r
+ Files.copy(file, toPath.resolve(fromPath.relativize(file)), StandardCopyOption.REPLACE_EXISTING);\r
+ return FileVisitResult.CONTINUE;\r
+ }\r
+ }\r
+}\r