6990846: Demo: NIO.2 filesystem provider for zip/jar archives
The first drop of the zip filesystem provider, as a separate demo Reviewed-by: alanb
This commit is contained in:
parent
98a4c7fec4
commit
2d526410d4
@ -31,7 +31,7 @@ BUILDDIR = ..
|
||||
PRODUCT = demos
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
SUBDIRS = jni
|
||||
SUBDIRS = jni nio
|
||||
SUBDIRS_desktop = applets jfc
|
||||
SUBDIRS_management = management
|
||||
SUBDIRS_misc = scripting
|
||||
|
39
jdk/make/mkdemo/nio/Makefile
Normal file
39
jdk/make/mkdemo/nio/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code 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
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for building the jfc demos
|
||||
#
|
||||
|
||||
BUILDDIR = ../..
|
||||
PRODUCT = demos
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
SUBDIRS = zipfs
|
||||
include $(BUILDDIR)/common/Subdirs.gmk
|
||||
|
||||
all build clean clobber::
|
||||
$(SUBDIRS-loop)
|
||||
|
44
jdk/make/mkdemo/nio/zipfs/Makefile
Normal file
44
jdk/make/mkdemo/nio/zipfs/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code 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
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile to build the ZipFileSystem demo.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../..
|
||||
PRODUCT = demo/zipfs
|
||||
DEMONAME = zipfs
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
DEMO_ROOT = $(SHARE_SRC)/demo/nio/$(DEMONAME)
|
||||
DEMO_TOPFILES = ./README.txt
|
||||
DEMO_SRCDIR = $(DEMO_ROOT)
|
||||
DEMO_DESTDIR = $(DEMODIR)/nio/$(DEMONAME)
|
||||
|
||||
#
|
||||
# Demo jar building rules.
|
||||
#
|
||||
include $(BUILDDIR)/common/Demo.gmk
|
||||
|
664
jdk/src/share/demo/nio/zipfs/Demo.java
Normal file
664
jdk/src/share/demo/nio/zipfs/Demo.java
Normal file
@ -0,0 +1,664 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.net.*;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
/*
|
||||
* ZipFileSystem usage demo
|
||||
*
|
||||
* java [-cp .../zipfs.jar:./] Demo action ZipfileName [...]
|
||||
*
|
||||
* To deploy the provider, either copy the zipfs.jar into JDK/JRE
|
||||
* extensions directory or add
|
||||
* <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar
|
||||
* into your class path as showed above.
|
||||
*
|
||||
* @author Xueming Shen
|
||||
*/
|
||||
|
||||
public class Demo {
|
||||
|
||||
static enum Action {
|
||||
rename, // <java Demo rename zipfile src dst>
|
||||
// rename entry src to dst inside zipfile
|
||||
|
||||
movein, // <java Demo movein zipfile src dst>
|
||||
// move an external src file into zipfile
|
||||
// as entry dst
|
||||
|
||||
moveout, // <java Demo moveout zipfile src dst>
|
||||
// move a zipfile entry src out to dst
|
||||
|
||||
copy, // <java Demo copy zipfile src dst>
|
||||
// copy entry src to dst inside zipfile
|
||||
|
||||
copyin, // <java Demo copyin zipfile src dst>
|
||||
// copy an external src file into zipfile
|
||||
// as entry dst
|
||||
|
||||
copyout, // <java Demo copyout zipfile src dst>
|
||||
// copy zipfile entry src" out to file dst
|
||||
|
||||
zzmove, // <java Demo zzmove zfsrc zfdst path>
|
||||
// move entry path/dir from zfsrc to zfdst
|
||||
|
||||
zzcopy, // <java Demo zzcopy zfsrc zfdst path>
|
||||
// copy path from zipfile zfsrc to zipfile
|
||||
// zfdst
|
||||
|
||||
attrs, // <java Demo attrs zipfile path>
|
||||
// printout the attributes of entry path
|
||||
|
||||
attrsspace, // <java Demo attrsspace zipfile path>
|
||||
// printout the storespace attrs of entry path
|
||||
|
||||
setmtime, // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
|
||||
// set the lastModifiedTime of entry path
|
||||
|
||||
lsdir, // <java Demo lsdir zipfile dir>
|
||||
// list dir's direct child files/dirs
|
||||
|
||||
mkdir, // <java Demo mkdir zipfile dir>
|
||||
|
||||
mkdirs, // <java Demo mkdirs zipfile dir>
|
||||
|
||||
rmdirs, // <java Demo rmdirs zipfile dir>
|
||||
|
||||
list, // <java Demo list zipfile [dir]>
|
||||
// recursively list all entries of dir
|
||||
// via DirectoryStream
|
||||
|
||||
tlist, // <java Demo tlist zipfile [dir]>
|
||||
// list with buildDirTree=true
|
||||
|
||||
vlist, // <java Demo vlist zipfile [dir]>
|
||||
// recursively verbose list all entries of
|
||||
// dir via DirectoryStream
|
||||
|
||||
walk, // <java Demo walk zipfile [dir]>
|
||||
// recursively walk all entries of dir
|
||||
// via Files.walkFileTree
|
||||
|
||||
twalk, // <java Demo twalk zipfile [dir]>
|
||||
// walk with buildDirTree=true
|
||||
|
||||
extract, // <java Demo extract zipfile file [...]>
|
||||
|
||||
update, // <java Demo extract zipfile file [...]>
|
||||
|
||||
delete, // <java Demo delete zipfile file [...]>
|
||||
|
||||
add, // <java Demo add zipfile file [...]>
|
||||
|
||||
create, // <java Demo create zipfile file [...]>
|
||||
// create a new zipfile if it doesn't exit
|
||||
// and then add the file(s) into it.
|
||||
|
||||
attrs2, // <java Demo attrs2 zipfile file [...]>
|
||||
// test different ways to print attrs
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
Action action = Action.valueOf(args[0]);;
|
||||
Map<String, Object> env = env = new HashMap<String, Object>();
|
||||
if (action == Action.create)
|
||||
env.put("createNew", true);
|
||||
if (action == Action.tlist || action == Action.twalk)
|
||||
env.put("buildDirTree", true);
|
||||
|
||||
FileSystem fs = FileSystems.newFileSystem(
|
||||
URI.create("zip" + Paths.get(args[1]).toUri().toString().substring(4)),
|
||||
env,
|
||||
null);
|
||||
try {
|
||||
FileSystem fs2;
|
||||
Path path, src, dst;
|
||||
boolean isRename = false;
|
||||
switch (action) {
|
||||
case rename:
|
||||
src = fs.getPath(args[2]);
|
||||
dst = fs.getPath(args[3]);
|
||||
src.moveTo(dst);
|
||||
break;
|
||||
case moveout:
|
||||
src = fs.getPath(args[2]);
|
||||
dst = Paths.get(args[3]);
|
||||
src.moveTo(dst);
|
||||
break;
|
||||
case movein:
|
||||
src = Paths.get(args[2]);
|
||||
dst = fs.getPath(args[3]);
|
||||
src.moveTo(dst);
|
||||
break;
|
||||
case copy:
|
||||
src = fs.getPath(args[2]);
|
||||
dst = fs.getPath(args[3]);
|
||||
src.copyTo(dst);
|
||||
break;
|
||||
case copyout:
|
||||
src = fs.getPath(args[2]);
|
||||
dst = Paths.get(args[3]);
|
||||
src.copyTo(dst);
|
||||
break;
|
||||
case copyin:
|
||||
src = Paths.get(args[2]);
|
||||
dst = fs.getPath(args[3]);
|
||||
src.copyTo(dst);
|
||||
break;
|
||||
case zzmove:
|
||||
fs2 = FileSystems.newFileSystem(
|
||||
URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)),
|
||||
env,
|
||||
null);
|
||||
//sf1.getPath(args[3]).moveTo(fs2.getPath(args[3]));
|
||||
z2zmove(fs, fs2, args[3]);
|
||||
fs2.close();
|
||||
break;
|
||||
case zzcopy:
|
||||
fs2 = FileSystems.newFileSystem(
|
||||
URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)),
|
||||
env,
|
||||
null);
|
||||
//sf1.getPath(args[3]).copyTo(fs2.getPath(args[3]));
|
||||
z2zcopy(fs, fs2, args[3]);
|
||||
fs2.close();
|
||||
break;
|
||||
case attrs:
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
path = fs.getPath(args[i]);
|
||||
System.out.println(
|
||||
Attributes.readBasicFileAttributes(path).toString());
|
||||
}
|
||||
break;
|
||||
case setmtime:
|
||||
DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
|
||||
Date newDatetime = df.parse(args[2]);
|
||||
for (int i = 3; i < args.length; i++) {
|
||||
path = fs.getPath(args[i]);
|
||||
path.setAttribute("lastModifiedTime",
|
||||
FileTime.fromMillis(newDatetime.getTime()));
|
||||
System.out.println(
|
||||
Attributes.readBasicFileAttributes(path).toString());
|
||||
}
|
||||
break;
|
||||
case attrsspace:
|
||||
path = fs.getPath("/");
|
||||
FileStore fstore = path.getFileStore();
|
||||
//System.out.println(fstore.getFileStoreAttributeView(FileStoreSpaceAttributeView.class)
|
||||
// .readAttributes());
|
||||
// or
|
||||
System.out.printf("filestore[%s]%n", fstore.name());
|
||||
System.out.printf(" totalSpace: %d%n",
|
||||
(Long)fstore.getAttribute("space:totalSpace"));
|
||||
System.out.printf(" usableSpace: %d%n",
|
||||
(Long)fstore.getAttribute("space:usableSpace"));
|
||||
System.out.printf(" unallocSpace: %d%n",
|
||||
(Long)fstore.getAttribute("space:unallocatedSpace"));
|
||||
break;
|
||||
case list:
|
||||
case tlist:
|
||||
if (args.length < 3)
|
||||
list(fs.getPath("/"), false);
|
||||
else
|
||||
list(fs.getPath(args[2]), false);
|
||||
break;
|
||||
case vlist:
|
||||
if (args.length < 3)
|
||||
list(fs.getPath("/"), true);
|
||||
else
|
||||
list(fs.getPath(args[2]), true);
|
||||
break;
|
||||
case twalk:
|
||||
case walk:
|
||||
walk(fs.getPath((args.length > 2)? args[2] : "/"));
|
||||
break;
|
||||
case extract:
|
||||
if (args.length == 2) {
|
||||
extract(fs, "/");
|
||||
} else {
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
extract(fs, args[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case delete:
|
||||
for (int i = 2; i < args.length; i++)
|
||||
fs.getPath(args[i]).delete();
|
||||
break;
|
||||
case create:
|
||||
case add:
|
||||
case update:
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
update(fs, args[i]);
|
||||
}
|
||||
break;
|
||||
case lsdir:
|
||||
path = fs.getPath(args[2]);
|
||||
final String fStr = (args.length > 3)?args[3]:"";
|
||||
DirectoryStream<Path> ds = path.newDirectoryStream(
|
||||
new DirectoryStream.Filter<Path>() {
|
||||
public boolean accept(Path path) {
|
||||
return path.toString().contains(fStr);
|
||||
}
|
||||
});
|
||||
for (Path p : ds)
|
||||
System.out.println(p);
|
||||
break;
|
||||
case mkdir:
|
||||
fs.getPath(args[2]).createDirectory();
|
||||
break;
|
||||
case mkdirs:
|
||||
mkdirs(fs.getPath(args[2]));
|
||||
break;
|
||||
case attrs2:
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
path = fs.getPath(args[i]);
|
||||
System.out.println("-------(1)---------");
|
||||
System.out.println(
|
||||
Attributes.readBasicFileAttributes(path).toString());
|
||||
System.out.println("-------(2)---------");
|
||||
Map<String, ?> map = path.readAttributes("zip:*");
|
||||
for (Map.Entry<String, ?> e : map.entrySet()) {
|
||||
System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
|
||||
}
|
||||
System.out.println("-------(3)---------");
|
||||
map = path.readAttributes("size,lastModifiedTime,isDirectory");
|
||||
for (Map.Entry<String, ?> e : map.entrySet()) {
|
||||
System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
} finally {
|
||||
if (fs != null)
|
||||
fs.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getBytes(String name) {
|
||||
return name.getBytes();
|
||||
}
|
||||
|
||||
private static String getString(byte[] name) {
|
||||
return new String(name);
|
||||
}
|
||||
|
||||
private static void walk(Path path) throws IOException
|
||||
{
|
||||
Files.walkFileTree(
|
||||
path,
|
||||
new SimpleFileVisitor<Path>() {
|
||||
private int indent = 0;
|
||||
private void indent() {
|
||||
int n = 0;
|
||||
while (n++ < indent)
|
||||
System.out.printf(" ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
indent();
|
||||
System.out.printf("%s%n", file.getName().toString());
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
indent();
|
||||
System.out.printf("[%s]%n", dir.toString());
|
||||
indent += 2;
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir,
|
||||
IOException ioe)
|
||||
{
|
||||
indent -= 2;
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void update(FileSystem fs, String path) throws Throwable{
|
||||
Path src = FileSystems.getDefault().getPath(path);
|
||||
if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) {
|
||||
DirectoryStream<Path> ds = src.newDirectoryStream();
|
||||
for (Path child : ds)
|
||||
update(fs, child.toString());
|
||||
ds.close();
|
||||
} else {
|
||||
Path dst = fs.getPath(path);
|
||||
Path parent = dst.getParent();
|
||||
if (parent != null && parent.notExists())
|
||||
mkdirs(parent);
|
||||
src.copyTo(dst, REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
private static void extract(FileSystem fs, String path) throws Throwable{
|
||||
Path src = fs.getPath(path);
|
||||
if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) {
|
||||
DirectoryStream<Path> ds = src.newDirectoryStream();
|
||||
for (Path child : ds)
|
||||
extract(fs, child.toString());
|
||||
ds.close();
|
||||
} else {
|
||||
if (path.startsWith("/"))
|
||||
path = path.substring(1);
|
||||
Path dst = FileSystems.getDefault().getPath(path);
|
||||
Path parent = dst.getParent();
|
||||
if (parent.notExists())
|
||||
mkdirs(parent);
|
||||
src.copyTo(dst, REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
// use DirectoryStream
|
||||
private static void z2zcopy(FileSystem src, FileSystem dst, String path)
|
||||
throws IOException
|
||||
{
|
||||
Path srcPath = src.getPath(path);
|
||||
Path dstPath = dst.getPath(path);
|
||||
|
||||
if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
|
||||
if (!dstPath.exists()) {
|
||||
try {
|
||||
mkdirs(dstPath);
|
||||
} catch (FileAlreadyExistsException x) {}
|
||||
}
|
||||
DirectoryStream<Path> ds = srcPath.newDirectoryStream();
|
||||
for (Path child : ds) {
|
||||
z2zcopy(src, dst,
|
||||
path + (path.endsWith("/")?"":"/") + child.getName());
|
||||
}
|
||||
ds.close();
|
||||
} else {
|
||||
//System.out.println("copying..." + path);
|
||||
srcPath.copyTo(dstPath);
|
||||
}
|
||||
}
|
||||
|
||||
// use TreeWalk to move
|
||||
private static void z2zmove(FileSystem src, FileSystem dst, String path)
|
||||
throws IOException
|
||||
{
|
||||
final Path srcPath = src.getPath(path).toAbsolutePath();
|
||||
final Path dstPath = dst.getPath(path).toAbsolutePath();
|
||||
|
||||
Files.walkFileTree(srcPath, new SimpleFileVisitor<Path>() {
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
Path dst = srcPath.relativize(file);
|
||||
dst = dstPath.resolve(dst);
|
||||
try {
|
||||
Path parent = dstPath.getParent();
|
||||
if (parent != null && parent.notExists())
|
||||
mkdirs(parent);
|
||||
file.moveTo(dst);
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
Path dst = srcPath.relativize(dir);
|
||||
dst = dstPath.resolve(dst);
|
||||
try {
|
||||
|
||||
if (dst.notExists())
|
||||
mkdirs(dst);
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir,
|
||||
IOException ioe)
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
dir.delete();
|
||||
} catch (IOException x) {
|
||||
//x.printStackTrace();
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static void mkdirs(Path path) throws IOException {
|
||||
path = path.toAbsolutePath();
|
||||
Path parent = path.getParent();
|
||||
if (parent != null) {
|
||||
if (parent.notExists())
|
||||
mkdirs(parent);
|
||||
}
|
||||
path.createDirectory();
|
||||
}
|
||||
|
||||
private static void rmdirs(Path path) throws IOException {
|
||||
while (path != null && path.getNameCount() != 0) {
|
||||
path.delete();
|
||||
path = path.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
private static void list(Path path, boolean verbose ) throws IOException {
|
||||
if (verbose)
|
||||
System.out.println(Attributes.readBasicFileAttributes(path).toString());
|
||||
else
|
||||
System.out.printf(" %s%n", path.toString());
|
||||
if (path.notExists())
|
||||
return;
|
||||
if (Attributes.readBasicFileAttributes(path).isDirectory()) {
|
||||
DirectoryStream<Path> ds = path.newDirectoryStream();
|
||||
for (Path child : ds)
|
||||
list(child, verbose);
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
// check the content of two paths are equal
|
||||
private static void checkEqual(Path src, Path dst) throws IOException
|
||||
{
|
||||
//System.out.printf("checking <%s> vs <%s>...%n",
|
||||
// src.toString(), dst.toString());
|
||||
|
||||
//streams
|
||||
InputStream isSrc = src.newInputStream();
|
||||
InputStream isDst = dst.newInputStream();
|
||||
byte[] bufSrc = new byte[8192];
|
||||
byte[] bufDst = new byte[8192];
|
||||
|
||||
try {
|
||||
int nSrc = 0;
|
||||
while ((nSrc = isSrc.read(bufSrc)) != -1) {
|
||||
int nDst = 0;
|
||||
while (nDst < nSrc) {
|
||||
int n = isDst.read(bufDst, nDst, nSrc - nDst);
|
||||
if (n == -1) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nDst += n;
|
||||
}
|
||||
while (--nSrc >= 0) {
|
||||
if (bufSrc[nSrc] != bufDst[nSrc]) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nSrc--;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
isSrc.close();
|
||||
isDst.close();
|
||||
}
|
||||
|
||||
// channels
|
||||
SeekableByteChannel chSrc = src.newByteChannel();
|
||||
SeekableByteChannel chDst = dst.newByteChannel();
|
||||
if (chSrc.size() != chDst.size()) {
|
||||
System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
|
||||
chSrc.toString(), chSrc.size(),
|
||||
chDst.toString(), chDst.size());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
ByteBuffer bbSrc = ByteBuffer.allocate(8192);
|
||||
ByteBuffer bbDst = ByteBuffer.allocate(8192);
|
||||
|
||||
try {
|
||||
int nSrc = 0;
|
||||
while ((nSrc = chSrc.read(bbSrc)) != -1) {
|
||||
int nDst = chDst.read(bbDst);
|
||||
if (nSrc != nDst) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
while (--nSrc >= 0) {
|
||||
if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nSrc--;
|
||||
}
|
||||
bbSrc.flip();
|
||||
bbDst.flip();
|
||||
}
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
} finally {
|
||||
chSrc.close();
|
||||
chDst.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void fchCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
Set<OpenOption> read = new HashSet<>();
|
||||
read.add(READ);
|
||||
Set<OpenOption> openwrite = new HashSet<>();
|
||||
openwrite.add(CREATE_NEW);
|
||||
openwrite.add(WRITE);
|
||||
|
||||
FileChannel srcFc = src.getFileSystem()
|
||||
.provider()
|
||||
.newFileChannel(src, read);
|
||||
FileChannel dstFc = dst.getFileSystem()
|
||||
.provider()
|
||||
.newFileChannel(dst, openwrite);
|
||||
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.allocate(8192);
|
||||
while (srcFc.read(bb) >= 0) {
|
||||
bb.flip();
|
||||
dstFc.write(bb);
|
||||
bb.clear();
|
||||
}
|
||||
} finally {
|
||||
srcFc.close();
|
||||
dstFc.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void chCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
Set<OpenOption> read = new HashSet<>();
|
||||
read.add(READ);
|
||||
Set<OpenOption> openwrite = new HashSet<>();
|
||||
openwrite.add(CREATE_NEW);
|
||||
openwrite.add(WRITE);
|
||||
|
||||
SeekableByteChannel srcCh = src.newByteChannel(read);
|
||||
SeekableByteChannel dstCh = dst.newByteChannel(openwrite);
|
||||
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.allocate(8192);
|
||||
while (srcCh.read(bb) >= 0) {
|
||||
bb.flip();
|
||||
dstCh.write(bb);
|
||||
bb.clear();
|
||||
}
|
||||
} finally {
|
||||
srcCh.close();
|
||||
dstCh.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void streamCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
InputStream isSrc = src.newInputStream();
|
||||
OutputStream osDst = dst.newOutputStream();
|
||||
byte[] buf = new byte[8192];
|
||||
try {
|
||||
int n = 0;
|
||||
while ((n = isSrc.read(buf)) != -1) {
|
||||
osDst.write(buf, 0, n);
|
||||
}
|
||||
} finally {
|
||||
isSrc.close();
|
||||
osDst.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
com.sun.nio.zipfs.ZipFileSystemProvider
|
||||
com.sun.nio.zipfs.JarFileSystemProvider
|
||||
|
29
jdk/src/share/demo/nio/zipfs/README.txt
Normal file
29
jdk/src/share/demo/nio/zipfs/README.txt
Normal file
@ -0,0 +1,29 @@
|
||||
ZipFileSystem is a file system provider that treats the contents of a zip or
|
||||
JAR file as a java.nio.file.FileSystem.
|
||||
|
||||
To deploy the provider you must copy zipfs.jar into your extensions
|
||||
directory or else add <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar
|
||||
to your class path.
|
||||
|
||||
The factory methods defined by the java.nio.file.FileSystems class can be
|
||||
used to create a FileSystem, eg:
|
||||
|
||||
// use file type detection
|
||||
Map<String,?> env = Collections.emptyMap();
|
||||
Path jarfile = Path.get("foo.jar");
|
||||
FileSystem fs = FileSystems.newFileSystem(jarfile, env);
|
||||
|
||||
-or
|
||||
|
||||
// locate file system by URI
|
||||
Map<String,?> env = Collections.emptyMap();
|
||||
URI uri = URI.create("zip:///mydir/foo.jar");
|
||||
FileSystem fs = FileSystems.newFileSystem(uri, env);
|
||||
|
||||
Once a FileSystem is created then classes in the java.nio.file package
|
||||
can be used to access files in the zip/JAR file, eg:
|
||||
|
||||
Path mf = fs.getPath("/META-INF/MANIFEST.MF");
|
||||
InputStream in = mf.newInputStream();
|
||||
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Sun Microsystems nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.spi.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
|
||||
import java.net.URI;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JarFileSystemProvider extends ZipFileSystemProvider
|
||||
{
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return "jar";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path uriToPath(URI uri) {
|
||||
String scheme = uri.getScheme();
|
||||
if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
|
||||
throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
|
||||
}
|
||||
try {
|
||||
String uristr = uri.toString();
|
||||
int end = uristr.indexOf("!/");
|
||||
uristr = uristr.substring(4, (end == -1) ? uristr.length() : end);
|
||||
uri = new URI(uristr);
|
||||
return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
|
||||
.toAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new AssertionError(e); //never thrown
|
||||
}
|
||||
}
|
||||
}
|
160
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipCoder.java
Normal file
160
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipCoder.java
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Utility class for zipfile name and comment decoding and encoding
|
||||
*
|
||||
* @author Xueming Shen
|
||||
*/
|
||||
|
||||
final class ZipCoder {
|
||||
|
||||
String toString(byte[] ba, int length) {
|
||||
CharsetDecoder cd = decoder().reset();
|
||||
int len = (int)(length * cd.maxCharsPerByte());
|
||||
char[] ca = new char[len];
|
||||
if (len == 0)
|
||||
return new String(ca);
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
return new String(ca, 0, cb.position());
|
||||
}
|
||||
|
||||
String toString(byte[] ba) {
|
||||
return toString(ba, ba.length);
|
||||
}
|
||||
|
||||
byte[] getBytes(String s) {
|
||||
CharsetEncoder ce = encoder().reset();
|
||||
char[] ca = s.toCharArray();
|
||||
int len = (int)(ca.length * ce.maxBytesPerChar());
|
||||
byte[] ba = new byte[len];
|
||||
if (len == 0)
|
||||
return ba;
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
if (bb.position() == ba.length) // defensive copy?
|
||||
return ba;
|
||||
else
|
||||
return Arrays.copyOf(ba, bb.position());
|
||||
}
|
||||
|
||||
// assume invoked only if "this" is not utf8
|
||||
byte[] getBytesUTF8(String s) {
|
||||
if (isutf8)
|
||||
return getBytes(s);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.getBytes(s);
|
||||
}
|
||||
|
||||
String toStringUTF8(byte[] ba, int len) {
|
||||
if (isutf8)
|
||||
return toString(ba, len);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.toString(ba, len);
|
||||
}
|
||||
|
||||
boolean isUTF8() {
|
||||
return isutf8;
|
||||
}
|
||||
|
||||
private Charset cs;
|
||||
private boolean isutf8;
|
||||
private ZipCoder utf8;
|
||||
|
||||
private ZipCoder(Charset cs) {
|
||||
this.cs = cs;
|
||||
this.isutf8 = cs.name().equals("UTF-8");
|
||||
}
|
||||
|
||||
static ZipCoder get(Charset charset) {
|
||||
return new ZipCoder(charset);
|
||||
}
|
||||
|
||||
static ZipCoder get(String csn) {
|
||||
try {
|
||||
return new ZipCoder(Charset.forName(csn));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return new ZipCoder(Charset.defaultCharset());
|
||||
}
|
||||
|
||||
private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
|
||||
private final ThreadLocal<CharsetEncoder> encTL = new ThreadLocal<>();
|
||||
|
||||
private CharsetDecoder decoder() {
|
||||
CharsetDecoder dec = decTL.get();
|
||||
if (dec == null) {
|
||||
dec = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
decTL.set(dec);
|
||||
}
|
||||
return dec;
|
||||
}
|
||||
|
||||
private CharsetEncoder encoder() {
|
||||
CharsetEncoder enc = encTL.get();
|
||||
if (enc == null) {
|
||||
enc = cs.newEncoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
encTL.set(enc);
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
}
|
261
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java
Normal file
261
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen
|
||||
*/
|
||||
|
||||
class ZipConstants {
|
||||
/*
|
||||
* Compression methods
|
||||
*/
|
||||
static final int METHOD_STORED = 0;
|
||||
static final int METHOD_DEFLATED = 8;
|
||||
static final int METHOD_DEFLATED64 = 9;
|
||||
static final int METHOD_BZIP2 = 12;
|
||||
static final int METHOD_LZMA = 14;
|
||||
static final int METHOD_LZ77 = 19;
|
||||
|
||||
/*
|
||||
* General purpose big flag
|
||||
*/
|
||||
static final int FLAG_ENCRYPTED = 0x01;
|
||||
static final int FLAG_DATADESCR = 0x08; // crc, size and csize in dd
|
||||
static final int FLAG_EFS = 0x800; // If this bit is set the filename and
|
||||
// comment fields for this file must be
|
||||
// encoded using UTF-8.
|
||||
/*
|
||||
* Header signatures
|
||||
*/
|
||||
static long LOCSIG = 0x04034b50L; // "PK\003\004"
|
||||
static long EXTSIG = 0x08074b50L; // "PK\007\008"
|
||||
static long CENSIG = 0x02014b50L; // "PK\001\002"
|
||||
static long ENDSIG = 0x06054b50L; // "PK\005\006"
|
||||
|
||||
/*
|
||||
* Header sizes in bytes (including signatures)
|
||||
*/
|
||||
static final int LOCHDR = 30; // LOC header size
|
||||
static final int EXTHDR = 16; // EXT header size
|
||||
static final int CENHDR = 46; // CEN header size
|
||||
static final int ENDHDR = 22; // END header size
|
||||
|
||||
/*
|
||||
* Local file (LOC) header field offsets
|
||||
*/
|
||||
static final int LOCVER = 4; // version needed to extract
|
||||
static final int LOCFLG = 6; // general purpose bit flag
|
||||
static final int LOCHOW = 8; // compression method
|
||||
static final int LOCTIM = 10; // modification time
|
||||
static final int LOCCRC = 14; // uncompressed file crc-32 value
|
||||
static final int LOCSIZ = 18; // compressed size
|
||||
static final int LOCLEN = 22; // uncompressed size
|
||||
static final int LOCNAM = 26; // filename length
|
||||
static final int LOCEXT = 28; // extra field length
|
||||
|
||||
/*
|
||||
* Extra local (EXT) header field offsets
|
||||
*/
|
||||
static final int EXTCRC = 4; // uncompressed file crc-32 value
|
||||
static final int EXTSIZ = 8; // compressed size
|
||||
static final int EXTLEN = 12; // uncompressed size
|
||||
|
||||
/*
|
||||
* Central directory (CEN) header field offsets
|
||||
*/
|
||||
static final int CENVEM = 4; // version made by
|
||||
static final int CENVER = 6; // version needed to extract
|
||||
static final int CENFLG = 8; // encrypt, decrypt flags
|
||||
static final int CENHOW = 10; // compression method
|
||||
static final int CENTIM = 12; // modification time
|
||||
static final int CENCRC = 16; // uncompressed file crc-32 value
|
||||
static final int CENSIZ = 20; // compressed size
|
||||
static final int CENLEN = 24; // uncompressed size
|
||||
static final int CENNAM = 28; // filename length
|
||||
static final int CENEXT = 30; // extra field length
|
||||
static final int CENCOM = 32; // comment length
|
||||
static final int CENDSK = 34; // disk number start
|
||||
static final int CENATT = 36; // internal file attributes
|
||||
static final int CENATX = 38; // external file attributes
|
||||
static final int CENOFF = 42; // LOC header offset
|
||||
|
||||
/*
|
||||
* End of central directory (END) header field offsets
|
||||
*/
|
||||
static final int ENDSUB = 8; // number of entries on this disk
|
||||
static final int ENDTOT = 10; // total number of entries
|
||||
static final int ENDSIZ = 12; // central directory size in bytes
|
||||
static final int ENDOFF = 16; // offset of first CEN header
|
||||
static final int ENDCOM = 20; // zip file comment length
|
||||
|
||||
/*
|
||||
* ZIP64 constants
|
||||
*/
|
||||
static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
|
||||
static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
|
||||
static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
|
||||
static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
|
||||
static final int ZIP64_EXTHDR = 24; // EXT header size
|
||||
static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
|
||||
|
||||
static final int ZIP64_MINVAL32 = 0xFFFF;
|
||||
static final long ZIP64_MINVAL = 0xFFFFFFFFL;
|
||||
|
||||
/*
|
||||
* Zip64 End of central directory (END) header field offsets
|
||||
*/
|
||||
static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
|
||||
static final int ZIP64_ENDVEM = 12; // version made by
|
||||
static final int ZIP64_ENDVER = 14; // version needed to extract
|
||||
static final int ZIP64_ENDNMD = 16; // number of this disk
|
||||
static final int ZIP64_ENDDSK = 20; // disk number of start
|
||||
static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
|
||||
static final int ZIP64_ENDTOT = 32; // total number of entries
|
||||
static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
|
||||
static final int ZIP64_ENDOFF = 48; // offset of first CEN header
|
||||
static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
|
||||
|
||||
/*
|
||||
* Zip64 End of central directory locator field offsets
|
||||
*/
|
||||
static final int ZIP64_LOCDSK = 4; // disk number start
|
||||
static final int ZIP64_LOCOFF = 8; // offset of zip64 end
|
||||
static final int ZIP64_LOCTOT = 16; // total number of disks
|
||||
|
||||
/*
|
||||
* Zip64 Extra local (EXT) header field offsets
|
||||
*/
|
||||
static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
|
||||
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
|
||||
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
|
||||
|
||||
/*
|
||||
* Extra field header ID
|
||||
*/
|
||||
static final int EXTID_ZIP64 = 0x0001; // ZIP64
|
||||
static final int EXTID_NTFS = 0x000a; // NTFS
|
||||
static final int EXTID_UNIX = 0x000d; // UNIX
|
||||
|
||||
|
||||
/*
|
||||
* fields access methods
|
||||
*/
|
||||
///////////////////////////////////////////////////////
|
||||
static final int CH(byte[] b, int n) {
|
||||
return b[n] & 0xff;
|
||||
}
|
||||
|
||||
static final int SH(byte[] b, int n) {
|
||||
return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
|
||||
}
|
||||
|
||||
static final long LG(byte[] b, int n) {
|
||||
return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
|
||||
}
|
||||
|
||||
static final long LL(byte[] b, int n) {
|
||||
return (LG(b, n)) | (LG(b, n + 4) << 32);
|
||||
}
|
||||
|
||||
static final long GETSIG(byte[] b) {
|
||||
return LG(b, 0);
|
||||
}
|
||||
|
||||
// local file (LOC) header fields
|
||||
static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
|
||||
static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
|
||||
static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
|
||||
static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method
|
||||
static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
|
||||
static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
|
||||
static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
|
||||
static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
|
||||
static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length
|
||||
static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
|
||||
|
||||
// extra local (EXT) header fields
|
||||
static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data
|
||||
static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size
|
||||
static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
|
||||
|
||||
// end of central directory header (END) fields
|
||||
static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk
|
||||
static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries
|
||||
static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size
|
||||
static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset
|
||||
static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of zip file comment
|
||||
static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
|
||||
|
||||
// zip64 end of central directory recoder fields
|
||||
static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk
|
||||
static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries
|
||||
static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size
|
||||
static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset
|
||||
static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset
|
||||
|
||||
//////////////////////////////////////////
|
||||
static final int CH(ByteBuffer b, int pos) {
|
||||
return b.get(pos) & 0xff;
|
||||
}
|
||||
static final int SH(ByteBuffer b, int pos) {
|
||||
return b.getShort(pos) & 0xffff;
|
||||
}
|
||||
static final long LG(ByteBuffer b, int pos) {
|
||||
return b.getInt(pos) & 0xffffffffL;
|
||||
}
|
||||
|
||||
// central directory header (END) fields
|
||||
static final long CENSIG(ByteBuffer b, int pos) { return LG(b, pos + 0); }
|
||||
static final int CENVEM(ByteBuffer b, int pos) { return SH(b, pos + 4); }
|
||||
static final int CENVER(ByteBuffer b, int pos) { return SH(b, pos + 6); }
|
||||
static final int CENFLG(ByteBuffer b, int pos) { return SH(b, pos + 8); }
|
||||
static final int CENHOW(ByteBuffer b, int pos) { return SH(b, pos + 10);}
|
||||
static final long CENTIM(ByteBuffer b, int pos) { return LG(b, pos + 12);}
|
||||
static final long CENCRC(ByteBuffer b, int pos) { return LG(b, pos + 16);}
|
||||
static final long CENSIZ(ByteBuffer b, int pos) { return LG(b, pos + 20);}
|
||||
static final long CENLEN(ByteBuffer b, int pos) { return LG(b, pos + 24);}
|
||||
static final int CENNAM(ByteBuffer b, int pos) { return SH(b, pos + 28);}
|
||||
static final int CENEXT(ByteBuffer b, int pos) { return SH(b, pos + 30);}
|
||||
static final int CENCOM(ByteBuffer b, int pos) { return SH(b, pos + 32);}
|
||||
static final int CENDSK(ByteBuffer b, int pos) { return SH(b, pos + 34);}
|
||||
static final int CENATT(ByteBuffer b, int pos) { return SH(b, pos + 36);}
|
||||
static final long CENATX(ByteBuffer b, int pos) { return LG(b, pos + 38);}
|
||||
static final long CENOFF(ByteBuffer b, int pos) { return LG(b, pos + 42);}
|
||||
|
||||
/* The END header is followed by a variable length comment of size < 64k. */
|
||||
static final long END_MAXLEN = 0xFFFF + ENDHDR;
|
||||
static final int READBLOCKSZ = 128;
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.ClosedDirectoryStreamException;
|
||||
import java.nio.file.NotDirectoryException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.io.IOException;
|
||||
import static com.sun.nio.zipfs.ZipUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipDirectoryStream implements DirectoryStream<Path> {
|
||||
|
||||
private final ZipFileSystem zipfs;
|
||||
private final byte[] path;
|
||||
private final DirectoryStream.Filter<? super Path> filter;
|
||||
private volatile boolean isClosed;
|
||||
private volatile Iterator<Path> itr;
|
||||
|
||||
ZipDirectoryStream(ZipPath zipPath,
|
||||
DirectoryStream.Filter<? super java.nio.file.Path> filter)
|
||||
throws IOException
|
||||
{
|
||||
this.zipfs = zipPath.getFileSystem();
|
||||
this.path = zipPath.getResolvedPath();
|
||||
this.filter = filter;
|
||||
// sanity check
|
||||
if (!zipfs.isDirectory(path))
|
||||
throw new NotDirectoryException(zipPath.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Iterator<Path> iterator() {
|
||||
if (isClosed)
|
||||
throw new ClosedDirectoryStreamException();
|
||||
if (itr != null)
|
||||
throw new IllegalStateException("Iterator has already been returned");
|
||||
|
||||
try {
|
||||
itr = zipfs.iteratorOf(path, filter);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
return new Iterator<Path>() {
|
||||
private Path next;
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (isClosed)
|
||||
return false;
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Path next() {
|
||||
if (isClosed)
|
||||
throw new NoSuchElementException();
|
||||
return itr.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
isClosed = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.file.ReadOnlyFileSystemException;
|
||||
import java.nio.file.attribute.BasicFileAttributeView;
|
||||
import java.nio.file.attribute.FileAttributeView;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/*
|
||||
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipFileAttributeView implements BasicFileAttributeView
|
||||
{
|
||||
private static enum AttrID {
|
||||
size,
|
||||
creationTime,
|
||||
lastAccessTime,
|
||||
lastModifiedTime,
|
||||
isDirectory,
|
||||
isRegularFile,
|
||||
isSymbolicLink,
|
||||
isOther,
|
||||
fileKey,
|
||||
compressedSize,
|
||||
crc,
|
||||
method
|
||||
};
|
||||
|
||||
private final ZipPath path;
|
||||
private final boolean isZipView;
|
||||
|
||||
private ZipFileAttributeView(ZipPath path, boolean isZipView) {
|
||||
this.path = path;
|
||||
this.isZipView = isZipView;
|
||||
}
|
||||
|
||||
static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) {
|
||||
if (type == null)
|
||||
throw new NullPointerException();
|
||||
if (type == BasicFileAttributeView.class)
|
||||
return (V)new ZipFileAttributeView(path, false);
|
||||
if (type == ZipFileAttributeView.class)
|
||||
return (V)new ZipFileAttributeView(path, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
static ZipFileAttributeView get(ZipPath path, String type) {
|
||||
if (type == null)
|
||||
throw new NullPointerException();
|
||||
if (type.equals("basic"))
|
||||
return new ZipFileAttributeView(path, false);
|
||||
if (type.equals("zip"))
|
||||
return new ZipFileAttributeView(path, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return isZipView ? "zip" : "basic";
|
||||
}
|
||||
|
||||
public ZipFileAttributes readAttributes() throws IOException
|
||||
{
|
||||
return path.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimes(FileTime lastModifiedTime,
|
||||
FileTime lastAccessTime,
|
||||
FileTime createTime)
|
||||
throws IOException
|
||||
{
|
||||
path.setTimes(lastModifiedTime, lastAccessTime, createTime);
|
||||
}
|
||||
|
||||
void setAttribute(String attribute, Object value)
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime)
|
||||
setTimes ((FileTime)value, null, null);
|
||||
return;
|
||||
} catch (IllegalArgumentException x) {}
|
||||
throw new UnsupportedOperationException("'" + attribute +
|
||||
"' is unknown or read-only attribute");
|
||||
}
|
||||
|
||||
public Object getAttribute(String attribute, boolean domap)
|
||||
throws IOException
|
||||
{
|
||||
ZipFileAttributes zfas = readAttributes();
|
||||
if (!domap) {
|
||||
try {
|
||||
return attribute(AttrID.valueOf(attribute), zfas);
|
||||
} catch (IllegalArgumentException x) {}
|
||||
return null;
|
||||
}
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
if ("*".equals(attribute)) {
|
||||
for (AttrID id : AttrID.values()) {
|
||||
try {
|
||||
map.put(id.name(), attribute(id, zfas));
|
||||
} catch (IllegalArgumentException x) {}
|
||||
}
|
||||
} else {
|
||||
String[] as = attribute.split(",");
|
||||
for (String a : as) {
|
||||
try {
|
||||
map.put(a, attribute(AttrID.valueOf(a), zfas));
|
||||
} catch (IllegalArgumentException x) {}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Object attribute(AttrID id, ZipFileAttributes zfas) {
|
||||
switch (id) {
|
||||
case size:
|
||||
return zfas.size();
|
||||
case creationTime:
|
||||
return zfas.creationTime();
|
||||
case lastAccessTime:
|
||||
return zfas.lastAccessTime();
|
||||
case lastModifiedTime:
|
||||
return zfas.lastModifiedTime();
|
||||
case isDirectory:
|
||||
return zfas.isDirectory();
|
||||
case isRegularFile:
|
||||
return zfas.isRegularFile();
|
||||
case isSymbolicLink:
|
||||
return zfas.isSymbolicLink();
|
||||
case isOther:
|
||||
return zfas.isOther();
|
||||
case fileKey:
|
||||
return zfas.fileKey();
|
||||
case compressedSize:
|
||||
if (isZipView)
|
||||
return zfas.compressedSize();
|
||||
break;
|
||||
case crc:
|
||||
if (isZipView)
|
||||
return zfas.crc();
|
||||
break;
|
||||
case method:
|
||||
if (isZipView)
|
||||
return zfas.method();
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Formatter;
|
||||
import static com.sun.nio.zipfs.ZipUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipFileAttributes implements BasicFileAttributes
|
||||
|
||||
{
|
||||
private final ZipFileSystem.Entry e;
|
||||
|
||||
ZipFileAttributes(ZipFileSystem.Entry e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
///////// basic attributes ///////////
|
||||
@Override
|
||||
public FileTime creationTime() {
|
||||
if (e.ctime != -1)
|
||||
return FileTime.fromMillis(dosToJavaTime(e.ctime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return e.isDir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOther() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegularFile() {
|
||||
return !e.isDir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileTime lastAccessTime() {
|
||||
if (e.atime != -1)
|
||||
return FileTime.fromMillis(dosToJavaTime(e.atime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileTime lastModifiedTime() {
|
||||
return FileTime.fromMillis(dosToJavaTime(e.mtime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() {
|
||||
return e.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymbolicLink() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fileKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
///////// zip entry attributes ///////////
|
||||
public byte[] name() {
|
||||
return Arrays.copyOf(e.name, e.name.length);
|
||||
}
|
||||
|
||||
public long compressedSize() {
|
||||
return e.csize;
|
||||
}
|
||||
|
||||
public long crc() {
|
||||
return e.crc;
|
||||
}
|
||||
|
||||
public int method() {
|
||||
return e.method;
|
||||
}
|
||||
|
||||
public byte[] extra() {
|
||||
if (e.extra != null)
|
||||
return Arrays.copyOf(e.extra, e.extra.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] comment() {
|
||||
if (e.comment != null)
|
||||
return Arrays.copyOf(e.comment, e.comment.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter fm = new Formatter(sb);
|
||||
fm.format("[/%s]%n", new String(e.name)); // TBD encoding
|
||||
fm.format(" creationTime : %s%n", creationTime());
|
||||
if (lastAccessTime() != null)
|
||||
fm.format(" lastAccessTime : %tc%n", lastAccessTime().toMillis());
|
||||
else
|
||||
fm.format(" lastAccessTime : null%n");
|
||||
fm.format(" lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
|
||||
fm.format(" isRegularFile : %b%n", isRegularFile());
|
||||
fm.format(" isDirectory : %b%n", isDirectory());
|
||||
fm.format(" isSymbolicLink : %b%n", isSymbolicLink());
|
||||
fm.format(" isOther : %b%n", isOther());
|
||||
fm.format(" fileKey : %s%n", fileKey());
|
||||
fm.format(" size : %d%n", size());
|
||||
fm.format(" compressedSize : %d%n", compressedSize());
|
||||
fm.format(" crc : %x%n", crc());
|
||||
fm.format(" method : %d%n", method());
|
||||
fm.close();
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
157
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileStore.java
Normal file
157
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileStore.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileStore;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.FileAttributeView;
|
||||
import java.nio.file.attribute.FileStoreAttributeView;
|
||||
import java.nio.file.attribute.FileStoreSpaceAttributeView;
|
||||
import java.nio.file.attribute.FileStoreSpaceAttributes;
|
||||
import java.nio.file.attribute.Attributes;
|
||||
import java.nio.file.attribute.BasicFileAttributeView;
|
||||
import java.util.Formatter;
|
||||
|
||||
/*
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipFileStore extends FileStore {
|
||||
|
||||
private final ZipFileSystem zfs;
|
||||
|
||||
ZipFileStore(ZipPath zpath) {
|
||||
this.zfs = (ZipFileSystem)zpath.getFileSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return zfs.toString() + "/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return "zipfs";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return zfs.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
||||
return (type == BasicFileAttributeView.class ||
|
||||
type == ZipFileAttributeView.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFileAttributeView(String name) {
|
||||
return name.equals("basic") || name.equals("zip");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
|
||||
if (type == null)
|
||||
throw new NullPointerException();
|
||||
if (type == FileStoreSpaceAttributeView.class)
|
||||
return (V) new ZipFileStoreAttributeView(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute) throws IOException {
|
||||
if (attribute.equals("space:totalSpace"))
|
||||
return new ZipFileStoreAttributeView(this).readAttributes().totalSpace();
|
||||
if (attribute.equals("space:usableSpace"))
|
||||
return new ZipFileStoreAttributeView(this).readAttributes().usableSpace();
|
||||
if (attribute.equals("space:unallocatedSpace"))
|
||||
return new ZipFileStoreAttributeView(this).readAttributes().unallocatedSpace();
|
||||
throw new UnsupportedOperationException("does not support the given attribute");
|
||||
}
|
||||
|
||||
private static class ZipFileStoreAttributeView implements FileStoreSpaceAttributeView {
|
||||
|
||||
private final ZipFileStore fileStore;
|
||||
|
||||
public ZipFileStoreAttributeView(ZipFileStore fileStore) {
|
||||
this.fileStore = fileStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "space";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStoreSpaceAttributes readAttributes() throws IOException {
|
||||
final String file = fileStore.name();
|
||||
Path path = FileSystems.getDefault().getPath(file);
|
||||
final long size = Attributes.readBasicFileAttributes(path).size();
|
||||
final FileStore fstore = path.getFileStore();
|
||||
final FileStoreSpaceAttributes fstoreAttrs =
|
||||
Attributes.readFileStoreSpaceAttributes(fstore);
|
||||
return new FileStoreSpaceAttributes() {
|
||||
public long totalSpace() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public long usableSpace() {
|
||||
if (!fstore.isReadOnly())
|
||||
return fstoreAttrs.usableSpace();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long unallocatedSpace() {
|
||||
if (!fstore.isReadOnly())
|
||||
return fstoreAttrs.unallocatedSpace();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter fm = new Formatter(sb);
|
||||
fm.format("FileStoreSpaceAttributes[%s]%n", file);
|
||||
fm.format(" totalSpace: %d%n", totalSpace());
|
||||
fm.format(" usableSpace: %d%n", usableSpace());
|
||||
fm.format(" unallocSpace: %d%n", unallocatedSpace());
|
||||
fm.close();
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
2257
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java
Normal file
2257
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.FileRef;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.FileSystemAlreadyExistsException;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.ProviderMismatchException;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipFileSystemProvider extends FileSystemProvider {
|
||||
private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
|
||||
|
||||
public ZipFileSystemProvider() {}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return "zip";
|
||||
}
|
||||
|
||||
protected Path uriToPath(URI uri) {
|
||||
String scheme = uri.getScheme();
|
||||
if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
|
||||
throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
|
||||
}
|
||||
try {
|
||||
return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
|
||||
.toAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new AssertionError(e); //never thrown
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileSystem newFileSystem(URI uri, Map<String, ?> env)
|
||||
throws IOException
|
||||
{
|
||||
return newFileSystem(uriToPath(uri), env);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileSystem newFileSystem(FileRef file, Map<String, ?> env)
|
||||
throws IOException
|
||||
{
|
||||
if (!(file instanceof Path))
|
||||
throw new UnsupportedOperationException();
|
||||
Path path = (Path)file;
|
||||
if (!path.toUri().getScheme().equalsIgnoreCase("file")) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return newFileSystem(path, env);
|
||||
}
|
||||
|
||||
private FileSystem newFileSystem(Path path, Map<String, ?> env)
|
||||
throws IOException
|
||||
{
|
||||
synchronized(filesystems) {
|
||||
if (filesystems.containsKey(path))
|
||||
throw new FileSystemAlreadyExistsException();
|
||||
ZipFileSystem zipfs = new ZipFileSystem(this, path, env);
|
||||
filesystems.put(path, zipfs);
|
||||
return zipfs;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getPath(URI uri) {
|
||||
FileSystem fs = getFileSystem(uri);
|
||||
String fragment = uri.getFragment();
|
||||
if (fragment == null) {
|
||||
throw new IllegalArgumentException("URI: "
|
||||
+ uri
|
||||
+ " does not contain path fragment ex. zip:///c:/foo.zip#/BAR");
|
||||
}
|
||||
return fs.getPath(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileChannel newFileChannel(Path path,
|
||||
Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
if (path == null)
|
||||
throw new NullPointerException("path is null");
|
||||
if (path instanceof ZipPath)
|
||||
return ((ZipPath)path).newFileChannel(options, attrs);
|
||||
throw new ProviderMismatchException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileSystem getFileSystem(URI uri) {
|
||||
synchronized (filesystems) {
|
||||
ZipFileSystem zipfs = filesystems.get(uriToPath(uri));
|
||||
if (zipfs == null)
|
||||
throw new FileSystemNotFoundException();
|
||||
return zipfs;
|
||||
}
|
||||
}
|
||||
|
||||
void removeFileSystem(Path zfpath) {
|
||||
synchronized (filesystems) {
|
||||
filesystems.remove(zfpath);
|
||||
}
|
||||
}
|
||||
}
|
132
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java
Normal file
132
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import com.sun.nio.zipfs.ZipFileSystem.Entry;
|
||||
import static com.sun.nio.zipfs.ZipConstants.*;
|
||||
import static com.sun.nio.zipfs.ZipUtils.*;
|
||||
|
||||
/**
|
||||
* Print the loc and cen tables of the ZIP file
|
||||
*
|
||||
* @author Xueming Shen
|
||||
*/
|
||||
|
||||
public class ZipInfo {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
if (args.length < 2) {
|
||||
print("Usage: java ZipInfo [cen|loc] zfname");
|
||||
} else {
|
||||
Map<String, ?> env = Collections.emptyMap();
|
||||
ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
|
||||
.newFileSystem(Paths.get(args[1]), env));
|
||||
|
||||
long pos = 0;
|
||||
|
||||
if ("loc".equals(args[0])) {
|
||||
print("[Local File Header]%n");
|
||||
byte[] buf = new byte[1024];
|
||||
for (int i = 0; i < zfs.getEntryNames().length; i++) {
|
||||
Entry loc = Entry.readLOC(zfs, pos, buf);
|
||||
print("--------loc[%x]--------%n", pos);
|
||||
printLOC(loc);
|
||||
pos = loc.endPos;
|
||||
}
|
||||
} if ("cen".equals(args[0])) {
|
||||
int i = 0;
|
||||
Iterator<ZipFileSystem.IndexNode> itr = zfs.inodes.values().iterator();
|
||||
print("[Central Directory Header]%n");
|
||||
while (itr.hasNext()) {
|
||||
Entry cen = Entry.readCEN(zfs.cen, itr.next().pos);
|
||||
print("--------cen[%d]--------%n", i);
|
||||
printCEN(cen);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
zfs.close();
|
||||
}
|
||||
}
|
||||
|
||||
static void print(String fmt, Object... objs) {
|
||||
System.out.printf(fmt, objs);
|
||||
}
|
||||
|
||||
static void printLOC(Entry loc) {
|
||||
print(" [%x, %x]%n", loc.startPos, loc.endPos);
|
||||
print(" Signature : %8x%n", LOCSIG);
|
||||
print(" Version : %4x [%d.%d]%n",
|
||||
loc.version, loc. version/10, loc. version%10);
|
||||
print(" Flag : %4x%n", loc.flag);
|
||||
print(" Method : %4x%n", loc. method);
|
||||
print(" LastMTime : %8x [%tc]%n",
|
||||
loc.mtime, dosToJavaTime(loc.mtime));
|
||||
print(" CRC : %8x%n", loc.crc);
|
||||
print(" CSize : %8x%n", loc.csize);
|
||||
print(" Size : %8x%n", loc.size);
|
||||
print(" NameLength : %4x [%s]%n",
|
||||
loc.nlen, new String(loc.name));
|
||||
print(" ExtraLength : %4x%n", loc.elen);
|
||||
if (loc.hasZip64)
|
||||
print(" *ZIP64*%n");
|
||||
}
|
||||
|
||||
static void printCEN(Entry cen) {
|
||||
print(" Signature : %08x%n", CENSIG);
|
||||
print(" VerMadeby : %4x [%d.%d]%n",
|
||||
cen.versionMade, cen.versionMade/10, cen.versionMade%10);
|
||||
print(" VerExtract : %4x [%d.%d]%n",
|
||||
cen.version, cen.version/10, cen.version%10);
|
||||
print(" Flag : %4x%n", cen.flag);
|
||||
print(" Method : %4x%n", cen.method);
|
||||
print(" LastMTime : %8x [%tc]%n",
|
||||
cen.mtime, dosToJavaTime(cen.mtime));
|
||||
print(" CRC : %8x%n", cen.crc);
|
||||
print(" CSize : %8x%n", cen.csize);
|
||||
print(" Size : %8x%n", cen.size);
|
||||
print(" NameLen : %4x [%s]%n",
|
||||
cen.nlen, new String(cen.name));
|
||||
print(" ExtraLen : %4x%n", cen.elen);
|
||||
print(" CommentLen : %4x%n", cen.clen);
|
||||
print(" DiskStart : %4x%n", cen.disk);
|
||||
print(" Attrs : %4x%n", cen.attrs);
|
||||
print(" AttrsEx : %8x%n", cen.attrsEx);
|
||||
print(" LocOff : %8x%n", cen.locoff);
|
||||
if (cen.hasZip64)
|
||||
print(" *ZIP64*%n");
|
||||
}
|
||||
}
|
964
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java
Normal file
964
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java
Normal file
@ -0,0 +1,964 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.DirectoryStream.Filter;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.nio.file.attribute.BasicFileAttributeView;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.attribute.FileAttributeView;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
|
||||
*/
|
||||
|
||||
public class ZipPath extends Path {
|
||||
|
||||
private final ZipFileSystem zfs;
|
||||
private final byte[] path;
|
||||
private volatile int[] offsets;
|
||||
private int hashcode = 0; // cached hashcode (created lazily)
|
||||
|
||||
ZipPath(ZipFileSystem zfs, byte[] path) {
|
||||
this(zfs, path, false);
|
||||
}
|
||||
|
||||
ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized)
|
||||
{
|
||||
this.zfs = zfs;
|
||||
if (normalized)
|
||||
this.path = path;
|
||||
else
|
||||
this.path = normalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath getRoot() {
|
||||
if (this.isAbsolute())
|
||||
return new ZipPath(zfs, new byte[]{path[0]});
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getName() {
|
||||
initOffsets();
|
||||
int count = offsets.length;
|
||||
if (count == 0)
|
||||
return null; // no elements so no name
|
||||
if (count == 1 && path[0] != '/')
|
||||
return this;
|
||||
int lastOffset = offsets[count-1];
|
||||
int len = path.length - lastOffset;
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(path, lastOffset, result, 0, len);
|
||||
return new ZipPath(zfs, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath getParent() {
|
||||
initOffsets();
|
||||
int count = offsets.length;
|
||||
if (count == 0) // no elements so no parent
|
||||
return null;
|
||||
int len = offsets[count-1] - 1;
|
||||
if (len <= 0) // parent is root only (may be null)
|
||||
return getRoot();
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(path, 0, result, 0, len);
|
||||
return new ZipPath(zfs, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameCount() {
|
||||
initOffsets();
|
||||
return offsets.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath getName(int index) {
|
||||
initOffsets();
|
||||
if (index < 0 || index >= offsets.length)
|
||||
throw new IllegalArgumentException();
|
||||
int begin = offsets[index];
|
||||
int len;
|
||||
if (index == (offsets.length-1))
|
||||
len = path.length - begin;
|
||||
else
|
||||
len = offsets[index+1] - begin - 1;
|
||||
// construct result
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(path, begin, result, 0, len);
|
||||
return new ZipPath(zfs, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath subpath(int beginIndex, int endIndex) {
|
||||
initOffsets();
|
||||
if (beginIndex < 0 ||
|
||||
beginIndex >= offsets.length ||
|
||||
endIndex > offsets.length ||
|
||||
beginIndex >= endIndex)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
// starting offset and length
|
||||
int begin = offsets[beginIndex];
|
||||
int len;
|
||||
if (endIndex == offsets.length)
|
||||
len = path.length - begin;
|
||||
else
|
||||
len = offsets[endIndex] - begin - 1;
|
||||
// construct result
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(path, begin, result, 0, len);
|
||||
return new ZipPath(zfs, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath toRealPath(boolean resolveLinks) throws IOException {
|
||||
ZipPath realPath = new ZipPath(zfs, getResolvedPath());
|
||||
realPath.checkAccess();
|
||||
return realPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath toAbsolutePath() {
|
||||
if (isAbsolute()) {
|
||||
return this;
|
||||
} else {
|
||||
//add / bofore the existing path
|
||||
byte[] defaultdir = zfs.getDefaultDir().path;
|
||||
int defaultlen = defaultdir.length;
|
||||
boolean endsWith = (defaultdir[defaultlen - 1] == '/');
|
||||
byte[] t = null;
|
||||
if (endsWith)
|
||||
t = new byte[defaultlen + path.length];
|
||||
else
|
||||
t = new byte[defaultlen + 1 + path.length];
|
||||
System.arraycopy(defaultdir, 0, t, 0, defaultlen);
|
||||
if (!endsWith)
|
||||
t[defaultlen++] = '/';
|
||||
System.arraycopy(path, 0, t, defaultlen, path.length);
|
||||
return new ZipPath(zfs, t, true); // normalized
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toUri() {
|
||||
String zfPath = zfs.toString();
|
||||
if (File.separatorChar == '\\') // replace all separators by '/'
|
||||
zfPath = "/" + zfPath.replace("\\", "/");
|
||||
try {
|
||||
return new URI("zip", "",
|
||||
zfPath,
|
||||
zfs.getString(toAbsolutePath().path));
|
||||
} catch (Exception ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean equalsNameAt(ZipPath other, int index) {
|
||||
int mbegin = offsets[index];
|
||||
int mlen = 0;
|
||||
if (index == (offsets.length-1))
|
||||
mlen = path.length - mbegin;
|
||||
else
|
||||
mlen = offsets[index + 1] - mbegin - 1;
|
||||
int obegin = other.offsets[index];
|
||||
int olen = 0;
|
||||
if (index == (other.offsets.length - 1))
|
||||
olen = other.path.length - obegin;
|
||||
else
|
||||
olen = other.offsets[index + 1] - obegin - 1;
|
||||
if (mlen != olen)
|
||||
return false;
|
||||
int n = 0;
|
||||
while(n < mlen) {
|
||||
if (path[mbegin + n] != other.path[obegin + n])
|
||||
return false;
|
||||
n++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path relativize(Path other) {
|
||||
final ZipPath o = checkPath(other);
|
||||
if (o.equals(this))
|
||||
return null;
|
||||
if (/* this.getFileSystem() != o.getFileSystem() || */
|
||||
this.isAbsolute() != o.isAbsolute()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
int mc = this.getNameCount();
|
||||
int oc = o.getNameCount();
|
||||
int n = Math.min(mc, oc);
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
if (!equalsNameAt(o, i))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
int dotdots = mc - i;
|
||||
int len = dotdots * 3 - 1;
|
||||
if (i < oc)
|
||||
len += (o.path.length - o.offsets[i] + 1);
|
||||
byte[] result = new byte[len];
|
||||
|
||||
int pos = 0;
|
||||
while (dotdots > 0) {
|
||||
result[pos++] = (byte)'.';
|
||||
result[pos++] = (byte)'.';
|
||||
if (pos < len) // no tailing slash at the end
|
||||
result[pos++] = (byte)'/';
|
||||
dotdots--;
|
||||
}
|
||||
if (i < oc)
|
||||
System.arraycopy(o.path, o.offsets[i],
|
||||
result, pos,
|
||||
o.path.length - o.offsets[i]);
|
||||
return new ZipPath(getFileSystem(), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipFileSystem getFileSystem() {
|
||||
return zfs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbsolute() {
|
||||
return (this.path[0] == '/');
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath resolve(Path other) {
|
||||
if (other == null)
|
||||
return this;
|
||||
final ZipPath o = checkPath(other);
|
||||
if (o.isAbsolute())
|
||||
return o;
|
||||
byte[] resolved = null;
|
||||
if (this.path[path.length - 1] == '/') {
|
||||
resolved = new byte[path.length + o.path.length];
|
||||
System.arraycopy(path, 0, resolved, 0, path.length);
|
||||
System.arraycopy(o.path, 0, resolved, path.length, o.path.length);
|
||||
} else {
|
||||
resolved = new byte[path.length + 1 + o.path.length];
|
||||
System.arraycopy(path, 0, resolved, 0, path.length);
|
||||
resolved[path.length] = '/';
|
||||
System.arraycopy(o.path, 0, resolved, path.length + 1, o.path.length);
|
||||
}
|
||||
return new ZipPath(zfs, resolved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipPath resolve(String other) {
|
||||
return resolve(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startsWith(Path other) {
|
||||
final ZipPath o = checkPath(other);
|
||||
if (o.isAbsolute() != this.isAbsolute())
|
||||
return false;
|
||||
final int oCount = o.getNameCount();
|
||||
if (getNameCount() < oCount)
|
||||
return false;
|
||||
for (int i = 0; i < oCount; i++) {
|
||||
if (!o.getName(i).equals(getName(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endsWith(Path other) {
|
||||
final ZipPath o = checkPath(other);
|
||||
if (o.isAbsolute())
|
||||
return this.isAbsolute() ? this.equals(o) : false;
|
||||
int i = o.getNameCount();
|
||||
int j = this.getNameCount();
|
||||
if (j < i)
|
||||
return false;
|
||||
for (--i, --j; i >= 0; i--, j--) {
|
||||
if (!o.getName(i).equals(this.getName(j)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path normalize() {
|
||||
byte[] resolved = getResolved();
|
||||
if (resolved == path) // no change
|
||||
return this;
|
||||
if (resolved.length == 0)
|
||||
return null;
|
||||
return new ZipPath(zfs, resolved, true);
|
||||
}
|
||||
|
||||
private ZipPath checkPath(Path path) {
|
||||
if (path == null)
|
||||
throw new NullPointerException();
|
||||
if (!(path instanceof ZipPath))
|
||||
throw new ProviderMismatchException();
|
||||
return (ZipPath) path;
|
||||
}
|
||||
|
||||
// create offset list if not already created
|
||||
private void initOffsets() {
|
||||
if (offsets == null) {
|
||||
int count, index;
|
||||
// count names
|
||||
count = 0;
|
||||
index = 0;
|
||||
while (index < path.length) {
|
||||
byte c = path[index++];
|
||||
if (c != '/') {
|
||||
count++;
|
||||
while (index < path.length && path[index] != '/')
|
||||
index++;
|
||||
}
|
||||
}
|
||||
// populate offsets
|
||||
int[] result = new int[count];
|
||||
count = 0;
|
||||
index = 0;
|
||||
while (index < path.length) {
|
||||
byte c = path[index];
|
||||
if (c == '/') {
|
||||
index++;
|
||||
} else {
|
||||
result[count++] = index++;
|
||||
while (index < path.length && path[index] != '/')
|
||||
index++;
|
||||
}
|
||||
}
|
||||
synchronized (this) {
|
||||
if (offsets == null)
|
||||
offsets = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolved path for locating zip entry inside the zip file,
|
||||
// the result path does not contain ./ and .. components
|
||||
private volatile byte[] resolved = null;
|
||||
byte[] getResolvedPath() {
|
||||
byte[] r = resolved;
|
||||
if (r == null) {
|
||||
if (isAbsolute())
|
||||
r = getResolved();
|
||||
else
|
||||
r = toAbsolutePath().getResolvedPath();
|
||||
if (r[0] == '/')
|
||||
r = Arrays.copyOfRange(r, 1, r.length);
|
||||
resolved = r;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// removes redundant slashs, replace "\" to zip separator "/"
|
||||
// and check for invalid characters
|
||||
private byte[] normalize(byte[] path) {
|
||||
if (path.length == 0)
|
||||
return path;
|
||||
byte prevC = 0;
|
||||
for (int i = 0; i < path.length; i++) {
|
||||
byte c = path[i];
|
||||
if (c == '\\')
|
||||
return normalize(path, i);
|
||||
if (c == (byte)'/' && prevC == '/')
|
||||
return normalize(path, i - 1);
|
||||
if (c == '\u0000')
|
||||
throw new InvalidPathException(zfs.getString(path),
|
||||
"Path: nul character not allowed");
|
||||
prevC = c;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private byte[] normalize(byte[] path, int off) {
|
||||
byte[] to = new byte[path.length];
|
||||
int n = 0;
|
||||
while (n < off) {
|
||||
to[n] = path[n];
|
||||
n++;
|
||||
}
|
||||
int m = n;
|
||||
byte prevC = 0;
|
||||
while (n < path.length) {
|
||||
byte c = path[n++];
|
||||
if (c == (byte)'\\')
|
||||
c = (byte)'/';
|
||||
if (c == (byte)'/' && prevC == (byte)'/')
|
||||
continue;
|
||||
if (c == '\u0000')
|
||||
throw new InvalidPathException(zfs.getString(path),
|
||||
"Path: nul character not allowed");
|
||||
to[m++] = c;
|
||||
prevC = c;
|
||||
}
|
||||
if (m > 1 && to[m - 1] == '/')
|
||||
m--;
|
||||
return (m == to.length)? to : Arrays.copyOf(to, m);
|
||||
}
|
||||
|
||||
// Remove DotSlash(./) and resolve DotDot (..) components
|
||||
private byte[] getResolved() {
|
||||
if (path.length == 0)
|
||||
return path;
|
||||
for (int i = 0; i < path.length; i++) {
|
||||
byte c = path[i];
|
||||
if (c == (byte)'.')
|
||||
return resolve0();
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// TBD: performance, avoid initOffsets
|
||||
private byte[] resolve0() {
|
||||
byte[] to = new byte[path.length];
|
||||
int nc = getNameCount();
|
||||
int[] lastM = new int[nc];
|
||||
int lastMOff = -1;
|
||||
int m = 0;
|
||||
for (int i = 0; i < nc; i++) {
|
||||
int n = offsets[i];
|
||||
int len = (i == offsets.length - 1)?
|
||||
(path.length - n):(offsets[i + 1] - n - 1);
|
||||
if (len == 1 && path[n] == (byte)'.')
|
||||
continue;
|
||||
if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
|
||||
if (lastMOff >= 0) {
|
||||
m = lastM[lastMOff--]; // retreat
|
||||
continue;
|
||||
}
|
||||
if (path[0] == '/') { // "/../xyz" skip
|
||||
if (m == 0)
|
||||
to[m++] = '/';
|
||||
} else { // "../xyz" -> "../xyz"
|
||||
if (m != 0 && to[m-1] != '/')
|
||||
to[m++] = '/';
|
||||
while (len-- > 0)
|
||||
to[m++] = path[n++];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (m == 0 && path[0] == '/' || // absolute path
|
||||
m != 0 && to[m-1] != '/') { // not the first name
|
||||
to[m++] = '/';
|
||||
}
|
||||
lastM[++lastMOff] = m;
|
||||
while (len-- > 0)
|
||||
to[m++] = path[n++];
|
||||
}
|
||||
if (m > 1 && to[m - 1] == '/')
|
||||
m--;
|
||||
return (m == to.length)? to : Arrays.copyOf(to, m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return zfs.getString(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hashcode;
|
||||
if (h == 0)
|
||||
hashcode = h = Arrays.hashCode(path);
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj != null &&
|
||||
obj instanceof ZipPath &&
|
||||
this.zfs == ((ZipPath)obj).zfs &&
|
||||
compareTo((Path) obj) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Path other) {
|
||||
final ZipPath o = checkPath(other);
|
||||
int len1 = this.path.length;
|
||||
int len2 = o.path.length;
|
||||
|
||||
int n = Math.min(len1, len2);
|
||||
byte v1[] = this.path;
|
||||
byte v2[] = o.path;
|
||||
|
||||
int k = 0;
|
||||
while (k < n) {
|
||||
int c1 = v1[k] & 0xff;
|
||||
int c2 = v2[k] & 0xff;
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
k++;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createSymbolicLink(
|
||||
Path target, FileAttribute<?>... attrs) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createLink(
|
||||
Path existing) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path readSymbolicLink() throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path createDirectory(FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
zfs.createDirectory(getResolvedPath(), attrs);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final Path createFile(FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
OutputStream os = newOutputStream(CREATE_NEW, WRITE);
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException x) {}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream newInputStream(OpenOption... options)
|
||||
throws IOException {
|
||||
if (options.length > 0) {
|
||||
for (OpenOption opt : options) {
|
||||
if (opt != READ)
|
||||
throw new UnsupportedOperationException("'" + opt + "' not allowed");
|
||||
}
|
||||
}
|
||||
return zfs.newInputStream(getResolvedPath());
|
||||
}
|
||||
|
||||
private static final DirectoryStream.Filter<Path> acceptAllFilter =
|
||||
new DirectoryStream.Filter<Path>() {
|
||||
@Override public boolean accept(Path entry) { return true; }
|
||||
};
|
||||
|
||||
@Override
|
||||
public final DirectoryStream<Path> newDirectoryStream() throws IOException {
|
||||
return newDirectoryStream(acceptAllFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
|
||||
throws IOException
|
||||
{
|
||||
return new ZipDirectoryStream(this, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DirectoryStream<Path> newDirectoryStream(String glob)
|
||||
throws IOException
|
||||
{
|
||||
// avoid creating a matcher if all entries are required.
|
||||
if (glob.equals("*"))
|
||||
return newDirectoryStream();
|
||||
|
||||
// create a matcher and return a filter that uses it.
|
||||
final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob);
|
||||
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
|
||||
@Override
|
||||
public boolean accept(Path entry) {
|
||||
return matcher.matches(entry.getName());
|
||||
}
|
||||
};
|
||||
return newDirectoryStream(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void delete() throws IOException {
|
||||
zfs.deleteFile(getResolvedPath(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteIfExists() throws IOException {
|
||||
zfs.deleteFile(getResolvedPath(), false);
|
||||
}
|
||||
|
||||
ZipFileAttributes getAttributes() throws IOException
|
||||
{
|
||||
ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath());
|
||||
if (zfas == null)
|
||||
throw new NoSuchFileException(toString());
|
||||
return zfas;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Class<V> type,
|
||||
LinkOption... options)
|
||||
{
|
||||
return (V)ZipFileAttributeView.get(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attribute,
|
||||
Object value,
|
||||
LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
String type = null;
|
||||
String attr = null;
|
||||
int colonPos = attribute.indexOf(':');
|
||||
if (colonPos == -1) {
|
||||
type = "basic";
|
||||
attr = attribute;
|
||||
} else {
|
||||
type = attribute.substring(0, colonPos++);
|
||||
attr = attribute.substring(colonPos);
|
||||
}
|
||||
ZipFileAttributeView view = ZipFileAttributeView.get(this, type);
|
||||
if (view == null)
|
||||
throw new UnsupportedOperationException("view <" + view + "> is not supported");
|
||||
view.setAttribute(attr, value);
|
||||
}
|
||||
|
||||
void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
|
||||
throws IOException
|
||||
{
|
||||
zfs.setTimes(getResolvedPath(), mtime, atime, ctime);
|
||||
}
|
||||
|
||||
private Object getAttributesImpl(String attribute, boolean domap)
|
||||
throws IOException
|
||||
{
|
||||
String view = null;
|
||||
String attr = null;
|
||||
int colonPos = attribute.indexOf(':');
|
||||
if (colonPos == -1) {
|
||||
view = "basic";
|
||||
attr = attribute;
|
||||
} else {
|
||||
view = attribute.substring(0, colonPos++);
|
||||
attr = attribute.substring(colonPos);
|
||||
}
|
||||
ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
|
||||
if (zfv == null) {
|
||||
throw new UnsupportedOperationException("view not supported");
|
||||
}
|
||||
return zfv.getAttribute(attr, domap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute, LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
return getAttributesImpl(attribute, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,?> readAttributes(String attribute, LinkOption... options)
|
||||
throws IOException
|
||||
{
|
||||
return (Map<String, ?>)getAttributesImpl(attribute, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStore getFileStore() throws IOException {
|
||||
// each ZipFileSystem only has one root (as requested for now)
|
||||
if (exists())
|
||||
return zfs.getFileStore(this);
|
||||
throw new NoSuchFileException(zfs.getString(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameFile(Path other) throws IOException {
|
||||
if (other == null ||
|
||||
this.getFileSystem() != other.getFileSystem())
|
||||
return false;
|
||||
this.checkAccess();
|
||||
other.checkAccess();
|
||||
return Arrays.equals(this.getResolvedPath(),
|
||||
((ZipPath)other).getResolvedPath());
|
||||
}
|
||||
|
||||
public WatchKey register(
|
||||
WatchService watcher,
|
||||
WatchEvent.Kind<?>[] events,
|
||||
WatchEvent.Modifier... modifiers) {
|
||||
if (watcher == null || events == null || modifiers == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
|
||||
return register(watcher, events, new WatchEvent.Modifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Path> iterator() {
|
||||
return new Iterator<Path>() {
|
||||
private int i = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return (i < getNameCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path next() {
|
||||
if (i < getNameCount()) {
|
||||
Path result = getName(i);
|
||||
i++;
|
||||
return result;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new ReadOnlyFileSystemException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
return zfs.newByteChannel(getResolvedPath(), options, attrs);
|
||||
}
|
||||
|
||||
|
||||
FileChannel newFileChannel(Set<? extends OpenOption> options,
|
||||
FileAttribute<?>... attrs)
|
||||
throws IOException
|
||||
{
|
||||
return zfs.newFileChannel(getResolvedPath(), options, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableByteChannel newByteChannel(OpenOption... options)
|
||||
throws IOException {
|
||||
Set<OpenOption> set = new HashSet<OpenOption>(options.length);
|
||||
Collections.addAll(set, options);
|
||||
return newByteChannel(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(AccessMode... modes) throws IOException {
|
||||
boolean w = false;
|
||||
boolean x = false;
|
||||
for (AccessMode mode : modes) {
|
||||
switch (mode) {
|
||||
case READ:
|
||||
break;
|
||||
case WRITE:
|
||||
w = true;
|
||||
break;
|
||||
case EXECUTE:
|
||||
x = true;
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
ZipFileAttributes attrs = zfs.getFileAttributes(getResolvedPath());
|
||||
if (attrs == null && (path.length != 1 || path[0] != '/'))
|
||||
throw new NoSuchFileException(toString());
|
||||
if (w) {
|
||||
if (zfs.isReadOnly())
|
||||
throw new AccessDeniedException(toString());
|
||||
}
|
||||
if (x)
|
||||
throw new AccessDeniedException(toString());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
if (path.length == 1 && path[0] == '/')
|
||||
return true;
|
||||
try {
|
||||
return zfs.exists(getResolvedPath());
|
||||
} catch (IOException x) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean notExists() {
|
||||
return !exists();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public OutputStream newOutputStream(OpenOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (options.length == 0)
|
||||
return zfs.newOutputStream(getResolvedPath(),
|
||||
CREATE_NEW, WRITE);
|
||||
return zfs.newOutputStream(getResolvedPath(), options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path moveTo(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (this.zfs.provider() == target.getFileSystem().provider() &&
|
||||
this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile()))
|
||||
{
|
||||
zfs.copyFile(true,
|
||||
getResolvedPath(),
|
||||
((ZipPath)target).getResolvedPath(),
|
||||
options);
|
||||
} else {
|
||||
copyToTarget(target, options);
|
||||
delete();
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path copyTo(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
if (this.zfs.provider() == target.getFileSystem().provider() &&
|
||||
this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile()))
|
||||
{
|
||||
zfs.copyFile(false,
|
||||
getResolvedPath(),
|
||||
((ZipPath)target).getResolvedPath(),
|
||||
options);
|
||||
} else {
|
||||
copyToTarget(target, options);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private void copyToTarget(Path target, CopyOption... options)
|
||||
throws IOException
|
||||
{
|
||||
boolean replaceExisting = false;
|
||||
boolean copyAttrs = false;
|
||||
for (CopyOption opt : options) {
|
||||
if (opt == REPLACE_EXISTING)
|
||||
replaceExisting = true;
|
||||
else if (opt == COPY_ATTRIBUTES)
|
||||
copyAttrs = false;
|
||||
}
|
||||
// attributes of source file
|
||||
ZipFileAttributes zfas = getAttributes();
|
||||
// check if target exists
|
||||
boolean exists;
|
||||
if (replaceExisting) {
|
||||
try {
|
||||
target.deleteIfExists();
|
||||
exists = false;
|
||||
} catch (DirectoryNotEmptyException x) {
|
||||
exists = true;
|
||||
}
|
||||
} else {
|
||||
exists = target.exists();
|
||||
}
|
||||
if (exists)
|
||||
throw new FileAlreadyExistsException(target.toString());
|
||||
|
||||
if (zfas.isDirectory()) {
|
||||
// create directory or file
|
||||
target.createDirectory();
|
||||
} else {
|
||||
InputStream is = zfs.newInputStream(getResolvedPath());
|
||||
try {
|
||||
OutputStream os = target.newOutputStream();
|
||||
try {
|
||||
byte[] buf = new byte[8192];
|
||||
int n = 0;
|
||||
while ((n = is.read(buf)) != -1) {
|
||||
os.write(buf, 0, n);
|
||||
}
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
if (copyAttrs) {
|
||||
BasicFileAttributeView view =
|
||||
target.getFileAttributeView(BasicFileAttributeView.class);
|
||||
try {
|
||||
view.setTimes(zfas.lastModifiedTime(), null, null);
|
||||
} catch (IOException x) {
|
||||
// rollback?
|
||||
try {
|
||||
target.delete();
|
||||
} catch (IOException ignore) { }
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
289
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java
Normal file
289
jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.sun.nio.zipfs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen
|
||||
*/
|
||||
|
||||
class ZipUtils {
|
||||
|
||||
/*
|
||||
* Writes a 16-bit short to the output stream in little-endian byte order.
|
||||
*/
|
||||
public static void writeShort(OutputStream os, int v) throws IOException {
|
||||
os.write((v >>> 0) & 0xff);
|
||||
os.write((v >>> 8) & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a 32-bit int to the output stream in little-endian byte order.
|
||||
*/
|
||||
public static void writeInt(OutputStream os, long v) throws IOException {
|
||||
os.write((int)((v >>> 0) & 0xff));
|
||||
os.write((int)((v >>> 8) & 0xff));
|
||||
os.write((int)((v >>> 16) & 0xff));
|
||||
os.write((int)((v >>> 24) & 0xff));
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a 64-bit int to the output stream in little-endian byte order.
|
||||
*/
|
||||
public static void writeLong(OutputStream os, long v) throws IOException {
|
||||
os.write((int)((v >>> 0) & 0xff));
|
||||
os.write((int)((v >>> 8) & 0xff));
|
||||
os.write((int)((v >>> 16) & 0xff));
|
||||
os.write((int)((v >>> 24) & 0xff));
|
||||
os.write((int)((v >>> 32) & 0xff));
|
||||
os.write((int)((v >>> 40) & 0xff));
|
||||
os.write((int)((v >>> 48) & 0xff));
|
||||
os.write((int)((v >>> 56) & 0xff));
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes an array of bytes to the output stream.
|
||||
*/
|
||||
public static void writeBytes(OutputStream os, byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
os.write(b, 0, b.length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes an array of bytes to the output stream.
|
||||
*/
|
||||
public static void writeBytes(OutputStream os, byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
os.write(b, off, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a slash at the end, if it does not have one yet
|
||||
*/
|
||||
public static byte[] toDirectoryPath(byte[] dir) {
|
||||
if (dir.length != 0 && dir[dir.length - 1] != '/') {
|
||||
dir = Arrays.copyOf(dir, dir.length + 1);
|
||||
dir[dir.length - 1] = '/';
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts DOS time to Java time (number of milliseconds since epoch).
|
||||
*/
|
||||
public static long dosToJavaTime(long dtime) {
|
||||
Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
|
||||
(int)(((dtime >> 21) & 0x0f) - 1),
|
||||
(int)((dtime >> 16) & 0x1f),
|
||||
(int)((dtime >> 11) & 0x1f),
|
||||
(int)((dtime >> 5) & 0x3f),
|
||||
(int)((dtime << 1) & 0x3e));
|
||||
return d.getTime();
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts Java time to DOS time.
|
||||
*/
|
||||
public static long javaToDosTime(long time) {
|
||||
Date d = new Date(time);
|
||||
int year = d.getYear() + 1900;
|
||||
if (year < 1980) {
|
||||
return (1 << 21) | (1 << 16);
|
||||
}
|
||||
return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
|
||||
d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
|
||||
d.getSeconds() >> 1;
|
||||
}
|
||||
|
||||
private static final String regexMetaChars = ".^$+{[]|()";
|
||||
private static final String globMetaChars = "\\*?[{";
|
||||
private static boolean isRegexMeta(char c) {
|
||||
return regexMetaChars.indexOf(c) != -1;
|
||||
}
|
||||
private static boolean isGlobMeta(char c) {
|
||||
return globMetaChars.indexOf(c) != -1;
|
||||
}
|
||||
private static char EOL = 0; //TBD
|
||||
private static char next(String glob, int i) {
|
||||
if (i < glob.length()) {
|
||||
return glob.charAt(i);
|
||||
}
|
||||
return EOL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a regex pattern from the given glob expression.
|
||||
*
|
||||
* @throws PatternSyntaxException
|
||||
*/
|
||||
public static String toRegexPattern(String globPattern) {
|
||||
boolean inGroup = false;
|
||||
StringBuilder regex = new StringBuilder("^");
|
||||
|
||||
int i = 0;
|
||||
while (i < globPattern.length()) {
|
||||
char c = globPattern.charAt(i++);
|
||||
switch (c) {
|
||||
case '\\':
|
||||
// escape special characters
|
||||
if (i == globPattern.length()) {
|
||||
throw new PatternSyntaxException("No character to escape",
|
||||
globPattern, i - 1);
|
||||
}
|
||||
char next = globPattern.charAt(i++);
|
||||
if (isGlobMeta(next) || isRegexMeta(next)) {
|
||||
regex.append('\\');
|
||||
}
|
||||
regex.append(next);
|
||||
break;
|
||||
case '/':
|
||||
regex.append(c);
|
||||
break;
|
||||
case '[':
|
||||
// don't match name separator in class
|
||||
regex.append("[[^/]&&[");
|
||||
if (next(globPattern, i) == '^') {
|
||||
// escape the regex negation char if it appears
|
||||
regex.append("\\^");
|
||||
i++;
|
||||
} else {
|
||||
// negation
|
||||
if (next(globPattern, i) == '!') {
|
||||
regex.append('^');
|
||||
i++;
|
||||
}
|
||||
// hyphen allowed at start
|
||||
if (next(globPattern, i) == '-') {
|
||||
regex.append('-');
|
||||
i++;
|
||||
}
|
||||
}
|
||||
boolean hasRangeStart = false;
|
||||
char last = 0;
|
||||
while (i < globPattern.length()) {
|
||||
c = globPattern.charAt(i++);
|
||||
if (c == ']') {
|
||||
break;
|
||||
}
|
||||
if (c == '/') {
|
||||
throw new PatternSyntaxException("Explicit 'name separator' in class",
|
||||
globPattern, i - 1);
|
||||
}
|
||||
// TBD: how to specify ']' in a class?
|
||||
if (c == '\\' || c == '[' ||
|
||||
c == '&' && next(globPattern, i) == '&') {
|
||||
// escape '\', '[' or "&&" for regex class
|
||||
regex.append('\\');
|
||||
}
|
||||
regex.append(c);
|
||||
|
||||
if (c == '-') {
|
||||
if (!hasRangeStart) {
|
||||
throw new PatternSyntaxException("Invalid range",
|
||||
globPattern, i - 1);
|
||||
}
|
||||
if ((c = next(globPattern, i++)) == EOL || c == ']') {
|
||||
break;
|
||||
}
|
||||
if (c < last) {
|
||||
throw new PatternSyntaxException("Invalid range",
|
||||
globPattern, i - 3);
|
||||
}
|
||||
regex.append(c);
|
||||
hasRangeStart = false;
|
||||
} else {
|
||||
hasRangeStart = true;
|
||||
last = c;
|
||||
}
|
||||
}
|
||||
if (c != ']') {
|
||||
throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
|
||||
}
|
||||
regex.append("]]");
|
||||
break;
|
||||
case '{':
|
||||
if (inGroup) {
|
||||
throw new PatternSyntaxException("Cannot nest groups",
|
||||
globPattern, i - 1);
|
||||
}
|
||||
regex.append("(?:(?:");
|
||||
inGroup = true;
|
||||
break;
|
||||
case '}':
|
||||
if (inGroup) {
|
||||
regex.append("))");
|
||||
inGroup = false;
|
||||
} else {
|
||||
regex.append('}');
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
if (inGroup) {
|
||||
regex.append(")|(?:");
|
||||
} else {
|
||||
regex.append(',');
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
if (next(globPattern, i) == '*') {
|
||||
// crosses directory boundaries
|
||||
regex.append(".*");
|
||||
i++;
|
||||
} else {
|
||||
// within directory boundary
|
||||
regex.append("[^/]*");
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
regex.append("[^/]");
|
||||
break;
|
||||
default:
|
||||
if (isRegexMeta(c)) {
|
||||
regex.append('\\');
|
||||
}
|
||||
regex.append(c);
|
||||
}
|
||||
}
|
||||
if (inGroup) {
|
||||
throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
|
||||
}
|
||||
return regex.append('$').toString();
|
||||
}
|
||||
}
|
159
jdk/test/demo/zipfs/Basic.java
Normal file
159
jdk/test/demo/zipfs/Basic.java
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.*;
|
||||
import java.net.URI;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Basic test for zip provider
|
||||
*/
|
||||
|
||||
public class Basic {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path zipfile = Paths.get(args[0]);
|
||||
|
||||
// Test: zip should should be returned in provider list
|
||||
boolean found = false;
|
||||
|
||||
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
|
||||
if (provider.getScheme().equalsIgnoreCase("zip")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
throw new RuntimeException("'zip' provider not installed");
|
||||
|
||||
// Test: FileSystems#newFileSystem(FileRef)
|
||||
Map<String,?> env = new HashMap<String,Object>();
|
||||
FileSystems.newFileSystem(zipfile, env, null).close();
|
||||
|
||||
// Test: FileSystems#newFileSystem(URI)
|
||||
URI uri = URI.create("zip" + zipfile.toUri().toString().substring(4));
|
||||
FileSystem fs = FileSystems.newFileSystem(uri, env, null);
|
||||
|
||||
// Test: exercise toUri method
|
||||
String expected = uri.toString() + "#/foo";
|
||||
String actual = fs.getPath("/foo").toUri().toString();
|
||||
if (!actual.equals(expected)) {
|
||||
throw new RuntimeException("toUri returned '" + actual +
|
||||
"', expected '" + expected + "'");
|
||||
}
|
||||
|
||||
// Test: exercise directory iterator and retrieval of basic attributes
|
||||
Files.walkFileTree(fs.getPath("/"), new FileTreePrinter());
|
||||
|
||||
// Test: DirectoryStream
|
||||
found = false;
|
||||
DirectoryStream<Path> stream = fs.getPath("/").newDirectoryStream();
|
||||
try {
|
||||
for (Path entry: stream) {
|
||||
found = entry.toString().equals("/META-INF/");
|
||||
if (found) break;
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
if (!found)
|
||||
throw new RuntimeException("Expected file not found");
|
||||
|
||||
// Test: copy file from zip file to current (scratch) directory
|
||||
Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
|
||||
if (source.exists()) {
|
||||
Path target = Paths.get(source.getName().toString());
|
||||
source.copyTo(target, StandardCopyOption.REPLACE_EXISTING);
|
||||
try {
|
||||
long s1 = Attributes.readBasicFileAttributes(source).size();
|
||||
long s2 = Attributes.readBasicFileAttributes(target).size();
|
||||
if (s2 != s1)
|
||||
throw new RuntimeException("target size != source size");
|
||||
} finally {
|
||||
target.delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Test: FileStore
|
||||
FileStore store = fs.getPath("/").getFileStore();
|
||||
if (!store.supportsFileAttributeView("basic"))
|
||||
throw new RuntimeException("BasicFileAttributeView should be supported");
|
||||
|
||||
// Test: ClosedFileSystemException
|
||||
fs.close();
|
||||
if (fs.isOpen())
|
||||
throw new RuntimeException("FileSystem should be closed");
|
||||
try {
|
||||
fs.getPath("/missing").checkAccess(AccessMode.READ);
|
||||
} catch (ClosedFileSystemException x) { }
|
||||
}
|
||||
|
||||
// FileVisitor that pretty prints a file tree
|
||||
static class FileTreePrinter extends SimpleFileVisitor<Path> {
|
||||
private int indent = 0;
|
||||
|
||||
private void indent() {
|
||||
StringBuilder sb = new StringBuilder(indent);
|
||||
for (int i=0; i<indent; i++) sb.append(" ");
|
||||
System.out.print(sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
if (dir.getName() != null) {
|
||||
indent();
|
||||
System.out.println(dir.getName() + "/");
|
||||
indent++;
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
indent();
|
||||
System.out.print(file.getName());
|
||||
if (attrs.isRegularFile())
|
||||
System.out.format(" (%d)", attrs.size());
|
||||
System.out.println();
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
|
||||
throws IOException
|
||||
{
|
||||
if (exc != null)
|
||||
super.postVisitDirectory(dir, exc);
|
||||
if (dir.getName() != null)
|
||||
indent--;
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
}
|
416
jdk/test/demo/zipfs/PathOps.java
Normal file
416
jdk/test/demo/zipfs/PathOps.java
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tests path operations for zip provider.
|
||||
*/
|
||||
|
||||
public class PathOps {
|
||||
|
||||
static final java.io.PrintStream out = System.out;
|
||||
static FileSystem fs;
|
||||
|
||||
private String input;
|
||||
private Path path;
|
||||
private Exception exc;
|
||||
|
||||
private PathOps(String s) {
|
||||
out.println();
|
||||
input = s;
|
||||
try {
|
||||
path = fs.getPath(s);
|
||||
out.format("%s -> %s", s, path);
|
||||
} catch (Exception x) {
|
||||
exc = x;
|
||||
out.format("%s -> %s", s, x);
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
||||
Path path() {
|
||||
return path;
|
||||
}
|
||||
|
||||
void fail() {
|
||||
throw new RuntimeException("PathOps failed");
|
||||
}
|
||||
|
||||
void checkPath() {
|
||||
if (path == null) {
|
||||
throw new InternalError("path is null");
|
||||
}
|
||||
}
|
||||
|
||||
void check(Object result, String expected) {
|
||||
out.format("\tExpected: %s\n", expected);
|
||||
out.format("\tActual: %s\n", result);
|
||||
if (result == null) {
|
||||
if (expected == null) return;
|
||||
} else {
|
||||
// compare string representations
|
||||
if (expected != null && result.toString().equals(expected.toString()))
|
||||
return;
|
||||
}
|
||||
fail();
|
||||
}
|
||||
|
||||
void check(Object result, boolean expected) {
|
||||
check(result, Boolean.toString(expected));
|
||||
}
|
||||
|
||||
PathOps root(String expected) {
|
||||
out.println("check root");
|
||||
checkPath();
|
||||
check(path.getRoot(), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps parent(String expected) {
|
||||
out.println("check parent");
|
||||
checkPath();
|
||||
check(path.getParent(), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps name(String expected) {
|
||||
out.println("check name");
|
||||
checkPath();
|
||||
check(path.getName(), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps element(int index, String expected) {
|
||||
out.format("check element %d\n", index);
|
||||
checkPath();
|
||||
check(path.getName(index), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps subpath(int startIndex, int endIndex, String expected) {
|
||||
out.format("test subpath(%d,%d)\n", startIndex, endIndex);
|
||||
checkPath();
|
||||
check(path.subpath(startIndex, endIndex), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps starts(String prefix) {
|
||||
out.format("test startsWith with %s\n", prefix);
|
||||
checkPath();
|
||||
Path s = fs.getPath(prefix);
|
||||
check(path.startsWith(s), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps notStarts(String prefix) {
|
||||
out.format("test not startsWith with %s\n", prefix);
|
||||
checkPath();
|
||||
Path s = fs.getPath(prefix);
|
||||
check(path.startsWith(s), false);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps ends(String suffix) {
|
||||
out.format("test endsWith %s\n", suffix);
|
||||
checkPath();
|
||||
Path s = fs.getPath(suffix);
|
||||
check(path.endsWith(s), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps notEnds(String suffix) {
|
||||
out.format("test not endsWith %s\n", suffix);
|
||||
checkPath();
|
||||
Path s = fs.getPath(suffix);
|
||||
check(path.endsWith(s), false);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps absolute() {
|
||||
out.println("check path is absolute");
|
||||
checkPath();
|
||||
check(path.isAbsolute(), true);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps notAbsolute() {
|
||||
out.println("check path is not absolute");
|
||||
checkPath();
|
||||
check(path.isAbsolute(), false);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps resolve(String other, String expected) {
|
||||
out.format("test resolve %s\n", other);
|
||||
checkPath();
|
||||
check(path.resolve(other), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps relativize(String other, String expected) {
|
||||
out.format("test relativize %s\n", other);
|
||||
checkPath();
|
||||
Path that = fs.getPath(other);
|
||||
check(path.relativize(that), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps normalize(String expected) {
|
||||
out.println("check normalized path");
|
||||
checkPath();
|
||||
check(path.normalize(), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps string(String expected) {
|
||||
out.println("check string representation");
|
||||
checkPath();
|
||||
check(path, expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps invalid() {
|
||||
if (!(exc instanceof InvalidPathException)) {
|
||||
out.println("InvalidPathException not thrown as expected");
|
||||
fail();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static PathOps test(String s) {
|
||||
return new PathOps(s);
|
||||
}
|
||||
|
||||
// -- PathOpss --
|
||||
|
||||
static void header(String s) {
|
||||
out.println();
|
||||
out.println();
|
||||
out.println("-- " + s + " --");
|
||||
}
|
||||
|
||||
static void doPathOpTests() {
|
||||
header("Path operations");
|
||||
|
||||
// all components
|
||||
test("/a/b/c")
|
||||
.root("/")
|
||||
.parent("/a/b")
|
||||
.name("c");
|
||||
|
||||
// root component only
|
||||
test("/")
|
||||
.root("/")
|
||||
.parent(null)
|
||||
.name(null);
|
||||
|
||||
// no root component
|
||||
test("a/b")
|
||||
.root(null)
|
||||
.parent("a")
|
||||
.name("b");
|
||||
|
||||
// name component only
|
||||
test("foo")
|
||||
.root(null)
|
||||
.parent(null)
|
||||
.name("foo");
|
||||
|
||||
// startsWith
|
||||
test("/")
|
||||
.starts("/")
|
||||
.notStarts("/foo");
|
||||
test("/foo")
|
||||
.starts("/")
|
||||
.starts("/foo")
|
||||
.notStarts("/f");
|
||||
test("/foo/bar")
|
||||
.starts("/")
|
||||
.starts("/foo")
|
||||
.starts("/foo/bar")
|
||||
.notStarts("/f")
|
||||
.notStarts("foo")
|
||||
.notStarts("foo/bar");
|
||||
test("foo")
|
||||
.starts("foo")
|
||||
.notStarts("f");
|
||||
test("foo/bar")
|
||||
.starts("foo")
|
||||
.starts("foo/bar")
|
||||
.notStarts("f")
|
||||
.notStarts("/foo")
|
||||
.notStarts("/foo/bar");
|
||||
|
||||
// endsWith
|
||||
test("/")
|
||||
.ends("/")
|
||||
.notEnds("foo")
|
||||
.notEnds("/foo");
|
||||
test("/foo")
|
||||
.ends("foo")
|
||||
.ends("/foo")
|
||||
.notEnds("/");
|
||||
test("/foo/bar")
|
||||
.ends("bar")
|
||||
.ends("foo/bar")
|
||||
.ends("/foo/bar")
|
||||
.notEnds("/bar");
|
||||
test("foo")
|
||||
.ends("foo");
|
||||
test("foo/bar")
|
||||
.ends("bar")
|
||||
.ends("foo/bar");
|
||||
|
||||
// elements
|
||||
test("a/b/c")
|
||||
.element(0,"a")
|
||||
.element(1,"b")
|
||||
.element(2,"c");
|
||||
|
||||
// isAbsolute
|
||||
test("/")
|
||||
.absolute();
|
||||
test("/tmp")
|
||||
.absolute();
|
||||
test("tmp")
|
||||
.notAbsolute();
|
||||
|
||||
// resolve
|
||||
test("/tmp")
|
||||
.resolve("foo", "/tmp/foo")
|
||||
.resolve("/foo", "/foo");
|
||||
test("tmp")
|
||||
.resolve("foo", "tmp/foo")
|
||||
.resolve("/foo", "/foo");
|
||||
|
||||
// relativize
|
||||
test("/a/b/c")
|
||||
.relativize("/a/b/c", null)
|
||||
.relativize("/a/b/c/d/e", "d/e")
|
||||
.relativize("/a/x", "../../x");
|
||||
|
||||
// normalize
|
||||
test("/")
|
||||
.normalize("/");
|
||||
test("foo")
|
||||
.normalize("foo");
|
||||
test("/foo")
|
||||
.normalize("/foo");
|
||||
test(".")
|
||||
.normalize(null);
|
||||
test("..")
|
||||
.normalize("..");
|
||||
test("/..")
|
||||
.normalize("/");
|
||||
test("/../..")
|
||||
.normalize("/");
|
||||
test("foo/.")
|
||||
.normalize("foo");
|
||||
test("./foo")
|
||||
.normalize("foo");
|
||||
test("foo/..")
|
||||
.normalize(null);
|
||||
test("../foo")
|
||||
.normalize("../foo");
|
||||
test("../../foo")
|
||||
.normalize("../../foo");
|
||||
test("foo/bar/..")
|
||||
.normalize("foo");
|
||||
test("foo/bar/gus/../..")
|
||||
.normalize("foo");
|
||||
test("/foo/bar/gus/../..")
|
||||
.normalize("/foo");
|
||||
|
||||
// invalid
|
||||
test("foo\u0000bar")
|
||||
.invalid();
|
||||
test("\u0000foo")
|
||||
.invalid();
|
||||
test("bar\u0000")
|
||||
.invalid();
|
||||
test("//foo\u0000bar")
|
||||
.invalid();
|
||||
test("//\u0000foo")
|
||||
.invalid();
|
||||
test("//bar\u0000")
|
||||
.invalid();
|
||||
|
||||
// normalization
|
||||
test("//foo//bar")
|
||||
.string("/foo/bar")
|
||||
.root("/")
|
||||
.parent("/foo")
|
||||
.name("bar");
|
||||
}
|
||||
|
||||
static void npes() {
|
||||
header("NullPointerException");
|
||||
|
||||
Path path = fs.getPath("foo");
|
||||
|
||||
try {
|
||||
path.resolve((String)null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
try {
|
||||
path.relativize(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
try {
|
||||
path.compareTo(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
try {
|
||||
path.startsWith(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
try {
|
||||
path.endsWith(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
Path zipfile = Paths.get(args[0]);
|
||||
Map<String,?> env = new HashMap<String,Object>();
|
||||
fs = FileSystems.newFileSystem(zipfile, env, null);
|
||||
npes();
|
||||
doPathOpTests();
|
||||
fs.close();
|
||||
}
|
||||
}
|
633
jdk/test/demo/zipfs/ZipFSTester.java
Normal file
633
jdk/test/demo/zipfs/ZipFSTester.java
Normal file
@ -0,0 +1,633 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
/*
|
||||
* Tests various zipfs operations.
|
||||
*/
|
||||
|
||||
public class ZipFSTester {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
FileSystem fs = null;
|
||||
try {
|
||||
fs = newZipFileSystem(Paths.get(args[0]), new HashMap<String, Object>());
|
||||
test(fs);
|
||||
test2(fs); // more tests
|
||||
} finally {
|
||||
if (fs != null)
|
||||
fs.close();
|
||||
}
|
||||
}
|
||||
|
||||
static void test(FileSystem fs)
|
||||
throws Exception
|
||||
{
|
||||
Random rdm = new Random();
|
||||
|
||||
// clone a fs and test on it
|
||||
Path tmpfsPath = getTempPath();
|
||||
Map<String, Object> env = new HashMap<String, Object>();
|
||||
env.put("createNew", true);
|
||||
FileSystem fs0 = newZipFileSystem(tmpfsPath, env);
|
||||
z2zcopy(fs, fs0, "/", 0);
|
||||
fs0.close(); // sync to file
|
||||
|
||||
fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>());
|
||||
|
||||
try {
|
||||
// prepare a src
|
||||
Path src = getTempPath();
|
||||
String tmpName = src.toString();
|
||||
OutputStream os = src.newOutputStream();
|
||||
byte[] bits = new byte[12345];
|
||||
rdm.nextBytes(bits);
|
||||
os.write(bits);
|
||||
os.close();
|
||||
|
||||
// copyin
|
||||
Path dst = getPathWithParents(fs, tmpName);
|
||||
src.copyTo(dst);
|
||||
checkEqual(src, dst);
|
||||
|
||||
// copy
|
||||
Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
|
||||
"/efg" + rdm.nextInt(100) + "/foo.class");
|
||||
dst.copyTo(dst2);
|
||||
//dst.moveTo(dst2);
|
||||
checkEqual(src, dst2);
|
||||
|
||||
// delete
|
||||
dst.delete();
|
||||
if (dst.exists())
|
||||
throw new RuntimeException("Failed!");
|
||||
|
||||
// moveout
|
||||
Path dst3 = Paths.get(tmpName + "_Tmp");
|
||||
dst2.moveTo(dst3);
|
||||
checkEqual(src, dst3);
|
||||
|
||||
// delete
|
||||
if (dst2.exists())
|
||||
throw new RuntimeException("Failed!");
|
||||
dst3.delete();
|
||||
if (dst3.exists())
|
||||
throw new RuntimeException("Failed!");
|
||||
|
||||
// newInputStream on dir
|
||||
Path parent = dst2.getParent();
|
||||
try {
|
||||
parent.newInputStream();
|
||||
throw new RuntimeException("Failed");
|
||||
} catch (FileSystemException e) {
|
||||
e.printStackTrace(); // expected fse
|
||||
}
|
||||
|
||||
// rmdirs
|
||||
try {
|
||||
rmdirs(parent);
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
|
||||
// newFileChannel() copy in, out and verify via fch
|
||||
fchCopy(src, dst); // in
|
||||
checkEqual(src, dst);
|
||||
Path tmp = Paths.get(tmpName + "_Tmp");
|
||||
fchCopy(dst, tmp); // out
|
||||
checkEqual(src, tmp);
|
||||
tmp.delete();
|
||||
|
||||
// test channels
|
||||
channel(fs, dst);
|
||||
dst.delete();
|
||||
src.delete();
|
||||
} finally {
|
||||
if (fs != null)
|
||||
fs.close();
|
||||
if (tmpfsPath.exists())
|
||||
tmpfsPath.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static void test2(FileSystem fs) throws Exception {
|
||||
|
||||
Path fs1Path = getTempPath();
|
||||
Path fs2Path = getTempPath();
|
||||
Path fs3Path = getTempPath();
|
||||
|
||||
if (fs1Path.exists())
|
||||
fs1Path.delete();
|
||||
if (fs2Path.exists())
|
||||
fs2Path.delete();
|
||||
if (fs3Path.exists())
|
||||
fs3Path.delete();
|
||||
|
||||
// create a new filesystem, copy everything from fs
|
||||
Map<String, Object> env = new HashMap<String, Object>();
|
||||
env.put("createNew", true);
|
||||
FileSystem fs0 = newZipFileSystem(fs1Path, env);
|
||||
|
||||
final FileSystem fs2 = newZipFileSystem(fs2Path, env);
|
||||
final FileSystem fs3 = newZipFileSystem(fs3Path, env);
|
||||
|
||||
System.out.println("copy src: fs -> fs0...");
|
||||
z2zcopy(fs, fs0, "/", 0); // copy fs -> fs1
|
||||
fs0.close(); // dump to file
|
||||
|
||||
System.out.println("open fs0 as fs1");
|
||||
env = new HashMap<String, Object>();
|
||||
final FileSystem fs1 = newZipFileSystem(fs1Path, env);
|
||||
|
||||
System.out.println("listing...");
|
||||
final ArrayList<String> files = new ArrayList<>();
|
||||
final ArrayList<String> dirs = new ArrayList<>();
|
||||
list(fs1.getPath("/"), files, dirs);
|
||||
|
||||
Thread t0 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
List<String> list = new ArrayList<>(dirs);
|
||||
Collections.shuffle(list);
|
||||
for (String path : list) {
|
||||
try {
|
||||
z2zcopy(fs1, fs2, path, 0);
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Thread t1 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
List<String> list = new ArrayList<>(dirs);
|
||||
Collections.shuffle(list);
|
||||
for (String path : list) {
|
||||
try {
|
||||
z2zcopy(fs1, fs2, path, 1);
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Thread t2 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
List<String> list = new ArrayList<>(dirs);
|
||||
Collections.shuffle(list);
|
||||
for (String path : list) {
|
||||
try {
|
||||
z2zcopy(fs1, fs2, path, 2);
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Thread t3 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
List<String> list = new ArrayList<>(files);
|
||||
Collections.shuffle(list);
|
||||
while (!list.isEmpty()) {
|
||||
Iterator<String> itr = list.iterator();
|
||||
while (itr.hasNext()) {
|
||||
String path = itr.next();
|
||||
try {
|
||||
if (fs2.getPath(path).exists()) {
|
||||
z2zmove(fs2, fs3, path);
|
||||
itr.remove();
|
||||
}
|
||||
} catch (FileAlreadyExistsException x){
|
||||
itr.remove();
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
System.out.println("copying/removing...");
|
||||
t0.start(); t1.start(); t2.start(); t3.start();
|
||||
t0.join(); t1.join(); t2.join(); t3.join();
|
||||
|
||||
System.out.println("closing: fs1, fs2");
|
||||
fs1.close();
|
||||
fs2.close();
|
||||
|
||||
int failed = 0;
|
||||
System.out.println("checkEqual: fs vs fs3");
|
||||
for (String path : files) {
|
||||
try {
|
||||
checkEqual(fs.getPath(path), fs3.getPath(path));
|
||||
} catch (IOException x) {
|
||||
//x.printStackTrace();
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
System.out.println("closing: fs3");
|
||||
fs3.close();
|
||||
|
||||
System.out.println("opening: fs3 as fs4");
|
||||
FileSystem fs4 = newZipFileSystem(fs3Path, env);
|
||||
|
||||
|
||||
ArrayList<String> files2 = new ArrayList<>();
|
||||
ArrayList<String> dirs2 = new ArrayList<>();
|
||||
list(fs4.getPath("/"), files2, dirs2);
|
||||
|
||||
System.out.println("checkEqual: fs vs fs4");
|
||||
for (String path : files2) {
|
||||
checkEqual(fs.getPath(path), fs4.getPath(path));
|
||||
}
|
||||
System.out.println("walking: fs4");
|
||||
walk(fs4.getPath("/"));
|
||||
System.out.println("closing: fs4");
|
||||
fs4.close();
|
||||
|
||||
System.out.printf("failed=%d%n", failed);
|
||||
|
||||
fs1Path.delete();
|
||||
fs2Path.delete();
|
||||
fs3Path.delete();
|
||||
}
|
||||
|
||||
private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
|
||||
throws IOException
|
||||
{
|
||||
return FileSystems.newFileSystem(
|
||||
URI.create("zip" +
|
||||
path.toUri().toString().substring(4)),
|
||||
env,
|
||||
null);
|
||||
}
|
||||
|
||||
private static Path getTempPath() throws IOException
|
||||
{
|
||||
File tmp = File.createTempFile("testzipfs_", "zip");
|
||||
tmp.delete(); // we need a clean path, no file
|
||||
return tmp.toPath();
|
||||
}
|
||||
|
||||
private static void list(Path path, List<String> files, List<String> dirs )
|
||||
throws IOException
|
||||
{
|
||||
if (Attributes.readBasicFileAttributes(path).isDirectory()) {
|
||||
DirectoryStream<Path> ds = path.newDirectoryStream();
|
||||
for (Path child : ds)
|
||||
list(child, files, dirs);
|
||||
ds.close();
|
||||
dirs.add(path.toString());
|
||||
} else {
|
||||
files.add(path.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void z2zcopy(FileSystem src, FileSystem dst, String path,
|
||||
int method)
|
||||
throws IOException
|
||||
{
|
||||
Path srcPath = src.getPath(path);
|
||||
Path dstPath = dst.getPath(path);
|
||||
|
||||
if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
|
||||
if (!dstPath.exists()) {
|
||||
try {
|
||||
mkdirs(dstPath);
|
||||
} catch (FileAlreadyExistsException x) {}
|
||||
}
|
||||
DirectoryStream<Path> ds = srcPath.newDirectoryStream();
|
||||
for (Path child : ds) {
|
||||
z2zcopy(src, dst,
|
||||
path + (path.endsWith("/")?"":"/") + child.getName(),
|
||||
method);
|
||||
}
|
||||
ds.close();
|
||||
} else {
|
||||
try {
|
||||
if (dstPath.exists())
|
||||
return;
|
||||
switch (method) {
|
||||
case 0:
|
||||
srcPath.copyTo(dstPath);
|
||||
break;
|
||||
case 1:
|
||||
chCopy(srcPath, dstPath);
|
||||
break;
|
||||
case 2:
|
||||
//fchCopy(srcPath, dstPath);
|
||||
streamCopy(srcPath, dstPath);
|
||||
break;
|
||||
}
|
||||
} catch (FileAlreadyExistsException x) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static void z2zmove(FileSystem src, FileSystem dst, String path)
|
||||
throws IOException
|
||||
{
|
||||
Path srcPath = src.getPath(path);
|
||||
Path dstPath = dst.getPath(path);
|
||||
|
||||
if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
|
||||
if (!dstPath.exists())
|
||||
mkdirs(dstPath);
|
||||
DirectoryStream<Path> ds = srcPath.newDirectoryStream();
|
||||
for (Path child : ds) {
|
||||
z2zmove(src, dst,
|
||||
path + (path.endsWith("/")?"":"/") + child.getName());
|
||||
}
|
||||
ds.close();
|
||||
} else {
|
||||
//System.out.println("moving..." + path);
|
||||
Path parent = dstPath.getParent();
|
||||
if (parent != null && parent.notExists())
|
||||
mkdirs(parent);
|
||||
srcPath.moveTo(dstPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void walk(Path path) throws IOException
|
||||
{
|
||||
Files.walkFileTree(
|
||||
path,
|
||||
new SimpleFileVisitor<Path>() {
|
||||
private int indent = 0;
|
||||
private void indent() {
|
||||
int n = 0;
|
||||
while (n++ < indent)
|
||||
System.out.printf(" ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
indent();
|
||||
System.out.printf("%s%n", file.getName().toString());
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs)
|
||||
{
|
||||
indent();
|
||||
System.out.printf("[%s]%n", dir.toString());
|
||||
indent += 2;
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir,
|
||||
IOException ioe)
|
||||
throws IOException
|
||||
{
|
||||
indent -= 2;
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void mkdirs(Path path) throws IOException {
|
||||
path = path.toAbsolutePath();
|
||||
Path parent = path.getParent();
|
||||
if (parent != null) {
|
||||
if (parent.notExists())
|
||||
mkdirs(parent);
|
||||
}
|
||||
path.createDirectory();
|
||||
}
|
||||
|
||||
private static void rmdirs(Path path) throws IOException {
|
||||
while (path != null && path.getNameCount() != 0) {
|
||||
path.delete();
|
||||
path = path.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
// check the content of two paths are equal
|
||||
private static void checkEqual(Path src, Path dst) throws IOException
|
||||
{
|
||||
//System.out.printf("checking <%s> vs <%s>...%n",
|
||||
// src.toString(), dst.toString());
|
||||
|
||||
//streams
|
||||
InputStream isSrc = src.newInputStream();
|
||||
InputStream isDst = dst.newInputStream();
|
||||
byte[] bufSrc = new byte[8192];
|
||||
byte[] bufDst = new byte[8192];
|
||||
|
||||
try {
|
||||
int nSrc = 0;
|
||||
while ((nSrc = isSrc.read(bufSrc)) != -1) {
|
||||
int nDst = 0;
|
||||
while (nDst < nSrc) {
|
||||
int n = isDst.read(bufDst, nDst, nSrc - nDst);
|
||||
if (n == -1) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nDst += n;
|
||||
}
|
||||
while (--nSrc >= 0) {
|
||||
if (bufSrc[nSrc] != bufDst[nSrc]) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nSrc--;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
isSrc.close();
|
||||
isDst.close();
|
||||
}
|
||||
|
||||
// channels
|
||||
SeekableByteChannel chSrc = src.newByteChannel();
|
||||
SeekableByteChannel chDst = dst.newByteChannel();
|
||||
if (chSrc.size() != chDst.size()) {
|
||||
System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
|
||||
chSrc.toString(), chSrc.size(),
|
||||
chDst.toString(), chDst.size());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
ByteBuffer bbSrc = ByteBuffer.allocate(8192);
|
||||
ByteBuffer bbDst = ByteBuffer.allocate(8192);
|
||||
|
||||
try {
|
||||
int nSrc = 0;
|
||||
while ((nSrc = chSrc.read(bbSrc)) != -1) {
|
||||
int nDst = chDst.read(bbDst);
|
||||
if (nSrc != nDst) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
while (--nSrc >= 0) {
|
||||
if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
|
||||
System.out.printf("checking <%s> vs <%s>...%n",
|
||||
src.toString(), dst.toString());
|
||||
throw new RuntimeException("CHECK FAILED!");
|
||||
}
|
||||
nSrc--;
|
||||
}
|
||||
bbSrc.flip();
|
||||
bbDst.flip();
|
||||
}
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
} finally {
|
||||
chSrc.close();
|
||||
chDst.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void fchCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
Set<OpenOption> read = new HashSet<>();
|
||||
read.add(READ);
|
||||
Set<OpenOption> openwrite = new HashSet<>();
|
||||
openwrite.add(CREATE_NEW);
|
||||
openwrite.add(WRITE);
|
||||
|
||||
FileChannel srcFc = src.getFileSystem()
|
||||
.provider()
|
||||
.newFileChannel(src, read);
|
||||
FileChannel dstFc = dst.getFileSystem()
|
||||
.provider()
|
||||
.newFileChannel(dst, openwrite);
|
||||
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.allocate(8192);
|
||||
while (srcFc.read(bb) >= 0) {
|
||||
bb.flip();
|
||||
dstFc.write(bb);
|
||||
bb.clear();
|
||||
}
|
||||
} finally {
|
||||
srcFc.close();
|
||||
dstFc.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void chCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
Set<OpenOption> read = new HashSet<>();
|
||||
read.add(READ);
|
||||
Set<OpenOption> openwrite = new HashSet<>();
|
||||
openwrite.add(CREATE_NEW);
|
||||
openwrite.add(WRITE);
|
||||
|
||||
SeekableByteChannel srcCh = src.newByteChannel(read);
|
||||
SeekableByteChannel dstCh = dst.newByteChannel(openwrite);
|
||||
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.allocate(8192);
|
||||
while (srcCh.read(bb) >= 0) {
|
||||
bb.flip();
|
||||
dstCh.write(bb);
|
||||
bb.clear();
|
||||
}
|
||||
} finally {
|
||||
srcCh.close();
|
||||
dstCh.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void streamCopy(Path src, Path dst) throws IOException
|
||||
{
|
||||
InputStream isSrc = src.newInputStream();
|
||||
OutputStream osDst = dst.newOutputStream();
|
||||
byte[] buf = new byte[8192];
|
||||
try {
|
||||
int n = 0;
|
||||
while ((n = isSrc.read(buf)) != -1) {
|
||||
osDst.write(buf, 0, n);
|
||||
}
|
||||
} finally {
|
||||
isSrc.close();
|
||||
osDst.close();
|
||||
}
|
||||
}
|
||||
|
||||
static void channel(FileSystem fs, Path path)
|
||||
throws Exception
|
||||
{
|
||||
System.out.println("test ByteChannel...");
|
||||
SeekableByteChannel sbc = path.newByteChannel();
|
||||
Set<OpenOption> read = new HashSet<>();
|
||||
read.add(READ);
|
||||
System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
|
||||
ByteBuffer bb = ByteBuffer.allocate((int)sbc.size());
|
||||
int n = sbc.read(bb);
|
||||
System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n",
|
||||
n, sbc.position(), sbc.size());
|
||||
ByteBuffer bb2 = ByteBuffer.allocate((int)sbc.size());
|
||||
int N = 120;
|
||||
sbc.close();
|
||||
|
||||
// sbc.position(pos) is not supported in current version
|
||||
// try the FileChannel
|
||||
sbc = fs.provider().newFileChannel(path, read);
|
||||
sbc.position(N);
|
||||
System.out.printf(" sbc[2]: pos=%d, size=%d%n",
|
||||
sbc.position(), sbc.size());
|
||||
bb2.limit(100);
|
||||
n = sbc.read(bb2);
|
||||
System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n",
|
||||
n, sbc.position(), sbc.size());
|
||||
System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
|
||||
N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
|
||||
sbc.close();
|
||||
}
|
||||
|
||||
// create parents if does not exist
|
||||
static Path getPathWithParents(FileSystem fs, String name)
|
||||
throws Exception
|
||||
{
|
||||
Path path = fs.getPath(name);
|
||||
Path parent = path.getParent();
|
||||
if (parent != null && parent.notExists())
|
||||
mkdirs(parent);
|
||||
return path;
|
||||
}
|
||||
}
|
73
jdk/test/demo/zipfs/basic.sh
Normal file
73
jdk/test/demo/zipfs/basic.sh
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code 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
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
# @test
|
||||
# @bug 6990846
|
||||
# @summary Test ZipFileSystem demo
|
||||
# @build Basic PathOps ZipFSTester
|
||||
# @run shell basic.sh
|
||||
|
||||
if [ -z "${TESTJAVA}" ]; then
|
||||
echo "Test must be run with jtreg"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ZIPFS="${TESTJAVA}/demo/nio/zipfs/zipfs.jar"
|
||||
if [ ! -r "${ZIPFS}" ]; then
|
||||
echo "${ZIPFS} not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Windows_* )
|
||||
CLASSPATH="${TESTCLASSES};${ZIPFS}"
|
||||
;;
|
||||
* )
|
||||
CLASSPATH="${TESTCLASSES}:${ZIPFS}"
|
||||
;;
|
||||
esac
|
||||
export CLASSPATH
|
||||
|
||||
failures=0
|
||||
|
||||
go() {
|
||||
echo ""
|
||||
${TESTJAVA}/bin/java $1 $2 $3 2>&1
|
||||
if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
|
||||
}
|
||||
|
||||
# Run the tests
|
||||
|
||||
go Basic "${ZIPFS}"
|
||||
go PathOps "${ZIPFS}"
|
||||
go ZipFSTester "${ZIPFS}"
|
||||
|
||||
#
|
||||
# Results
|
||||
#
|
||||
|
||||
if [ $failures -gt 0 ];
|
||||
then echo "$failures tests failed";
|
||||
else echo "All tests passed";
|
||||
fi
|
||||
exit $failures
|
Loading…
x
Reference in New Issue
Block a user