diff options
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java | 127 | ||||
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOVisitor.java | 22 | ||||
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/NIOUtil.java | 136 | ||||
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TMPUtil.java (renamed from plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TempUtil.java) | 4 | ||||
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ZIPUtil.java | 303 |
5 files changed, 590 insertions, 2 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java index fc6e517f96..3ed92ac5ea 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; /** * @author Eike Stepper @@ -226,6 +228,80 @@ public final class IOUtil } } + public static List<File> listDepthFirst(File file) + { + FileCollector collector = new FileCollector(); + visitDepthFirst(file, collector); + return collector.getFiles(); + } + + public static List<File> listBreadthFirst(File file) + { + FileCollector collector = new FileCollector(); + visitBreadthFirst(file, collector); + return collector.getFiles(); + } + + public static void visitDepthFirst(File file, IOVisitor visitor) throws IORuntimeException + { + try + { + boolean recurse = visitor.visit(file); + if (recurse && file.isDirectory()) + { + visitDepthFirst(file.listFiles(), visitor); + } + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + } + + public static void visitDepthFirst(File[] files, IOVisitor visitor) + { + for (File file : files) + { + visitDepthFirst(file, visitor); + } + } + + public static void visitBreadthFirst(File file, IOVisitor visitor) throws IORuntimeException + { + File[] files = { file }; + visitBreadthFirst(files, visitor); + } + + public static void visitBreadthFirst(File[] files, IOVisitor visitor) throws IORuntimeException + { + try + { + boolean[] recurse = new boolean[files.length]; + for (int i = 0; i < files.length; i++) + { + File file = files[i]; + recurse[i] = visitor.visit(file); + } + + for (int i = 0; i < files.length; i++) + { + File file = files[i]; + if (file.isDirectory() && recurse[i]) + { + File[] children = file.listFiles(); + for (File child : children) + { + visitBreadthFirst(child, visitor); + } + } + } + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + } + public static void safeRun(Closeable io, IORunnable runnable) throws IORuntimeException { try @@ -287,4 +363,55 @@ public final class IOUtil throw new IORuntimeException(ex); } } + + public static boolean equals(File file1, File file2) throws IORuntimeException + { + if (file1.length() != file2.length()) + { + return false; + } + + FileInputStream stream1 = null; + FileInputStream stream2 = null; + + try + { + stream1 = new FileInputStream(file1); + stream2 = new FileInputStream(file2); + + return equals(stream1, stream2); + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + finally + { + closeSilent(stream1); + closeSilent(stream2); + } + } + + /** + * @author Eike Stepper + */ + public static class FileCollector implements IOVisitor + { + private List<File> files = new ArrayList(); + + public FileCollector() + { + } + + public List<File> getFiles() + { + return files; + } + + public boolean visit(File file) throws IOException + { + files.add(file); + return true; + } + } } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOVisitor.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOVisitor.java new file mode 100644 index 0000000000..3f31db5385 --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOVisitor.java @@ -0,0 +1,22 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2007 Eike Stepper, Germany. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + **************************************************************************/ +package org.eclipse.net4j.util.io; + +import java.io.File; +import java.io.IOException; + +/** + * @author Eike Stepper + */ +public interface IOVisitor +{ + public boolean visit(File file) throws IOException; +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/NIOUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/NIOUtil.java index 1de881a926..23167f3ea2 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/NIOUtil.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/NIOUtil.java @@ -27,8 +27,13 @@ public final class NIOUtil { } + /** + * TODO Look at {@link #copy(File, File, boolean)} + */ public static void copyFile(File source, File target) { + // http://www.javalobby.org/java/forums/t17036.html + // http://java.sun.com/developer/JDCTechTips/2002/tt0507.html#tip1 FileChannel sourceChannel = null; FileChannel targetChannel = null; @@ -59,4 +64,135 @@ public final class NIOUtil IOUtil.closeSilent(targetChannel); } } + + /** + * Copy source file to destination. If destination is a path then source file + * name is appended. If destination file exists then: overwrite=true - + * destination file is replaced; overwite=false - exception is thrown. + * + * @param src + * source file + * @param dst + * destination file or path + * @param overwrite + * overwrite destination file + * @exception IOException + * I/O problem + * @exception IllegalArgumentException + * illegal argument + */ + @SuppressWarnings("unused") + private static void copy(final File src, File dst, final boolean overwrite) throws IOException, + IllegalArgumentException + { + long q = System.currentTimeMillis(); + // checks + if (!src.isFile() || !src.exists()) + throw new IllegalArgumentException("Source file '" + src.getAbsolutePath() + "' not found!"); + if (dst.exists()) + if (dst.isDirectory()) // Directory? -> use source file name + dst = new File(dst, src.getName()); + else if (dst.isFile()) + { + if (!overwrite) + throw new IllegalArgumentException("Destination file '" + dst.getAbsolutePath() + "' already exists!"); + } + else + throw new IllegalArgumentException("Invalid destination object '" + dst.getAbsolutePath() + "'!"); + File dstParent = dst.getParentFile(); + if (!dstParent.exists()) + if (!dstParent.mkdirs()) + throw new IOException("Failed to create directory " + dstParent.getAbsolutePath()); + long fileSize = src.length(); + if (fileSize > 20971520l) + { // for larger files (20Mb) use streams + FileInputStream in = new FileInputStream(src); + FileOutputStream out = new FileOutputStream(dst); + try + { + int doneCnt = -1, bufSize = 32768; + byte buf[] = new byte[bufSize]; + while ((doneCnt = in.read(buf, 0, bufSize)) >= 0) + if (doneCnt == 0) + Thread.yield(); + else + out.write(buf, 0, doneCnt); + out.flush(); + } + finally + { + try + { + in.close(); + } + catch (IOException e) + { + } + + try + { + out.close(); + } + catch (IOException e) + { + } + } + } + else + { // smaller files, use channels + FileInputStream fis = new FileInputStream(src); + FileOutputStream fos = new FileOutputStream(dst); + FileChannel in = fis.getChannel(), out = fos.getChannel(); + + try + { + long offs = 0, doneCnt = 0, copyCnt = Math.min(65536, fileSize); + do + { + doneCnt = in.transferTo(offs, copyCnt, out); + offs += doneCnt; + fileSize -= doneCnt; + } + + while (fileSize > 0); + } + finally + { // cleanup + try + { + in.close(); + } + catch (IOException e) + { + } + + try + { + out.close(); + } + catch (IOException e) + { + } + + try + { + fis.close(); + } + catch (IOException e) + { + } + + try + { + fos.close(); + } + catch (IOException e) + { + } + } + } // else + + System.out.println(">>> " + String.valueOf(src.length() / 1024) + " Kb, " + + String.valueOf(System.currentTimeMillis() - q)); + } // copy } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TempUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TMPUtil.java index 4f82c2a353..cc1d3317bf 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TempUtil.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/TMPUtil.java @@ -16,9 +16,9 @@ import java.io.IOException; /** * @author Eike Stepper */ -public final class TempUtil +public final class TMPUtil { - private TempUtil() + private TMPUtil() { } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ZIPUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ZIPUtil.java new file mode 100644 index 0000000000..fe0559f0c6 --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ZIPUtil.java @@ -0,0 +1,303 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2007 Eike Stepper, Germany. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + **************************************************************************/ +package org.eclipse.net4j.util.io; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * @author Eike Stepper + */ +public final class ZIPUtil +{ + public static final int DEFALULT_BUFFER_SIZE = 4096; + + private ZIPUtil() + { + } + + public static void zip(File zipFile, ZipEntryHandler handler) throws IORuntimeException + { + final byte[] buffer = new byte[DEFALULT_BUFFER_SIZE]; + final EntryContext context = new EntryContext(); + + FileOutputStream fos = IOUtil.openOutputStream(zipFile); + ZipOutputStream zos = null; + InputStream input = null; + + try + { + zos = new ZipOutputStream(new BufferedOutputStream(fos, DEFALULT_BUFFER_SIZE)); + for (;;) + { + handler.handleEntry(context); + if (context.isEmpty()) + { + break; + } + + String name = context.getName(); + ZipEntry entry = new ZipEntry(name); + zos.putNextEntry(entry); + + if (!context.isDirectory()) + { + try + { + input = context.getInputStream(); + IOUtil.copy(input, zos, buffer); + } + finally + { + IOUtil.closeSilent(input); + } + } + + context.reset(); + } + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + finally + { + IOUtil.closeSilent(zos); + IOUtil.closeSilent(fos); + } + } + + public static void zip(File zipFile, File sourceFolder, boolean excludeRoot) + { + zip(zipFile, new FileSystemZipHandler(sourceFolder, excludeRoot)); + } + + public static void main(String[] args) throws Exception + { + File zipFile = new File("C:\\org.eclipse.emf.ecore_2.3.1.v200707242120.zip"); + File targetFolder = new File("C:\\_weaver\\org.eclipse.emf.ecore_2.3.1.unzipped"); + unzip(zipFile, targetFolder); + + zip(new File("C:\\_weaver\\org.eclipse.emf.ecore_2.3.1.jar"), targetFolder, true); + } + + public static void unzip(File zipFile, UnzipHandler handler) throws IORuntimeException + { + FileInputStream fis = IOUtil.openInputStream(zipFile); + ZipInputStream zis = null; + + try + { + zis = new ZipInputStream(new BufferedInputStream(fis, DEFALULT_BUFFER_SIZE)); + + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) + { + if (entry.isDirectory()) + { + handler.unzipDirectory(entry.getName()); + } + else + { + // TODO Provide delegating InputStream that ignores close() + handler.unzipFile(entry.getName(), zis); + } + } + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + finally + { + IOUtil.closeSilent(zis); + IOUtil.closeSilent(fis); + } + } + + public static void unzip(File zipFile, File targetFolder) throws IORuntimeException + { + unzip(zipFile, new FileSystemUnzipHandler(targetFolder, DEFALULT_BUFFER_SIZE)); + } + + /** + * @author Eike Stepper + */ + public interface ZipEntryHandler + { + public void handleEntry(EntryContext context) throws IOException; + } + + /** + * @author Eike Stepper + */ + public interface UnzipHandler + { + public void unzipDirectory(String name) throws IOException; + + public void unzipFile(String name, InputStream zipStream) throws IOException; + } + + /** + * @author Eike Stepper + */ + public static final class EntryContext + { + private static final String EMPTY = new String(); + + private String name = EMPTY; + + private InputStream inputStream; + + EntryContext() + { + } + + void reset() + { + name = null; + inputStream = null; + } + + boolean isEmpty() + { + return name == null; + } + + boolean isDirectory() + { + return inputStream == null; + } + + String getName() + { + if (isDirectory()) + { + return name; + } + + return name + "/"; + } + + InputStream getInputStream() + { + return inputStream; + } + + public void setName(String name) + { + this.name = name; + } + + public void setInputStream(InputStream inputStream) + { + this.inputStream = inputStream; + } + } + + /** + * @author Eike Stepper + */ + public static final class FileSystemZipHandler implements ZipEntryHandler + { + private int sourceFolderLength; + + private transient Iterator<File> files; + + public FileSystemZipHandler(File sourceFolder, boolean excludeRoot) + { + sourceFolderLength = sourceFolder.getAbsolutePath().length(); + files = IOUtil.listBreadthFirst(sourceFolder).iterator(); + if (excludeRoot) + { + files.next(); + } + } + + public void handleEntry(EntryContext context) throws IOException + { + if (files.hasNext()) + { + File file = files.next(); + context.setName(getName(file)); + + if (file.isFile()) + { + context.setInputStream(IOUtil.openInputStream(file)); + } + } + } + + protected String getName(File file) + { + return file.getAbsolutePath().substring(sourceFolderLength); + } + } + + /** + * @author Eike Stepper + */ + public static final class FileSystemUnzipHandler implements UnzipHandler + { + private File targetFolder; + + private transient byte[] buffer; + + public FileSystemUnzipHandler(File targetFolder, int bufferSize) + { + this.targetFolder = targetFolder; + buffer = new byte[bufferSize]; + } + + public File getTargetFolder() + { + return targetFolder; + } + + public void unzipDirectory(String name) + { + File directory = new File(targetFolder, name); + if (!directory.exists()) + { + directory.mkdirs(); + } + } + + public void unzipFile(String name, InputStream zipStream) + { + File targetFile = new File(targetFolder, name); + if (!targetFile.getParentFile().exists()) + { + targetFile.getParentFile().mkdirs(); + } + + FileOutputStream out = IOUtil.openOutputStream(targetFile); + + try + { + IOUtil.copy(zipStream, out, buffer); + } + finally + { + IOUtil.closeSilent(out); + } + } + } +} |