mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-20 02:17:53 +00:00
Merge
This commit is contained in:
commit
0ffa1c4042
2
.hgtags
2
.hgtags
@ -86,3 +86,5 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99
|
||||
e02b4d709e177d08d56130a4bc68061e4bbacc7d jdk7-b109
|
||||
a6442d6bc38a44152e0662688213ce4d2701f42a jdk7-b110
|
||||
69f3edf083477955b5bd2f754252c7504167d8e1 jdk7-b111
|
||||
f960f117f1623629f64203e2b09a92a8f6f14ff5 jdk7-b112
|
||||
1fee41c7ed2b3388970a756a85aa693c0de8407a jdk7-b113
|
||||
|
||||
@ -86,3 +86,5 @@ f8be576feefce0c6695f188ef97ec16b73ad9cfd jdk7-b104
|
||||
81dfc728d7bb7e1fff4a4dc6d0f7cea5a3315667 jdk7-b109
|
||||
2a02d4a6955c7c078aee9a604cb3be409800d82c jdk7-b110
|
||||
9702d6fef68e17533ee7fcf5923b11ead3e912ce jdk7-b111
|
||||
b852103caf73da70068473777ae867a457bb3ae1 jdk7-b112
|
||||
c1df968c4527bfab5f97662a89245f15d12d378b jdk7-b113
|
||||
|
||||
16
Makefile
16
Makefile
@ -558,9 +558,12 @@ endif
|
||||
# rule to test
|
||||
################################################################
|
||||
|
||||
.NOTPARALLEL: test
|
||||
.NOTPARALLEL: test_run
|
||||
|
||||
test: test_clean test_start test_summary
|
||||
test:
|
||||
$(MAKE) test_run
|
||||
|
||||
test_run: test_clean test_start test_summary
|
||||
|
||||
test_start:
|
||||
@$(ECHO) "Tests started at `$(DATE)`"
|
||||
@ -586,7 +589,7 @@ test_summary: $(OUTPUTDIR)/test_failures.txt
|
||||
# Get failure list from log
|
||||
$(OUTPUTDIR)/test_failures.txt: $(OUTPUTDIR)/test_log.txt
|
||||
@$(RM) $@
|
||||
@( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) > $@
|
||||
@( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) | $(NAWK) 'length>0' > $@
|
||||
|
||||
# Get log file of all tests run
|
||||
JDK_TO_TEST := $(shell \
|
||||
@ -598,10 +601,11 @@ JDK_TO_TEST := $(shell \
|
||||
$(ECHO) "$(PRODUCT_HOME)"; \
|
||||
fi \
|
||||
)
|
||||
TEST_TARGETS=all
|
||||
$(OUTPUTDIR)/test_log.txt:
|
||||
$(RM) $@
|
||||
( $(CD) test && \
|
||||
$(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) \
|
||||
( $(CD) test && \
|
||||
$(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) $(TEST_TARGETS) \
|
||||
) | tee $@
|
||||
|
||||
################################################################
|
||||
@ -614,7 +618,7 @@ include ./make/jprt.gmk
|
||||
# PHONY
|
||||
################################################################
|
||||
|
||||
.PHONY: all test test_start test_summary test_clean \
|
||||
.PHONY: all test test_run test_start test_summary test_clean \
|
||||
generic_build_repo_series \
|
||||
what clobber insane \
|
||||
dev dev-build dev-sanity dev-clobber \
|
||||
|
||||
@ -86,3 +86,5 @@ a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
|
||||
c3dd858e09b20206459d9e7b0ead99d27ab00eab jdk7-b109
|
||||
0e1f80fda2271f53d4bbb59ec3f301dfbcef6a0a jdk7-b110
|
||||
640fa4d4e2ad4c2d7e4815c955026740d8c52b7a jdk7-b111
|
||||
cc67fdc4fee9a5b25caee4e71b51a8ff24ae7d1a jdk7-b112
|
||||
a89a6c5be9d1a754868d3d359cbf7ad36aa95631 jdk7-b113
|
||||
|
||||
@ -121,3 +121,5 @@ e44a93947ccbfce712b51725f313163606f15486 jdk7-b108
|
||||
cc4bb3022b3144dc5db0805b9ef6c7eff2aa3b81 jdk7-b109
|
||||
2f25f2b8de2700a1822463b1bd3d02b5e218018f jdk7-b110
|
||||
07b042e13dde4f3479ba9ec55120fcd5e8623323 jdk7-b111
|
||||
5511edd5d719f3fc9fdd04879482026a3d2c8652 jdk7-b112
|
||||
beef35b96b81129c375d572357fb9548d9020db1 jdk7-b113
|
||||
|
||||
@ -86,3 +86,5 @@ d42c4acb6424a094bdafe2ad9c8c1c7ca7fb7b7e jdk7-b104
|
||||
0f382d6120fc07aed2209484a42458cabf405916 jdk7-b109
|
||||
d422dbdd09766269344b796b3a46a5b3f74557e1 jdk7-b110
|
||||
8106c747067c905d814a737a57fea0e29057b33f jdk7-b111
|
||||
1b05254242881527b4d5d711295c0fe708c8823a jdk7-b112
|
||||
bc0c84ce54c34d3e8b0604b94da0d7c75c26755e jdk7-b113
|
||||
|
||||
@ -86,3 +86,5 @@ b1ca39340238a239ba6d8489ad5315215e1366ca jdk7-b108
|
||||
4f626e0d70bda68c76bbd0e89d2bc2407f979736 jdk7-b109
|
||||
95ecac35fb11530752bd0404c9bf02bcfb30990e jdk7-b110
|
||||
2575ebca96c7fb1b78f6ae025a97321210aba309 jdk7-b111
|
||||
8e0f0054817f0f73fb33e80fb1333fb45b1d513d jdk7-b112
|
||||
d35c94fd22362f478f75b4bfcd2bef6a83cb9b3f jdk7-b113
|
||||
|
||||
@ -86,3 +86,5 @@ b91ef6b60f4e19bf4592c6dd594c9bac62487519 jdk7-b106
|
||||
ab0d3f54a63f2aadfcdd2e14b81f79362ce454e2 jdk7-b109
|
||||
176586cd040e4dd17a5ff6e91f72df10d7442453 jdk7-b110
|
||||
fb63a2688db807a73e2a3de7d9bab298f1bff0e8 jdk7-b111
|
||||
b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
|
||||
61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113
|
||||
|
||||
@ -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
|
||||
|
||||
@ -80,7 +80,12 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
|
||||
vpath %.c $(SHARE_SRC)/native/sun/java2d
|
||||
|
||||
ifeq ($(PLATFORM), windows)
|
||||
OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
|
||||
OTHER_CFLAGS += -DCMS_IS_WINDOWS_
|
||||
|
||||
ifeq ($(COMPILER_VERSION), VS2003)
|
||||
OTHER_CFLAGS += -Dsqrtf=sqrt
|
||||
endif
|
||||
|
||||
OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
|
||||
OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
|
||||
-I$(SHARE_SRC)/native/sun/awt/debug
|
||||
|
||||
@ -1068,7 +1068,7 @@ public class Dialog extends Window {
|
||||
modalityPushed();
|
||||
try {
|
||||
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||
secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000);
|
||||
secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 0);
|
||||
if (!secondaryLoop.enter()) {
|
||||
secondaryLoop = null;
|
||||
}
|
||||
|
||||
@ -142,6 +142,9 @@ public abstract class KeyboardFocusManager
|
||||
public void removeLastFocusRequest(Component heavyweight) {
|
||||
KeyboardFocusManager.removeLastFocusRequest(heavyweight);
|
||||
}
|
||||
public void setMostRecentFocusOwner(Window window, Component component) {
|
||||
KeyboardFocusManager.setMostRecentFocusOwner(window, component);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ import java.awt.Event;
|
||||
* in the range from {@code ACTION_FIRST} to {@code ACTION_LAST}.
|
||||
*
|
||||
* @see ActionListener
|
||||
* @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/eventmodel.html">Tutorial: Java 1.1 Event Model</a>
|
||||
* @see <a href="http://java.sun.com/docs/books/tutorial/uiswing/events/actionlistener.html">Tutorial: How to Write an Action Listener</a>
|
||||
*
|
||||
* @author Carl Quinn
|
||||
* @since 1.1
|
||||
|
||||
@ -937,14 +937,22 @@ public abstract class SampleModel
|
||||
int iArray[], DataBuffer data) {
|
||||
int pixels[];
|
||||
int Offset=0;
|
||||
int x1 = x + w;
|
||||
int y1 = y + h;
|
||||
|
||||
if (x < 0 || x1 < x || x1 > width ||
|
||||
y < 0 || y1 < y || y1 > height)
|
||||
{
|
||||
throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
|
||||
}
|
||||
|
||||
if (iArray != null)
|
||||
pixels = iArray;
|
||||
else
|
||||
pixels = new int[w * h];
|
||||
|
||||
for(int i=y; i<(h+y); i++) {
|
||||
for (int j=x; j<(w+x); j++) {
|
||||
for(int i=y; i<y1; i++) {
|
||||
for (int j=x; j<x1; j++) {
|
||||
pixels[Offset++] = getSample(j, i, b, data);
|
||||
}
|
||||
}
|
||||
@ -978,14 +986,22 @@ public abstract class SampleModel
|
||||
DataBuffer data) {
|
||||
float pixels[];
|
||||
int Offset=0;
|
||||
int x1 = x + w;
|
||||
int y1 = y + h;
|
||||
|
||||
if (x < 0 || x1 < x || x1 > width ||
|
||||
y < 0 || y1 < y || y1 > height)
|
||||
{
|
||||
throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
|
||||
}
|
||||
|
||||
if (fArray != null)
|
||||
pixels = fArray;
|
||||
else
|
||||
pixels = new float[w * h];
|
||||
|
||||
for (int i=y; i<(h+y); i++) {
|
||||
for (int j=x; j<(w+x); j++) {
|
||||
for (int i=y; i<y1; i++) {
|
||||
for (int j=x; j<x1; j++) {
|
||||
pixels[Offset++] = getSampleFloat(j, i, b, data);
|
||||
}
|
||||
}
|
||||
@ -1019,14 +1035,22 @@ public abstract class SampleModel
|
||||
DataBuffer data) {
|
||||
double pixels[];
|
||||
int Offset=0;
|
||||
int x1 = x + w;
|
||||
int y1 = y + h;
|
||||
|
||||
if (x < 0 || x1 < x || x1 > width ||
|
||||
y < 0 || y1 < y || y1 > height)
|
||||
{
|
||||
throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
|
||||
}
|
||||
|
||||
if (dArray != null)
|
||||
pixels = dArray;
|
||||
else
|
||||
pixels = new double[w * h];
|
||||
|
||||
for (int i=y; i<(y+h); i++) {
|
||||
for (int j=x; j<(x+w); j++) {
|
||||
for (int i=y; i<y1; i++) {
|
||||
for (int j=x; j<x1; j++) {
|
||||
pixels[Offset++] = getSampleDouble(j, i, b, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +176,9 @@ public class EventSetDescriptor extends FeatureDescriptor {
|
||||
setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
|
||||
|
||||
// Be more forgiving of not finding the getListener method.
|
||||
if (getListenerMethodName != null) {
|
||||
setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName));
|
||||
Method method = Introspector.findMethod(sourceClass, getListenerMethodName, 0);
|
||||
if (method != null) {
|
||||
setGetListenerMethod(method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -189,11 +189,13 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
||||
indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
|
||||
}
|
||||
}
|
||||
indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
|
||||
|
||||
Class[] args = { int.class };
|
||||
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
|
||||
if (indexedReadMethod == null) {
|
||||
// no "is" method, so look for a "get" method.
|
||||
indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
|
||||
indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
|
||||
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
|
||||
}
|
||||
setIndexedReadMethod0(indexedReadMethod);
|
||||
}
|
||||
@ -265,7 +267,9 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
||||
if (indexedWriteMethodName == null) {
|
||||
indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
|
||||
}
|
||||
indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type);
|
||||
|
||||
Class[] args = (type == null) ? null : new Class[] { int.class, type };
|
||||
indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args);
|
||||
if (indexedWriteMethod != null) {
|
||||
if (!indexedWriteMethod.getReturnType().equals(void.class)) {
|
||||
indexedWriteMethod = null;
|
||||
|
||||
@ -28,7 +28,6 @@ package java.beans;
|
||||
import com.sun.beans.WeakCache;
|
||||
import com.sun.beans.finder.BeanInfoFinder;
|
||||
import com.sun.beans.finder.ClassFinder;
|
||||
import com.sun.beans.finder.MethodFinder;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
@ -843,8 +842,8 @@ public class Introspector {
|
||||
Method read = result.getReadMethod();
|
||||
|
||||
if (read == null && write != null) {
|
||||
read = findInstanceMethod(result.getClass0(),
|
||||
GET_PREFIX + NameGenerator.capitalize(result.getName()));
|
||||
read = findMethod(result.getClass0(),
|
||||
GET_PREFIX + NameGenerator.capitalize(result.getName()), 0);
|
||||
if (read != null) {
|
||||
try {
|
||||
result.setReadMethod(read);
|
||||
@ -854,9 +853,9 @@ public class Introspector {
|
||||
}
|
||||
}
|
||||
if (write == null && read != null) {
|
||||
write = findInstanceMethod(result.getClass0(),
|
||||
SET_PREFIX + NameGenerator.capitalize(result.getName()),
|
||||
FeatureDescriptor.getReturnType(result.getClass0(), read));
|
||||
write = findMethod(result.getClass0(),
|
||||
SET_PREFIX + NameGenerator.capitalize(result.getName()), 1,
|
||||
new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) });
|
||||
if (write != null) {
|
||||
try {
|
||||
result.setWriteMethod(write);
|
||||
@ -1280,27 +1279,90 @@ public class Introspector {
|
||||
// Package private support methods.
|
||||
//======================================================================
|
||||
|
||||
static Method findMethod(Class<?> type, String name, int args) {
|
||||
for (Method method : type.getMethods()) {
|
||||
if (method.getName().equals(name) && (args == method.getParameterTypes().length)) {
|
||||
try {
|
||||
return MethodFinder.findAccessibleMethod(method);
|
||||
/**
|
||||
* Internal support for finding a target methodName with a given
|
||||
* parameter list on a given class.
|
||||
*/
|
||||
private static Method internalFindMethod(Class start, String methodName,
|
||||
int argCount, Class args[]) {
|
||||
// For overriden methods we need to find the most derived version.
|
||||
// So we start with the given class and walk up the superclass chain.
|
||||
|
||||
Method method = null;
|
||||
|
||||
for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
|
||||
Method methods[] = getPublicDeclaredMethods(cl);
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
method = methods[i];
|
||||
if (method == null) {
|
||||
continue;
|
||||
}
|
||||
catch (NoSuchMethodException exception) {
|
||||
// continue search for a method with the specified count of parameters
|
||||
|
||||
// make sure method signature matches.
|
||||
Class params[] = FeatureDescriptor.getParameterTypes(start, method);
|
||||
if (method.getName().equals(methodName) &&
|
||||
params.length == argCount) {
|
||||
if (args != null) {
|
||||
boolean different = false;
|
||||
if (argCount > 0) {
|
||||
for (int j = 0; j < argCount; j++) {
|
||||
if (params[j] != args[j]) {
|
||||
different = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (different) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
method = null;
|
||||
|
||||
// Now check any inherited interfaces. This is necessary both when
|
||||
// the argument class is itself an interface, and when the argument
|
||||
// class is an abstract class.
|
||||
Class ifcs[] = start.getInterfaces();
|
||||
for (int i = 0 ; i < ifcs.length; i++) {
|
||||
// Note: The original implementation had both methods calling
|
||||
// the 3 arg method. This is preserved but perhaps it should
|
||||
// pass the args array instead of null.
|
||||
method = internalFindMethod(ifcs[i], methodName, argCount, null);
|
||||
if (method != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static Method findInstanceMethod(Class<?> type, String name, Class<?>... args) {
|
||||
try {
|
||||
return MethodFinder.findInstanceMethod(type, name, args);
|
||||
}
|
||||
catch (NoSuchMethodException exception) {
|
||||
/**
|
||||
* Find a target methodName on a given class.
|
||||
*/
|
||||
static Method findMethod(Class cls, String methodName, int argCount) {
|
||||
return findMethod(cls, methodName, argCount, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a target methodName with specific parameter list on a given class.
|
||||
* <p>
|
||||
* Used in the contructors of the EventSetDescriptor,
|
||||
* PropertyDescriptor and the IndexedPropertyDescriptor.
|
||||
* <p>
|
||||
* @param cls The Class object on which to retrieve the method.
|
||||
* @param methodName Name of the method.
|
||||
* @param argCount Number of arguments for the desired method.
|
||||
* @param args Array of argument types for the method.
|
||||
* @return the method or null if not found
|
||||
*/
|
||||
static Method findMethod(Class cls, String methodName, int argCount,
|
||||
Class args[]) {
|
||||
if (methodName == null) {
|
||||
return null;
|
||||
}
|
||||
return internalFindMethod(cls, methodName, argCount, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -90,13 +90,13 @@ public class MethodDescriptor extends FeatureDescriptor {
|
||||
// Find methods for up to 2 params. We are guessing here.
|
||||
// This block should never execute unless the classloader
|
||||
// that loaded the argument classes disappears.
|
||||
method = Introspector.findMethod(cls, name, i);
|
||||
method = Introspector.findMethod(cls, name, i, null);
|
||||
if (method != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
method = Statement.getMethod(cls, name, params);
|
||||
method = Introspector.findMethod(cls, name, params.length, params);
|
||||
}
|
||||
setMethod(method);
|
||||
}
|
||||
|
||||
@ -112,7 +112,8 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
// If this class or one of its base classes allow PropertyChangeListener,
|
||||
// then we assume that any properties we discover are "bound".
|
||||
// See Introspector.getTargetPropertyInfo() method.
|
||||
this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class);
|
||||
Class[] args = { PropertyChangeListener.class };
|
||||
this.bound = null != Introspector.findMethod(beanClass, "addPropertyChangeListener", args.length, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -223,10 +224,10 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
// property type is. For booleans, there can be "is" and "get"
|
||||
// methods. If an "is" method exists, this is the official
|
||||
// reader method so look for this one first.
|
||||
readMethod = Introspector.findInstanceMethod(cls, readMethodName);
|
||||
readMethod = Introspector.findMethod(cls, readMethodName, 0);
|
||||
if (readMethod == null) {
|
||||
readMethodName = Introspector.GET_PREFIX + getBaseName();
|
||||
readMethod = Introspector.findInstanceMethod(cls, readMethodName);
|
||||
readMethod = Introspector.findMethod(cls, readMethodName, 0);
|
||||
}
|
||||
try {
|
||||
setReadMethod(readMethod);
|
||||
@ -291,7 +292,8 @@ public class PropertyDescriptor extends FeatureDescriptor {
|
||||
writeMethodName = Introspector.SET_PREFIX + getBaseName();
|
||||
}
|
||||
|
||||
writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type);
|
||||
Class[] args = (type == null) ? null : new Class[] { type };
|
||||
writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
|
||||
if (writeMethod != null) {
|
||||
if (!writeMethod.getReturnType().equals(void.class)) {
|
||||
writeMethod = null;
|
||||
|
||||
@ -569,6 +569,9 @@ public final class Locale implements Cloneable, Serializable {
|
||||
* @exception NullPointerException thrown if any argument is null.
|
||||
*/
|
||||
public Locale(String language, String country, String variant) {
|
||||
if (language== null || country == null || variant == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
_baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
|
||||
_extensions = getCompatibilityExtensions(language, "", country, variant);
|
||||
}
|
||||
|
||||
@ -292,16 +292,6 @@ public abstract class ResourceBundle {
|
||||
private static final ConcurrentMap<CacheKey, BundleReference> cacheList
|
||||
= new ConcurrentHashMap<CacheKey, BundleReference>(INITIAL_CACHE_SIZE);
|
||||
|
||||
/**
|
||||
* This ConcurrentMap is used to keep multiple threads from loading the
|
||||
* same bundle concurrently. The table entries are <CacheKey, Thread>
|
||||
* where CacheKey is the key for the bundle that is under construction
|
||||
* and Thread is the thread that is constructing the bundle.
|
||||
* This list is manipulated in findBundleInCache and putBundleInCache.
|
||||
*/
|
||||
private static final ConcurrentMap<CacheKey, Thread> underConstruction
|
||||
= new ConcurrentHashMap<CacheKey, Thread>();
|
||||
|
||||
/**
|
||||
* Queue for reference objects referring to class loaders or bundles.
|
||||
*/
|
||||
@ -1381,7 +1371,7 @@ public abstract class ResourceBundle {
|
||||
boolean expiredBundle = false;
|
||||
|
||||
// First, look up the cache to see if it's in the cache, without
|
||||
// declaring beginLoading.
|
||||
// attempting to load bundle.
|
||||
cacheKey.setLocale(targetLocale);
|
||||
ResourceBundle bundle = findBundleInCache(cacheKey, control);
|
||||
if (isValidBundle(bundle)) {
|
||||
@ -1408,56 +1398,25 @@ public abstract class ResourceBundle {
|
||||
CacheKey constKey = (CacheKey) cacheKey.clone();
|
||||
|
||||
try {
|
||||
// Try declaring loading. If beginLoading() returns true,
|
||||
// then we can proceed. Otherwise, we need to take a look
|
||||
// at the cache again to see if someone else has loaded
|
||||
// the bundle and put it in the cache while we've been
|
||||
// waiting for other loading work to complete.
|
||||
while (!beginLoading(constKey)) {
|
||||
bundle = findBundleInCache(cacheKey, control);
|
||||
if (bundle == null) {
|
||||
continue;
|
||||
}
|
||||
if (bundle == NONEXISTENT_BUNDLE) {
|
||||
// If the bundle is NONEXISTENT_BUNDLE, the bundle doesn't exist.
|
||||
return parent;
|
||||
}
|
||||
expiredBundle = bundle.expired;
|
||||
if (!expiredBundle) {
|
||||
if (bundle.parent == parent) {
|
||||
return bundle;
|
||||
}
|
||||
BundleReference bundleRef = cacheList.get(cacheKey);
|
||||
if (bundleRef != null && bundleRef.get() == bundle) {
|
||||
cacheList.remove(cacheKey, bundleRef);
|
||||
}
|
||||
bundle = loadBundle(cacheKey, formats, control, expiredBundle);
|
||||
if (bundle != null) {
|
||||
if (bundle.parent == null) {
|
||||
bundle.setParent(parent);
|
||||
}
|
||||
bundle.locale = targetLocale;
|
||||
bundle = putBundleInCache(cacheKey, bundle, control);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle = loadBundle(cacheKey, formats, control, expiredBundle);
|
||||
if (bundle != null) {
|
||||
if (bundle.parent == null) {
|
||||
bundle.setParent(parent);
|
||||
}
|
||||
bundle.locale = targetLocale;
|
||||
bundle = putBundleInCache(cacheKey, bundle, control);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
// Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
|
||||
// instance for the locale.
|
||||
putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
|
||||
} finally {
|
||||
endLoading(constKey);
|
||||
}
|
||||
// Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
|
||||
// instance for the locale.
|
||||
putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
|
||||
} finally {
|
||||
if (constKey.getCause() instanceof InterruptedException) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
assert underConstruction.get(cacheKey) != Thread.currentThread();
|
||||
return parent;
|
||||
}
|
||||
|
||||
@ -1465,7 +1424,6 @@ public abstract class ResourceBundle {
|
||||
List<String> formats,
|
||||
Control control,
|
||||
boolean reload) {
|
||||
assert underConstruction.get(cacheKey) == Thread.currentThread();
|
||||
|
||||
// Here we actually load the bundle in the order of formats
|
||||
// specified by the getFormats() value.
|
||||
@ -1498,7 +1456,6 @@ public abstract class ResourceBundle {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert underConstruction.get(cacheKey) == Thread.currentThread();
|
||||
|
||||
return bundle;
|
||||
}
|
||||
@ -1529,57 +1486,6 @@ public abstract class ResourceBundle {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares the beginning of actual resource bundle loading. This method
|
||||
* returns true if the declaration is successful and the current thread has
|
||||
* been put in underConstruction. If someone else has already begun
|
||||
* loading, this method waits until that loading work is complete and
|
||||
* returns false.
|
||||
*/
|
||||
private static final boolean beginLoading(CacheKey constKey) {
|
||||
Thread me = Thread.currentThread();
|
||||
Thread worker;
|
||||
// We need to declare by putting the current Thread (me) to
|
||||
// underConstruction that we are working on loading the specified
|
||||
// resource bundle. If we are already working the loading, it means
|
||||
// that the resource loading requires a recursive call. In that case,
|
||||
// we have to proceed. (4300693)
|
||||
if (((worker = underConstruction.putIfAbsent(constKey, me)) == null)
|
||||
|| worker == me) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If someone else is working on the loading, wait until
|
||||
// the Thread finishes the bundle loading.
|
||||
synchronized (worker) {
|
||||
while (underConstruction.get(constKey) == worker) {
|
||||
try {
|
||||
worker.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// record the interruption
|
||||
constKey.setCause(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares the end of the bundle loading. This method calls notifyAll
|
||||
* for those who are waiting for this completion.
|
||||
*/
|
||||
private static final void endLoading(CacheKey constKey) {
|
||||
// Remove this Thread from the underConstruction map and wake up
|
||||
// those who have been waiting for me to complete this bundle
|
||||
// loading.
|
||||
Thread me = Thread.currentThread();
|
||||
assert (underConstruction.get(constKey) == me);
|
||||
underConstruction.remove(constKey);
|
||||
synchronized (me) {
|
||||
me.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a MissingResourceException with proper message
|
||||
*/
|
||||
|
||||
@ -1464,8 +1464,8 @@ public class GroupLayout implements LayoutManager2 {
|
||||
* <= {@code pref} <= {@code max}.
|
||||
* <p>
|
||||
* Similarly any methods that take a {@code Component} throw a
|
||||
* {@code NullPointerException} if passed {@code null} and any methods
|
||||
* that take a {@code Group} throw an {@code IllegalArgumentException} if
|
||||
* {@code IllegalArgumentException} if passed {@code null} and any methods
|
||||
* that take a {@code Group} throw an {@code NullPointerException} if
|
||||
* passed {@code null}.
|
||||
*
|
||||
* @see #createSequentialGroup
|
||||
|
||||
@ -4787,6 +4787,17 @@ public abstract class JComponent extends Container implements Serializable,
|
||||
* @see RepaintManager#addDirtyRegion
|
||||
*/
|
||||
public void repaint(long tm, int x, int y, int width, int height) {
|
||||
Container p = this;
|
||||
while ((p = p.getParent()) instanceof JComponent) {
|
||||
JComponent jp = (JComponent) p;
|
||||
if (jp.isPaintingOrigin()) {
|
||||
Rectangle rectangle = SwingUtilities.convertRectangle(
|
||||
this, new Rectangle(x, y, width, height), jp);
|
||||
jp.repaint(tm,
|
||||
rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
@ -215,7 +215,8 @@ public class JDesktopPane extends JLayeredPane implements Accessible
|
||||
|
||||
/**
|
||||
* Sets the <code>DesktopManger</code> that will handle
|
||||
* desktop-specific UI actions.
|
||||
* desktop-specific UI actions. This may be overridden by
|
||||
* {@code LookAndFeel}.
|
||||
*
|
||||
* @param d the <code>DesktopManager</code> to use
|
||||
*
|
||||
|
||||
@ -25,17 +25,17 @@
|
||||
|
||||
package javax.swing;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
import javax.swing.plaf.LayerUI;
|
||||
import javax.swing.border.Border;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
@ -156,8 +156,6 @@ public final class JLayer<V extends Component>
|
||||
private LayerUI<? super V> layerUI;
|
||||
private JPanel glassPane;
|
||||
private boolean isPainting;
|
||||
private static final DefaultLayerLayout sharedLayoutInstance =
|
||||
new DefaultLayerLayout();
|
||||
private long eventMask;
|
||||
|
||||
private static final LayerEventController eventController =
|
||||
@ -165,7 +163,7 @@ public final class JLayer<V extends Component>
|
||||
|
||||
/**
|
||||
* Creates a new {@code JLayer} object with a {@code null} view component
|
||||
* and {@code null} {@link javax.swing.plaf.LayerUI}.
|
||||
* and default {@link javax.swing.plaf.LayerUI}.
|
||||
*
|
||||
* @see #setView
|
||||
* @see #setUI
|
||||
@ -176,14 +174,14 @@ public final class JLayer<V extends Component>
|
||||
|
||||
/**
|
||||
* Creates a new {@code JLayer} object
|
||||
* with {@code null} {@link javax.swing.plaf.LayerUI}.
|
||||
* with default {@link javax.swing.plaf.LayerUI}.
|
||||
*
|
||||
* @param view the component to be decorated by this {@code JLayer}
|
||||
*
|
||||
* @see #setUI
|
||||
*/
|
||||
public JLayer(V view) {
|
||||
this(view, null);
|
||||
this(view, new LayerUI<V>());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,7 +193,6 @@ public final class JLayer<V extends Component>
|
||||
* to be used by this {@code JLayer}
|
||||
*/
|
||||
public JLayer(V view, LayerUI<V> ui) {
|
||||
setLayout(sharedLayoutInstance);
|
||||
setGlassPane(createGlassPane());
|
||||
setView(view);
|
||||
setUI(ui);
|
||||
@ -279,10 +276,15 @@ public final class JLayer<V extends Component>
|
||||
*/
|
||||
public void setGlassPane(JPanel glassPane) {
|
||||
Component oldGlassPane = getGlassPane();
|
||||
boolean isGlassPaneVisible = false;
|
||||
if (oldGlassPane != null) {
|
||||
isGlassPaneVisible = oldGlassPane.isVisible();
|
||||
super.remove(oldGlassPane);
|
||||
}
|
||||
if (glassPane != null) {
|
||||
AWTAccessor.getComponentAccessor().setMixingCutoutShape(glassPane,
|
||||
new Rectangle());
|
||||
glassPane.setVisible(isGlassPaneVisible);
|
||||
super.addImpl(glassPane, null, 0);
|
||||
}
|
||||
this.glassPane = glassPane;
|
||||
@ -302,6 +304,40 @@ public final class JLayer<V extends Component>
|
||||
return new DefaultLayerGlassPane();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the layout manager for this container. This method is
|
||||
* overridden to prevent the layout manager from being set.
|
||||
* <p/>Note: If {@code mgr} is non-{@code null}, this
|
||||
* method will throw an exception as layout managers are not supported on
|
||||
* a {@code JLayer}.
|
||||
*
|
||||
* @param mgr the specified layout manager
|
||||
* @exception IllegalArgumentException this method is not supported
|
||||
*/
|
||||
public void setLayout(LayoutManager mgr) {
|
||||
if (mgr != null) {
|
||||
throw new IllegalArgumentException("JLayer.setLayout() not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-{@code null] border, or non-zero insets, isn't supported, to prevent the geometry
|
||||
* of this component from becoming complex enough to inhibit
|
||||
* subclassing of {@code LayerUI} class. To create a {@code JLayer} with a border,
|
||||
* add it to a {@code JPanel} that has a border.
|
||||
* <p/>Note: If {@code border} is non-{@code null}, this
|
||||
* method will throw an exception as borders are not supported on
|
||||
* a {@code JLayer}.
|
||||
*
|
||||
* @param border the {@code Border} to set
|
||||
* @exception IllegalArgumentException this method is not supported
|
||||
*/
|
||||
public void setBorder(Border border) {
|
||||
if (border != null) {
|
||||
throw new IllegalArgumentException("JLayer.setBorder() not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not supported by {@code JLayer}
|
||||
* and always throws {@code UnsupportedOperationException}
|
||||
@ -340,6 +376,32 @@ public final class JLayer<V extends Component>
|
||||
setGlassPane(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns {@code true} to cause painting to originate from {@code JLayer},
|
||||
* or one of its ancestors.
|
||||
*
|
||||
* @return true
|
||||
* @see JComponent#isPaintingOrigin()
|
||||
*/
|
||||
boolean isPaintingOrigin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates repainting to {@link javax.swing.plaf.LayerUI#repaint} method.
|
||||
*
|
||||
* @param tm this parameter is not used
|
||||
* @param x the x value of the dirty region
|
||||
* @param y the y value of the dirty region
|
||||
* @param width the width of the dirty region
|
||||
* @param height the height of the dirty region
|
||||
*/
|
||||
public void repaint(long tm, int x, int y, int width, int height) {
|
||||
if (getUI() != null) {
|
||||
getUI().repaint(tm, x, y, width, height, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates all painting to the {@link javax.swing.plaf.LayerUI} object.
|
||||
*
|
||||
@ -364,14 +426,18 @@ public final class JLayer<V extends Component>
|
||||
}
|
||||
|
||||
/**
|
||||
* To enable the correct painting of the {@code glassPane} and view component,
|
||||
* the {@code JLayer} overrides the default implementation of
|
||||
* this method to return {@code false} when the {@code glassPane} is visible.
|
||||
* The {@code JLayer} overrides the default implementation of
|
||||
* this method (in {@code JComponent}) to return {@code false}.
|
||||
* This ensures
|
||||
* that the drawing machinery will call the {@code JLayer}'s
|
||||
* {@code paint}
|
||||
* implementation rather than messaging the {@code JLayer}'s
|
||||
* children directly.
|
||||
*
|
||||
* @return false if {@code JLayer}'s {@code glassPane} is visible
|
||||
* @return false
|
||||
*/
|
||||
public boolean isOptimizedDrawingEnabled() {
|
||||
return glassPane == null || !glassPane.isVisible();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -461,17 +527,16 @@ public final class JLayer<V extends Component>
|
||||
/**
|
||||
* Returns the preferred size of the viewport for a view component.
|
||||
* <p/>
|
||||
* If the ui delegate of this layer is not {@code null}, this method delegates its
|
||||
* implementation to the {@code LayerUI.getPreferredScrollableViewportSize(JLayer)}
|
||||
* If the view component of this layer implements {@link Scrollable}, this method delegates its
|
||||
* implementation to the view component.
|
||||
*
|
||||
* @return the preferred size of the viewport for a view component
|
||||
*
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getPreferredScrollableViewportSize(JLayer)
|
||||
*/
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
if (getUI() != null) {
|
||||
return getUI().getPreferredScrollableViewportSize(this);
|
||||
if (getView() instanceof Scrollable) {
|
||||
return ((Scrollable)getView()).getPreferredScrollableViewportSize();
|
||||
}
|
||||
return getPreferredSize();
|
||||
}
|
||||
@ -481,18 +546,17 @@ public final class JLayer<V extends Component>
|
||||
* that display logical rows or columns in order to completely expose
|
||||
* one block of rows or columns, depending on the value of orientation.
|
||||
* <p/>
|
||||
* If the ui delegate of this layer is not {@code null}, this method delegates its
|
||||
* implementation to the {@code LayerUI.getScrollableBlockIncrement(JLayer,Rectangle,int,int)}
|
||||
* If the view component of this layer implements {@link Scrollable}, this method delegates its
|
||||
* implementation to the view component.
|
||||
*
|
||||
* @return the "block" increment for scrolling in the specified direction
|
||||
*
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getScrollableBlockIncrement(JLayer, Rectangle, int, int)
|
||||
*/
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect,
|
||||
int orientation, int direction) {
|
||||
if (getUI() != null) {
|
||||
return getUI().getScrollableBlockIncrement(this, visibleRect,
|
||||
if (getView() instanceof Scrollable) {
|
||||
return ((Scrollable)getView()).getScrollableBlockIncrement(visibleRect,
|
||||
orientation, direction);
|
||||
}
|
||||
return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
|
||||
@ -504,17 +568,16 @@ public final class JLayer<V extends Component>
|
||||
* determine the height of the layer, unless the preferred height
|
||||
* of the layer is smaller than the height of the viewport.
|
||||
* <p/>
|
||||
* If the ui delegate of this layer is not null, this method delegates its
|
||||
* implementation to the {@code LayerUI.getScrollableTracksViewportHeight(JLayer)}
|
||||
* If the view component of this layer implements {@link Scrollable}, this method delegates its
|
||||
* implementation to the view component.
|
||||
*
|
||||
* @return whether the layer should track the height of the viewport
|
||||
*
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getScrollableTracksViewportHeight(JLayer)
|
||||
*/
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
if (getUI() != null) {
|
||||
return getUI().getScrollableTracksViewportHeight(this);
|
||||
if (getView() instanceof Scrollable) {
|
||||
return ((Scrollable)getView()).getScrollableTracksViewportHeight();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -524,17 +587,16 @@ public final class JLayer<V extends Component>
|
||||
* determine the width of the layer, unless the preferred width
|
||||
* of the layer is smaller than the width of the viewport.
|
||||
* <p/>
|
||||
* If the ui delegate of this layer is not null, this method delegates its
|
||||
* implementation to the {@code LayerUI.getScrollableTracksViewportWidth(JLayer)}
|
||||
* If the view component of this layer implements {@link Scrollable}, this method delegates its
|
||||
* implementation to the view component.
|
||||
*
|
||||
* @return whether the layer should track the width of the viewport
|
||||
*
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getScrollableTracksViewportWidth(JLayer)
|
||||
*/
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
if (getUI() != null) {
|
||||
return getUI().getScrollableTracksViewportWidth(this);
|
||||
if (getView() instanceof Scrollable) {
|
||||
return ((Scrollable)getView()).getScrollableTracksViewportWidth();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -549,20 +611,19 @@ public final class JLayer<V extends Component>
|
||||
* Scrolling containers, like {@code JScrollPane}, will use this method
|
||||
* each time the user requests a unit scroll.
|
||||
* <p/>
|
||||
* If the ui delegate of this layer is not {@code null}, this method delegates its
|
||||
* implementation to the {@code LayerUI.getScrollableUnitIncrement(JLayer,Rectangle,int,int)}
|
||||
* If the view component of this layer implements {@link Scrollable}, this method delegates its
|
||||
* implementation to the view component.
|
||||
*
|
||||
* @return The "unit" increment for scrolling in the specified direction.
|
||||
* This value should always be positive.
|
||||
*
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getScrollableUnitIncrement(JLayer, Rectangle, int, int)
|
||||
*/
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
|
||||
int direction) {
|
||||
if (getUI() != null) {
|
||||
return getUI().getScrollableUnitIncrement(
|
||||
this, visibleRect, orientation, direction);
|
||||
if (getView() instanceof Scrollable) {
|
||||
return ((Scrollable) getView()).getScrollableUnitIncrement(
|
||||
visibleRect, orientation, direction);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -594,6 +655,16 @@ public final class JLayer<V extends Component>
|
||||
eventController.updateAWTEventListener(eventMask, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates its functionality to the {@link javax.swing.plaf.LayerUI#doLayout(JLayer)} method,
|
||||
* if {@code LayerUI} is set.
|
||||
*/
|
||||
public void doLayout() {
|
||||
if (getUI() != null) {
|
||||
getUI().doLayout(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* static AWTEventListener to be shared with all AbstractLayerUIs
|
||||
*/
|
||||
@ -625,8 +696,8 @@ public final class JLayer<V extends Component>
|
||||
JLayer l = (JLayer) component;
|
||||
LayerUI ui = l.getUI();
|
||||
if (ui != null &&
|
||||
isEventEnabled(l.getLayerEventMask(),
|
||||
event.getID())) {
|
||||
isEventEnabled(l.getLayerEventMask(), event.getID()) &&
|
||||
(!(event instanceof InputEvent) || !((InputEvent)event).isConsumed())) {
|
||||
ui.eventDispatched(event, l);
|
||||
}
|
||||
}
|
||||
@ -758,82 +829,4 @@ public final class JLayer<V extends Component>
|
||||
return super.contains(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The default layout manager for the {@link javax.swing.JLayer}.<br/>
|
||||
* It places the glassPane on top of the view component
|
||||
* and makes it the same size as {@code JLayer},
|
||||
* it also makes the view component the same size but minus layer's insets<br/>
|
||||
*/
|
||||
private static class DefaultLayerLayout implements LayoutManager, Serializable {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void layoutContainer(Container parent) {
|
||||
JLayer layer = (JLayer) parent;
|
||||
Component view = layer.getView();
|
||||
Component glassPane = layer.getGlassPane();
|
||||
if (view != null) {
|
||||
Insets insets = layer.getInsets();
|
||||
view.setLocation(insets.left, insets.top);
|
||||
view.setSize(layer.getWidth() - insets.left - insets.right,
|
||||
layer.getHeight() - insets.top - insets.bottom);
|
||||
}
|
||||
if (glassPane != null) {
|
||||
glassPane.setLocation(0, 0);
|
||||
glassPane.setSize(layer.getWidth(), layer.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Dimension minimumLayoutSize(Container parent) {
|
||||
JLayer layer = (JLayer) parent;
|
||||
Insets insets = layer.getInsets();
|
||||
Dimension ret = new Dimension(insets.left + insets.right,
|
||||
insets.top + insets.bottom);
|
||||
Component view = layer.getView();
|
||||
if (view != null) {
|
||||
Dimension size = view.getMinimumSize();
|
||||
ret.width += size.width;
|
||||
ret.height += size.height;
|
||||
}
|
||||
if (ret.width == 0 || ret.height == 0) {
|
||||
ret.width = ret.height = 4;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
JLayer layer = (JLayer) parent;
|
||||
Insets insets = layer.getInsets();
|
||||
Dimension ret = new Dimension(insets.left + insets.right,
|
||||
insets.top + insets.bottom);
|
||||
Component view = layer.getView();
|
||||
if (view != null) {
|
||||
Dimension size = view.getPreferredSize();
|
||||
if (size.width > 0 && size.height > 0) {
|
||||
ret.width += size.width;
|
||||
ret.height += size.height;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addLayoutComponent(String name, Component comp) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void removeLayoutComponent(Component comp) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4574,9 +4574,8 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
* @see TableColumnModelListener
|
||||
*/
|
||||
public void columnMoved(TableColumnModelEvent e) {
|
||||
// If I'm currently editing, then I should stop editing
|
||||
if (isEditing()) {
|
||||
removeEditor();
|
||||
if (isEditing() && !getCellEditor().stopCellEditing()) {
|
||||
getCellEditor().cancelCellEditing();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
@ -4593,8 +4592,8 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
* @see TableColumnModelListener
|
||||
*/
|
||||
public void columnMarginChanged(ChangeEvent e) {
|
||||
if (isEditing()) {
|
||||
removeEditor();
|
||||
if (isEditing() && !getCellEditor().stopCellEditing()) {
|
||||
getCellEditor().cancelCellEditing();
|
||||
}
|
||||
TableColumn resizingColumn = getResizingColumn();
|
||||
// Need to do this here, before the parent's
|
||||
|
||||
@ -459,7 +459,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
|
||||
if (insideComponent == null) {
|
||||
// Drag exit
|
||||
}
|
||||
if (window != null && event.getSource() == window) {
|
||||
if (window != null && event.getSource() == window && insideComponent != null) {
|
||||
// if we get an exit and have a heavy window
|
||||
// we need to check if it if overlapping the inside component
|
||||
Container insideComponentWindow = insideComponent.getTopLevelAncestor();
|
||||
|
||||
@ -599,104 +599,6 @@ public class LayerUI<V extends Component>
|
||||
public void applyPropertyChange(PropertyChangeEvent evt, JLayer<? extends V> l) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred size of the viewport for a view component.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
* @return the preferred size of the viewport for a view component
|
||||
* @see Scrollable#getPreferredScrollableViewportSize()
|
||||
*/
|
||||
public Dimension getPreferredScrollableViewportSize(JLayer<? extends V> l) {
|
||||
if (l.getView() instanceof Scrollable) {
|
||||
return ((Scrollable)l.getView()).getPreferredScrollableViewportSize();
|
||||
}
|
||||
return l.getPreferredSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a scroll increment, which is required for components
|
||||
* that display logical rows or columns in order to completely expose
|
||||
* one block of rows or columns, depending on the value of orientation.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
* @param visibleRect The view area visible within the viewport
|
||||
* @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
|
||||
* @param direction Less than zero to scroll up/left, greater than zero for down/right.
|
||||
* @return the "block" increment for scrolling in the specified direction
|
||||
* @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int)
|
||||
*/
|
||||
public int getScrollableBlockIncrement(JLayer<? extends V> l,
|
||||
Rectangle visibleRect,
|
||||
int orientation, int direction) {
|
||||
if (l.getView() instanceof Scrollable) {
|
||||
return ((Scrollable)l.getView()).getScrollableBlockIncrement(
|
||||
visibleRect,orientation, direction);
|
||||
}
|
||||
return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
|
||||
visibleRect.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code false} to indicate that the height of the viewport does not
|
||||
* determine the height of the layer, unless the preferred height
|
||||
* of the layer is smaller than the height of the viewport.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
* @return whether the layer should track the height of the viewport
|
||||
* @see Scrollable#getScrollableTracksViewportHeight()
|
||||
*/
|
||||
public boolean getScrollableTracksViewportHeight(JLayer<? extends V> l) {
|
||||
if (l.getView() instanceof Scrollable) {
|
||||
return ((Scrollable)l.getView()).getScrollableTracksViewportHeight();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code false} to indicate that the width of the viewport does not
|
||||
* determine the width of the layer, unless the preferred width
|
||||
* of the layer is smaller than the width of the viewport.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
* @return whether the layer should track the width of the viewport
|
||||
* @see Scrollable
|
||||
* @see LayerUI#getScrollableTracksViewportWidth(JLayer)
|
||||
*/
|
||||
public boolean getScrollableTracksViewportWidth(JLayer<? extends V> l) {
|
||||
if (l.getView() instanceof Scrollable) {
|
||||
return ((Scrollable)l.getView()).getScrollableTracksViewportWidth();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a scroll increment, which is required for components
|
||||
* that display logical rows or columns in order to completely expose
|
||||
* one new row or column, depending on the value of orientation.
|
||||
* Ideally, components should handle a partially exposed row or column
|
||||
* by returning the distance required to completely expose the item.
|
||||
* <p>
|
||||
* Scrolling containers, like JScrollPane, will use this method
|
||||
* each time the user requests a unit scroll.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
* @param visibleRect The view area visible within the viewport
|
||||
* @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
|
||||
* @param direction Less than zero to scroll up/left, greater than zero for down/right.
|
||||
* @return The "unit" increment for scrolling in the specified direction.
|
||||
* This value should always be positive.
|
||||
* @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
|
||||
*/
|
||||
public int getScrollableUnitIncrement(JLayer<? extends V> l,
|
||||
Rectangle visibleRect,
|
||||
int orientation, int direction) {
|
||||
if (l.getView() instanceof Scrollable) {
|
||||
return ((Scrollable)l.getView()).getScrollableUnitIncrement(
|
||||
visibleRect, orientation, direction);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@code JLayer}'s view component is not {@code null},
|
||||
* this calls the view's {@code getBaseline()} method.
|
||||
@ -718,7 +620,7 @@ public class LayerUI<V extends Component>
|
||||
|
||||
/**
|
||||
* If the {@code JLayer}'s view component is not {@code null},
|
||||
* this calls the view's {@code getBaselineResizeBehavior()} method.
|
||||
* this returns the result of the view's {@code getBaselineResizeBehavior()} method.
|
||||
* Otherwise, the default implementation is called.
|
||||
*
|
||||
* @param c {@code JLayer} to return baseline resize behavior for
|
||||
@ -732,4 +634,90 @@ public class LayerUI<V extends Component>
|
||||
}
|
||||
return super.getBaselineResizeBehavior(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes the passed instance of {@code JLayer} to lay out its components.
|
||||
*
|
||||
* @param l the {@code JLayer} component where this UI delegate is being installed
|
||||
*/
|
||||
public void doLayout(JLayer<? extends V> l) {
|
||||
Component view = l.getView();
|
||||
if (view != null) {
|
||||
view.setBounds(0, 0, l.getWidth(), l.getHeight());
|
||||
}
|
||||
Component glassPane = l.getGlassPane();
|
||||
if (glassPane != null) {
|
||||
glassPane.setBounds(0, 0, l.getWidth(), l.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@code JLayer}'s view component is not {@code null},
|
||||
* this returns the result of the view's {@code getPreferredSize()} method.
|
||||
* Otherwise, the default implementation is used.
|
||||
*
|
||||
* @param c {@code JLayer} to return preferred size for
|
||||
* @return preferred size for the passed {@code JLayer}
|
||||
*/
|
||||
public Dimension getPreferredSize(JComponent c) {
|
||||
JLayer l = (JLayer) c;
|
||||
Component view = l.getView();
|
||||
if (view != null) {
|
||||
return view.getPreferredSize();
|
||||
}
|
||||
return super.getPreferredSize(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@code JLayer}'s view component is not {@code null},
|
||||
* this returns the result of the view's {@code getMinimalSize()} method.
|
||||
* Otherwise, the default implementation is used.
|
||||
*
|
||||
* @param c {@code JLayer} to return preferred size for
|
||||
* @return minimal size for the passed {@code JLayer}
|
||||
*/
|
||||
public Dimension getMinimumSize(JComponent c) {
|
||||
JLayer l = (JLayer) c;
|
||||
Component view = l.getView();
|
||||
if (view != null) {
|
||||
return view.getMinimumSize();
|
||||
}
|
||||
return super.getMinimumSize(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@code JLayer}'s view component is not {@code null},
|
||||
* this returns the result of the view's {@code getMaximumSize()} method.
|
||||
* Otherwise, the default implementation is used.
|
||||
*
|
||||
* @param c {@code JLayer} to return preferred size for
|
||||
* @return maximun size for the passed {@code JLayer}
|
||||
*/
|
||||
public Dimension getMaximumSize(JComponent c) {
|
||||
JLayer l = (JLayer) c;
|
||||
Component view = l.getView();
|
||||
if (view != null) {
|
||||
return view.getMaximumSize();
|
||||
}
|
||||
return super.getMaximumSize(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified region to the dirty region list if the component
|
||||
* is showing. The component will be repainted after all of the
|
||||
* currently pending events have been dispatched.
|
||||
* <p/>
|
||||
* This method is to be overridden when the dirty region needs to be changed.
|
||||
*
|
||||
* @param tm this parameter is not used
|
||||
* @param x the x value of the dirty region
|
||||
* @param y the y value of the dirty region
|
||||
* @param width the width of the dirty region
|
||||
* @param height the height of the dirty region
|
||||
* @see java.awt.Component#isShowing
|
||||
* @see RepaintManager#addDirtyRegion
|
||||
*/
|
||||
public void repaint(long tm, int x, int y, int width, int height, JLayer<? extends V> l) {
|
||||
RepaintManager.currentManager(l).addDirtyRegion(l, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1603,6 +1603,7 @@ public class BasicScrollBarUI
|
||||
BoundedRangeModel newModel = (BoundedRangeModel)e.getNewValue();
|
||||
oldModel.removeChangeListener(modelListener);
|
||||
newModel.addChangeListener(modelListener);
|
||||
scrollBarValue = scrollbar.getValue();
|
||||
scrollbar.repaint();
|
||||
scrollbar.revalidate();
|
||||
} else if ("orientation" == propertyName) {
|
||||
|
||||
@ -144,7 +144,7 @@ public class MetalComboBoxUI extends BasicComboBoxUI {
|
||||
*/
|
||||
public int getBaseline(JComponent c, int width, int height) {
|
||||
int baseline;
|
||||
if (MetalLookAndFeel.usingOcean()) {
|
||||
if (MetalLookAndFeel.usingOcean() && height >= 4) {
|
||||
height -= 4;
|
||||
baseline = super.getBaseline(c, width, height);
|
||||
if (baseline >= 0) {
|
||||
|
||||
@ -115,6 +115,9 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI
|
||||
return new SynthTabbedPaneUI();
|
||||
}
|
||||
|
||||
private SynthTabbedPaneUI() {
|
||||
}
|
||||
|
||||
private boolean scrollableTabLayoutEnabled() {
|
||||
return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
|
||||
}
|
||||
|
||||
@ -344,6 +344,11 @@ public final class AWTAccessor {
|
||||
* Removes the last focus request for the heavyweight from the queue.
|
||||
*/
|
||||
void removeLastFocusRequest(Component heavyweight);
|
||||
|
||||
/*
|
||||
* Sets the most recent focus owner in the window.
|
||||
*/
|
||||
void setMostRecentFocusOwner(Window window, Component component);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -70,7 +70,10 @@ public abstract class EmbeddedFrame extends Frame
|
||||
// JDK 1.1 compatibility
|
||||
private static final long serialVersionUID = 2967042741780317130L;
|
||||
|
||||
// Use these in traverseOut method to determine directions
|
||||
/*
|
||||
* The constants define focus traversal directions.
|
||||
* Use them in {@code traverseIn}, {@code traverseOut} methods.
|
||||
*/
|
||||
protected static final boolean FORWARD = true;
|
||||
protected static final boolean BACKWARD = false;
|
||||
|
||||
@ -283,6 +286,41 @@ public abstract class EmbeddedFrame extends Frame
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by the embedder when we should receive focus as element
|
||||
* of the traversal chain. The method requests focus on:
|
||||
* 1. the first Component of this EmbeddedFrame if user moves focus forward
|
||||
* in the focus traversal cycle.
|
||||
* 2. the last Component of this EmbeddedFrame if user moves focus backward
|
||||
* in the focus traversal cycle.
|
||||
*
|
||||
* The direction parameter specifies which of the two mentioned cases is
|
||||
* happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class
|
||||
* to avoid confusing boolean values.
|
||||
*
|
||||
* A concrete implementation of this method is defined in the platform-dependent
|
||||
* subclasses.
|
||||
*
|
||||
* @param direction FORWARD or BACKWARD
|
||||
* @return true, if the EmbeddedFrame wants to get focus, false otherwise.
|
||||
*/
|
||||
public boolean traverseIn(boolean direction) {
|
||||
Component comp = null;
|
||||
|
||||
if (direction == FORWARD) {
|
||||
comp = getFocusTraversalPolicy().getFirstComponent(this);
|
||||
} else {
|
||||
comp = getFocusTraversalPolicy().getLastComponent(this);
|
||||
}
|
||||
if (comp != null) {
|
||||
// comp.requestFocus(); - Leads to a hung.
|
||||
|
||||
AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp);
|
||||
synthesizeWindowActivation(true);
|
||||
}
|
||||
return (null != comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from dispatchKeyEvent in the following two cases:
|
||||
* 1. The focus is on the first Component of this EmbeddedFrame and we are
|
||||
|
||||
@ -64,12 +64,14 @@ public final class BaseLocale {
|
||||
|
||||
public static BaseLocale getInstance(String language, String script, String region, String variant) {
|
||||
// JDK uses deprecated ISO639.1 language codes for he, yi and id
|
||||
if (AsciiUtil.caseIgnoreMatch(language, "he")) {
|
||||
language = "iw";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
|
||||
language = "ji";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
|
||||
language = "in";
|
||||
if (language != null) {
|
||||
if (AsciiUtil.caseIgnoreMatch(language, "he")) {
|
||||
language = "iw";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
|
||||
language = "ji";
|
||||
} else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
|
||||
language = "in";
|
||||
}
|
||||
}
|
||||
|
||||
Key key = new Key(language, script, region, variant);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -64,7 +64,10 @@ class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer {
|
||||
accessor.setFile(fd, null);
|
||||
accessor.setFiles(fd, null, null);
|
||||
} else {
|
||||
accessor.setDirectory(fd, directory);
|
||||
// Fix 6987233: add the trailing slash if it's absent
|
||||
accessor.setDirectory(fd, directory +
|
||||
(directory.endsWith(File.separator) ?
|
||||
"" : File.separator));
|
||||
accessor.setFile(fd, filenames[0]);
|
||||
accessor.setFiles(fd, directory, filenames);
|
||||
}
|
||||
|
||||
@ -705,12 +705,8 @@ public class XBaseWindow {
|
||||
throw new IllegalStateException("Attempt to resize uncreated window");
|
||||
}
|
||||
insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height);
|
||||
if (width <= 0) {
|
||||
width = 1;
|
||||
}
|
||||
if (height <= 0) {
|
||||
height = 1;
|
||||
}
|
||||
width = Math.max(MIN_SIZE, width);
|
||||
height = Math.max(MIN_SIZE, height);
|
||||
XToolkit.awtLock();
|
||||
try {
|
||||
XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height);
|
||||
|
||||
@ -763,12 +763,8 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
}
|
||||
|
||||
private void checkShellRectSize(Rectangle shellRect) {
|
||||
if (shellRect.width < 0) {
|
||||
shellRect.width = 1;
|
||||
}
|
||||
if (shellRect.height < 0) {
|
||||
shellRect.height = 1;
|
||||
}
|
||||
shellRect.width = Math.max(MIN_SIZE, shellRect.width);
|
||||
shellRect.height = Math.max(MIN_SIZE, shellRect.height);
|
||||
}
|
||||
|
||||
private void checkShellRectPos(Rectangle shellRect) {
|
||||
|
||||
@ -28,9 +28,12 @@ package sun.awt.X11;
|
||||
import sun.awt.EmbeddedFrame;
|
||||
import java.awt.*;
|
||||
import java.awt.AWTKeyStroke;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class XEmbeddedFrame extends EmbeddedFrame {
|
||||
|
||||
private static final Logger log = Logger.getLogger(XEmbeddedFrame.class.getName());
|
||||
|
||||
long handle;
|
||||
public XEmbeddedFrame() {
|
||||
}
|
||||
@ -70,6 +73,21 @@ public class XEmbeddedFrame extends EmbeddedFrame {
|
||||
this(handle, supportsXEmbed, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The method shouldn't be called in case of active XEmbed.
|
||||
*/
|
||||
public boolean traverseIn(boolean direction) {
|
||||
XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer();
|
||||
if (peer != null) {
|
||||
if (peer.supportsXEmbed() && peer.isXEmbedActive()) {
|
||||
log.fine("The method shouldn't be called when XEmbed is active!");
|
||||
} else {
|
||||
return super.traverseIn(direction);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean traverseOut(boolean direction) {
|
||||
XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer();
|
||||
if (direction == FORWARD) {
|
||||
@ -81,6 +99,20 @@ public class XEmbeddedFrame extends EmbeddedFrame {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The method shouldn't be called in case of active XEmbed.
|
||||
*/
|
||||
public void synthesizeWindowActivation(boolean doActivate) {
|
||||
XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer();
|
||||
if (peer != null) {
|
||||
if (peer.supportsXEmbed() && peer.isXEmbedActive()) {
|
||||
log.fine("The method shouldn't be called when XEmbed is active!");
|
||||
} else {
|
||||
peer.synthesizeFocusInOut(doActivate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAccelerator(AWTKeyStroke stroke) {
|
||||
XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer();
|
||||
if (xefp != null) {
|
||||
|
||||
@ -35,6 +35,8 @@ import sun.util.logging.PlatformLogger;
|
||||
import sun.awt.EmbeddedFrame;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import static sun.awt.X11.XConstants.*;
|
||||
|
||||
public class XEmbeddedFramePeer extends XFramePeer {
|
||||
|
||||
private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer");
|
||||
@ -305,4 +307,20 @@ public class XEmbeddedFramePeer extends XFramePeer {
|
||||
EmbeddedFrame frame = (EmbeddedFrame)target;
|
||||
frame.notifyModalBlocked(blocker, blocked);
|
||||
}
|
||||
|
||||
public void synthesizeFocusInOut(boolean doFocus) {
|
||||
XFocusChangeEvent xev = new XFocusChangeEvent();
|
||||
|
||||
XToolkit.awtLock();
|
||||
try {
|
||||
xev.set_type(doFocus ? FocusIn : FocusOut);
|
||||
xev.set_window(getFocusProxy().getWindow());
|
||||
xev.set_mode(NotifyNormal);
|
||||
XlibWrapper.XSendEvent(XToolkit.getDisplay(), getFocusProxy().getWindow(), false,
|
||||
NoEventMask, xev.pData);
|
||||
} finally {
|
||||
XToolkit.awtUnlock();
|
||||
xev.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1482,8 +1482,19 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
||||
try {
|
||||
if (numberOfButtons == 0) {
|
||||
numberOfButtons = getNumberOfButtonsImpl();
|
||||
numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
|
||||
//4th and 5th buttons are for wheel and shouldn't be reported as buttons.
|
||||
//If we have more than 3 physical buttons and a wheel, we report N-2 buttons.
|
||||
//If we have 3 physical buttons and a wheel, we report 3 buttons.
|
||||
//If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively.
|
||||
if (numberOfButtons >=5) {
|
||||
numberOfButtons -= 2;
|
||||
} else if (numberOfButtons == 4 || numberOfButtons ==5){
|
||||
numberOfButtons = 3;
|
||||
}
|
||||
}
|
||||
return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
|
||||
//Assume don't have to re-query the number again and again.
|
||||
return numberOfButtons;
|
||||
} finally {
|
||||
awtUnlock();
|
||||
}
|
||||
|
||||
@ -1473,6 +1473,10 @@ static void OpenXIMCallback(Display *display, XPointer client_data, XPointer cal
|
||||
static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
|
||||
/* mark that XIM server was destroyed */
|
||||
X11im = NULL;
|
||||
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
/* free the old pX11IMData and set it to null. this also avoids crashing
|
||||
* the jvm if the XIM server reappears */
|
||||
X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -556,24 +556,26 @@ public abstract class WComponentPeer extends WObjectPeer
|
||||
|
||||
Component target = (Component)getTarget();
|
||||
Window window = SunToolkit.getContainingWindow(target);
|
||||
if (window != null && !window.isOpaque()) {
|
||||
// Non-opaque windows do not support heavyweight children.
|
||||
// Redirect all painting to the Window's Graphics instead.
|
||||
// The caller is responsible for calling the
|
||||
// WindowPeer.updateWindow() after painting has finished.
|
||||
int x = 0, y = 0;
|
||||
for (Component c = target; c != window; c = c.getParent()) {
|
||||
x += c.getX();
|
||||
y += c.getY();
|
||||
}
|
||||
|
||||
if (window != null) {
|
||||
Graphics g =
|
||||
((WWindowPeer)window.getPeer()).getTranslucentGraphics();
|
||||
// getTranslucentGraphics() returns non-null value for non-opaque windows only
|
||||
if (g != null) {
|
||||
// Non-opaque windows do not support heavyweight children.
|
||||
// Redirect all painting to the Window's Graphics instead.
|
||||
// The caller is responsible for calling the
|
||||
// WindowPeer.updateWindow() after painting has finished.
|
||||
int x = 0, y = 0;
|
||||
for (Component c = target; c != window; c = c.getParent()) {
|
||||
x += c.getX();
|
||||
y += c.getY();
|
||||
}
|
||||
|
||||
g.translate(x, y);
|
||||
g.clipRect(0, 0, target.getWidth(), target.getHeight());
|
||||
g.translate(x, y);
|
||||
g.clipRect(0, 0, target.getWidth(), target.getHeight());
|
||||
|
||||
return g;
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceData surfaceData = this.surfaceData;
|
||||
|
||||
@ -191,9 +191,20 @@ public class WEmbeddedFrame extends EmbeddedFrame {
|
||||
public void activateEmbeddingTopLevel() {
|
||||
}
|
||||
|
||||
public void synthesizeWindowActivation(boolean doActivate) {
|
||||
((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate);
|
||||
public void synthesizeWindowActivation(final boolean doActivate) {
|
||||
if (!doActivate || EventQueue.isDispatchThread()) {
|
||||
((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate);
|
||||
} else {
|
||||
// To avoid focus concurrence b/w IE and EmbeddedFrame
|
||||
// activation is postponed by means of posting it to EDT.
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAccelerator(AWTKeyStroke stroke) {}
|
||||
public void unregisterAccelerator(AWTKeyStroke stroke) {}
|
||||
|
||||
|
||||
@ -594,16 +594,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics getGraphics() {
|
||||
synchronized (getStateLock()) {
|
||||
if (!isOpaque) {
|
||||
return getTranslucentGraphics();
|
||||
}
|
||||
}
|
||||
return super.getGraphics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color c) {
|
||||
super.setBackground(c);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#
|
||||
#
|
||||
# This file describes mapping information between Windows and Java
|
||||
# time zones.
|
||||
# Format: Each line should include a colon separated fields of Windows
|
||||
@ -11,7 +10,7 @@
|
||||
# NOTE
|
||||
# This table format is not a public interface of any Java
|
||||
# platforms. No applications should depend on this file in any form.
|
||||
#
|
||||
#
|
||||
# This table has been generated by a program and should not be edited
|
||||
# manually.
|
||||
#
|
||||
@ -84,8 +83,8 @@ Ekaterinburg:10,11::Asia/Yekaterinburg:
|
||||
Ekaterinburg Standard Time:10,11::Asia/Yekaterinburg:
|
||||
West Asia:10,11:UZ:Asia/Tashkent:
|
||||
West Asia Standard Time:10,11:UZ:Asia/Tashkent:
|
||||
Central Asia:12,13::Asia/Dhaka:
|
||||
Central Asia Standard Time:12,13::Asia/Dhaka:
|
||||
Central Asia:12,13::Asia/Almaty:
|
||||
Central Asia Standard Time:12,13::Asia/Almaty:
|
||||
N. Central Asia Standard Time:12,13::Asia/Novosibirsk:
|
||||
Bangkok:14,15::Asia/Bangkok:
|
||||
Bangkok Standard Time:14,15::Asia/Bangkok:
|
||||
@ -167,22 +166,27 @@ Greenwich:88,89::GMT:
|
||||
Greenwich Standard Time:88,89::GMT:
|
||||
Argentina Standard Time:900,900::America/Buenos_Aires:
|
||||
Azerbaijan Standard Time:901,901:AZ:Asia/Baku:
|
||||
Central Brazilian Standard Time:902,902:BR:America/Manaus:
|
||||
Central Standard Time (Mexico):903,903::America/Mexico_City:
|
||||
Georgian Standard Time:904,904:GE:Asia/Tbilisi:
|
||||
Jordan Standard Time:905,905:JO:Asia/Amman:
|
||||
Mauritius Standard Time:906,906:MU:Indian/Mauritius:
|
||||
Middle East Standard Time:907,907:LB:Asia/Beirut:
|
||||
Montevideo Standard Time:908,908:UY:America/Montevideo:
|
||||
Morocco Standard Time:909,909:MA:Africa/Casablanca:
|
||||
Mountain Standard Time (Mexico):910,910:MX:America/Chihuahua:
|
||||
Namibia Standard Time:911,911:NA:Africa/Windhoek:
|
||||
Pacific Standard Time (Mexico):912,912:MX:America/Tijuana:
|
||||
Pakistan Standard Time:913,913::Asia/Karachi:
|
||||
UTC:914,914::UTC:
|
||||
Venezuela Standard Time:915,915::America/Caracas:
|
||||
Kamchatka Standard Time:916,916:RU:Asia/Kamchatka:
|
||||
Paraguay Standard Time:917,917:PY:America/Asuncion:
|
||||
Western Brazilian Standard Time:918,918:BR:America/Rio_Branco:
|
||||
Ulaanbaatar Standard Time:919,919::Asia/Ulaanbaatar:
|
||||
Armenian Standard Time:920,920:AM:Asia/Yerevan:
|
||||
Bangladesh Standard Time:902,902::Asia/Dhaka:
|
||||
Central Brazilian Standard Time:903,903:BR:America/Manaus:
|
||||
Central Standard Time (Mexico):904,904::America/Mexico_City:
|
||||
Georgian Standard Time:905,905:GE:Asia/Tbilisi:
|
||||
Jordan Standard Time:906,906:JO:Asia/Amman:
|
||||
Kamchatka Standard Time:907,907:RU:Asia/Kamchatka:
|
||||
Mauritius Standard Time:908,908:MU:Indian/Mauritius:
|
||||
Middle East Standard Time:909,909:LB:Asia/Beirut:
|
||||
Montevideo Standard Time:910,910:UY:America/Montevideo:
|
||||
Morocco Standard Time:911,911:MA:Africa/Casablanca:
|
||||
Mountain Standard Time (Mexico):912,912:MX:America/Chihuahua:
|
||||
Namibia Standard Time:913,913:NA:Africa/Windhoek:
|
||||
Pacific Standard Time (Mexico):914,914:MX:America/Tijuana:
|
||||
Pakistan Standard Time:915,915::Asia/Karachi:
|
||||
Paraguay Standard Time:916,916:PY:America/Asuncion:
|
||||
Syria Standard Time:917,917:SY:Asia/Damascus:
|
||||
UTC:918,918::UTC:
|
||||
UTC+12:919,919::GMT+1200:
|
||||
UTC-02:920,920::GMT-0200:
|
||||
UTC-11:921,921::GMT-1100:
|
||||
Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar:
|
||||
Venezuela Standard Time:923,923::America/Caracas:
|
||||
Western Brazilian Standard Time:924,924:BR:America/Rio_Branco:
|
||||
Armenian Standard Time:925,925:AM:Asia/Yerevan:
|
||||
|
||||
@ -2329,6 +2329,19 @@ MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
|
||||
MSG msg;
|
||||
InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
|
||||
|
||||
AwtWindow *toplevel = GetContainer();
|
||||
if (toplevel && !toplevel->IsSimpleWindow()) {
|
||||
/*
|
||||
* The frame should be focused by click in case it is
|
||||
* the active window but not the focused window. See 6886678.
|
||||
*/
|
||||
if (toplevel->GetHWnd() == ::GetActiveWindow() &&
|
||||
toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
|
||||
{
|
||||
toplevel->AwtSetActiveWindow();
|
||||
}
|
||||
}
|
||||
|
||||
SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
|
||||
GetJavaModifiers(), clickCount, JNI_FALSE,
|
||||
GetButton(button), &msg);
|
||||
|
||||
@ -59,15 +59,17 @@ JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_ShellExecute
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
(int)retval,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR)&buffer,
|
||||
0,
|
||||
NULL );
|
||||
|
||||
jstring errmsg = JNU_NewStringPlatform(env, buffer, len);
|
||||
LocalFree(buffer);
|
||||
return errmsg;
|
||||
if (buffer) {
|
||||
jstring errmsg = JNU_NewStringPlatform(env, buffer);
|
||||
LocalFree(buffer);
|
||||
return errmsg;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@ -505,7 +505,8 @@ void AwtDesktopProperties::GetOtherParameters() {
|
||||
SetIntegerProperty(TEXT("win.drag.width"), cxdrag);
|
||||
SetIntegerProperty(TEXT("win.drag.height"), cydrag);
|
||||
SetIntegerProperty(TEXT("DnD.gestureMotionThreshold"), max(cxdrag, cydrag)/2);
|
||||
SetIntegerProperty(TEXT("awt.mouse.numButtons"), GetSystemMetrics(SM_CMOUSEBUTTONS));
|
||||
SetIntegerProperty(TEXT("awt.mouse.numButtons"), AwtToolkit::GetNumberOfButtons());
|
||||
|
||||
SetIntegerProperty(TEXT("awt.multiClickInterval"), GetDoubleClickTime());
|
||||
|
||||
// BEGIN cross-platform properties
|
||||
|
||||
@ -133,6 +133,8 @@ extern "C" JNIEXPORT jboolean JNICALL AWTIsHeadless() {
|
||||
|
||||
static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit");
|
||||
|
||||
static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2.
|
||||
|
||||
UINT AwtToolkit::GetMouseKeyState()
|
||||
{
|
||||
static BOOL mbSwapped = ::GetSystemMetrics(SM_SWAPBUTTON);
|
||||
@ -2310,5 +2312,9 @@ void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) {
|
||||
|
||||
JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
|
||||
(JNIEnv *, jobject self) {
|
||||
return GetSystemMetrics(SM_CMOUSEBUTTONS);
|
||||
return AwtToolkit::GetNumberOfButtons();
|
||||
}
|
||||
|
||||
UINT AwtToolkit::GetNumberOfButtons() {
|
||||
return MOUSE_BUTTONS_WINDOWS_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -185,6 +185,7 @@ public:
|
||||
BOOL IsDynamicLayoutActive();
|
||||
BOOL areExtraMouseButtonsEnabled();
|
||||
void setExtraMouseButtonsEnabled(BOOL enable);
|
||||
static UINT GetNumberOfButtons();
|
||||
|
||||
INLINE BOOL localPump() { return m_localPump; }
|
||||
INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag
|
||||
|
||||
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
|
||||
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 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. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
@test FocusOwnerFrameOnClick.java %W% %E%
|
||||
@bug 6886678
|
||||
@summary Tests that clicking an owner frame switches focus from its owned window.
|
||||
@author Anton Tarasov: area=awt.focus
|
||||
@library ../../regtesthelpers
|
||||
@build Util
|
||||
@run main FocusOwnerFrameOnClick
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.applet.Applet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import test.java.awt.regtesthelpers.Util;
|
||||
|
||||
public class FocusOwnerFrameOnClick extends Applet {
|
||||
Robot robot;
|
||||
Frame frame = new Frame("Frame");
|
||||
Window window = new Window(frame);
|
||||
Button fButton = new Button("fButton");
|
||||
Button wButton = new Button("wButton");
|
||||
|
||||
AtomicBoolean focused = new AtomicBoolean(false);
|
||||
|
||||
public static void main(String[] args) {
|
||||
FocusOwnerFrameOnClick app = new FocusOwnerFrameOnClick();
|
||||
app.init();
|
||||
app.start();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
robot = Util.createRobot();
|
||||
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.setSize(200, 200);
|
||||
frame.add(fButton);
|
||||
|
||||
window.setLocation(300, 0);
|
||||
window.add(wButton);
|
||||
window.pack();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
frame.setVisible(true);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
window.setVisible(true);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
if (!wButton.hasFocus()) {
|
||||
if (!Util.trackFocusGained(wButton, new Runnable() {
|
||||
public void run() {
|
||||
Util.clickOnComp(wButton, robot);
|
||||
}
|
||||
}, 2000, false))
|
||||
{
|
||||
throw new TestErrorException("wButton didn't gain focus on showing");
|
||||
}
|
||||
}
|
||||
|
||||
Runnable clickAction = new Runnable() {
|
||||
public void run() {
|
||||
Point loc = fButton.getLocationOnScreen();
|
||||
Dimension dim = fButton.getSize();
|
||||
|
||||
robot.mouseMove(loc.x, loc.y + dim.height + 20);
|
||||
robot.delay(50);
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.delay(50);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
if (!Util.trackWindowGainedFocus(frame, clickAction, 2000, true)) {
|
||||
throw new TestFailedException("The frame wasn't focused on click");
|
||||
}
|
||||
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when the behavior being verified is found wrong.
|
||||
*/
|
||||
class TestFailedException extends RuntimeException {
|
||||
TestFailedException(String msg) {
|
||||
super("Test failed: " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when an error not related to the behavior being verified is encountered.
|
||||
*/
|
||||
class TestErrorException extends RuntimeException {
|
||||
TestErrorException(String msg) {
|
||||
super("Unexpected error: " + msg);
|
||||
}
|
||||
}
|
||||
@ -21,16 +21,15 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
static final int SHIFT = 1;
|
||||
static final int CTRL = 2;
|
||||
static final int ALT = 3;
|
||||
static CheckingModifierAdapter adapterTest1;
|
||||
static CheckingModifierAdapter adapterTest2;
|
||||
static CheckingModifierAdapter adapterTest3;
|
||||
static CheckingModifierAdapter adapterTest4;
|
||||
static CheckingModifierAdapterExtra adapterTest1;
|
||||
static CheckingModifierAdapterExtra adapterTest2;
|
||||
static CheckingModifierAdapterExtra adapterTest3;
|
||||
static CheckingModifierAdapterExtra adapterTest4;
|
||||
|
||||
static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception
|
||||
static boolean autorun = false; //use robot or manual run
|
||||
static int testModifier = NONE;
|
||||
|
||||
static int [] mouseButtons;
|
||||
static int [] mouseButtonDownMasks;
|
||||
|
||||
//an arrays representing a modifiersEx of extra mouse buttons while using ALT/CTRL/SHIFT or none of them
|
||||
@ -39,7 +38,6 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
static int [] modifiersExStandardCTRL;
|
||||
static int [] modifiersExStandardALT;
|
||||
|
||||
// final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK};
|
||||
// BUTTON1, 2, 3 press-release.
|
||||
final static int modifiersStandard = 0; //InputEvent.BUTTON_DOWN_MASK;
|
||||
|
||||
@ -56,7 +54,7 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
|
||||
if (modifiersEx != curStandardExModifiers[index]){
|
||||
// System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers");
|
||||
MessageLogger.reportError("Test failed : Pressed. modifiersEx != curStandardExModifiers");
|
||||
MessageLogger.reportError("Test failed : Pressed. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
|
||||
}
|
||||
|
||||
//check event.paramString() output
|
||||
@ -168,7 +166,7 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
}
|
||||
|
||||
if (modifiersEx != curStandardExModifiers[index]){
|
||||
MessageLogger.reportError("Test failed : Released. modifiersEx != curStandardExModifiers");
|
||||
MessageLogger.reportError("Test failed : Released. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
|
||||
}
|
||||
|
||||
//check event.paramString() output
|
||||
@ -191,7 +189,7 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
}
|
||||
|
||||
if (modifiersEx != curStandardExModifiers[index]){
|
||||
MessageLogger.reportError("Test failed : Clicked. modifiersEx != curStandardExModifiers");
|
||||
MessageLogger.reportError("Test failed : Clicked. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
|
||||
}
|
||||
|
||||
//check event.paramString() output
|
||||
@ -275,11 +273,11 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
this.addMouseListener(adapterTest1);
|
||||
robot.delay(1000);
|
||||
robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
|
||||
for (int i = 3; i< mouseButtons.length; i++){
|
||||
System.out.println("testNONE() => " +mouseButtons[i] );
|
||||
robot.mousePress(mouseButtons[i]);
|
||||
for (int i = 3; i< mouseButtonDownMasks.length; i++){
|
||||
System.out.println("testNONE() => " +mouseButtonDownMasks[i] );
|
||||
robot.mousePress(mouseButtonDownMasks[i]);
|
||||
robot.delay(100);
|
||||
robot.mouseRelease(mouseButtons[i]);
|
||||
robot.mouseRelease(mouseButtonDownMasks[i]);
|
||||
}
|
||||
robot.delay(1000);
|
||||
this.removeMouseListener(adapterTest1);
|
||||
@ -289,12 +287,12 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
this.addMouseListener(adapterTest2);
|
||||
robot.delay(1000);
|
||||
robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
|
||||
for (int i = 3; i< mouseButtons.length; i++){
|
||||
for (int i = 3; i< mouseButtonDownMasks.length; i++){
|
||||
robot.keyPress(KeyEvent.VK_SHIFT);
|
||||
System.out.println("testSHIFT() => " +mouseButtons[i] );
|
||||
robot.mousePress(mouseButtons[i]);
|
||||
System.out.println("testSHIFT() => " +mouseButtonDownMasks[i] );
|
||||
robot.mousePress(mouseButtonDownMasks[i]);
|
||||
robot.delay(100);
|
||||
robot.mouseRelease(mouseButtons[i]);
|
||||
robot.mouseRelease(mouseButtonDownMasks[i]);
|
||||
robot.keyRelease(KeyEvent.VK_SHIFT);
|
||||
}
|
||||
robot.delay(1000);
|
||||
@ -305,12 +303,12 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
this.addMouseListener(adapterTest3);
|
||||
robot.delay(1000);
|
||||
robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
|
||||
for (int i = 3; i< mouseButtons.length; i++){
|
||||
for (int i = 3; i< mouseButtonDownMasks.length; i++){
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
System.out.println("testCTRL() => " +mouseButtons[i] );
|
||||
robot.mousePress(mouseButtons[i]);
|
||||
System.out.println("testCTRL() => " +mouseButtonDownMasks[i] );
|
||||
robot.mousePress(mouseButtonDownMasks[i]);
|
||||
robot.delay(100);
|
||||
robot.mouseRelease(mouseButtons[i]);
|
||||
robot.mouseRelease(mouseButtonDownMasks[i]);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
}
|
||||
robot.delay(1000);
|
||||
@ -321,12 +319,12 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
this.addMouseListener(adapterTest4);
|
||||
robot.delay(1000);
|
||||
robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
|
||||
for (int i = 3; i< mouseButtons.length; i++){
|
||||
for (int i = 3; i< mouseButtonDownMasks.length; i++){
|
||||
robot.keyPress(KeyEvent.VK_ALT);
|
||||
System.out.println("testALT() => " +mouseButtons[i] );
|
||||
robot.mousePress(mouseButtons[i]);
|
||||
System.out.println("testALT() => " +mouseButtonDownMasks[i] );
|
||||
robot.mousePress(mouseButtonDownMasks[i]);
|
||||
robot.delay(100);
|
||||
robot.mouseRelease(mouseButtons[i]);
|
||||
robot.mouseRelease(mouseButtonDownMasks[i]);
|
||||
robot.keyRelease(KeyEvent.VK_ALT);
|
||||
}
|
||||
robot.delay(1000);
|
||||
@ -368,52 +366,52 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
}
|
||||
|
||||
public static void initAdapters(){
|
||||
adapterTest1 = new CheckingModifierAdapter(NONE);
|
||||
adapterTest2 = new CheckingModifierAdapter(SHIFT);
|
||||
adapterTest3 = new CheckingModifierAdapter(CTRL);
|
||||
adapterTest4 = new CheckingModifierAdapter(ALT);
|
||||
adapterTest1 = new CheckingModifierAdapterExtra(NONE);
|
||||
adapterTest2 = new CheckingModifierAdapterExtra(SHIFT);
|
||||
adapterTest3 = new CheckingModifierAdapterExtra(CTRL);
|
||||
adapterTest4 = new CheckingModifierAdapterExtra(ALT);
|
||||
}
|
||||
|
||||
public static void initVars(){
|
||||
int [] tmp = new int [MouseInfo.getNumberOfButtons()];
|
||||
for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
|
||||
tmp[i] = InputEvent.getMaskForButton(i+1);
|
||||
// System.out.println("TEST: "+tmp[i]);
|
||||
//Init the array of the mouse button masks. It will be used for generating mouse events.
|
||||
mouseButtonDownMasks = new int [MouseInfo.getNumberOfButtons()];
|
||||
for (int i = 0; i < mouseButtonDownMasks.length; i++){
|
||||
mouseButtonDownMasks[i] = InputEvent.getMaskForButton(i+1);
|
||||
System.out.println("MouseArray [i] == "+mouseButtonDownMasks[i]);
|
||||
}
|
||||
|
||||
mouseButtons = Arrays.copyOf(tmp, tmp.length);
|
||||
|
||||
for (int i = 0; i < mouseButtons.length; i++){
|
||||
System.out.println("MouseArray [i] == "+mouseButtons[i]);
|
||||
}
|
||||
|
||||
mouseButtonDownMasks = Arrays.copyOf(tmp, tmp.length);
|
||||
|
||||
// So we need to get the number of extra buttons on the mouse: "MouseInfo.getNumberOfButtons() - 3"
|
||||
// and multyply on 3 because each button will generate three events : PRESS, RELEASE and CLICK.
|
||||
tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3];
|
||||
Arrays.fill(tmp, 0);
|
||||
int [] tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3];
|
||||
|
||||
//Fill array of expected results for the case when mouse buttons are only used (no-modifier keys)
|
||||
Arrays.fill(tmp, 0);
|
||||
for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
|
||||
tmp[i] = mouseButtonDownMasks[j];
|
||||
}
|
||||
modifiersExStandard = Arrays.copyOf(tmp, tmp.length);
|
||||
|
||||
//Fill array of expected results for the case when mouse buttons are only used with SHIFT modifier key
|
||||
Arrays.fill(tmp, InputEvent.SHIFT_DOWN_MASK);
|
||||
for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
|
||||
tmp[i] = tmp[j] | mouseButtonDownMasks[j];
|
||||
for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
|
||||
System.out.println("modifiersExStandardSHIFT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
|
||||
tmp[i] = tmp[i] | mouseButtonDownMasks[j];
|
||||
}
|
||||
modifiersExStandardSHIFT = Arrays.copyOf(tmp, tmp.length);
|
||||
|
||||
//Fill array of expected results for the case when mouse buttons are only used with CTRL modifier key
|
||||
Arrays.fill(tmp, InputEvent.CTRL_DOWN_MASK);
|
||||
for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
|
||||
tmp[i] = tmp[j] | mouseButtonDownMasks[j];
|
||||
for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
|
||||
System.out.println("modifiersExStandardCTRL FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
|
||||
tmp[i] = tmp[i] | mouseButtonDownMasks[j];
|
||||
}
|
||||
modifiersExStandardCTRL = Arrays.copyOf(tmp, tmp.length);
|
||||
|
||||
//Fill array of expected results for the case when mouse buttons are only used with ALT modifier key
|
||||
Arrays.fill(tmp, InputEvent.ALT_DOWN_MASK);
|
||||
for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
|
||||
tmp[i] = tmp[j] | mouseButtonDownMasks[j];
|
||||
for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
|
||||
System.out.println("modifiersExStandardALT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
|
||||
tmp[i] = tmp[i] | mouseButtonDownMasks[j];
|
||||
}
|
||||
modifiersExStandardALT = Arrays.copyOf(tmp, tmp.length);
|
||||
}
|
||||
@ -436,9 +434,9 @@ public class MouseModifiersUnitTest_Extra extends Frame {
|
||||
/* A class that invoke appropriate verification
|
||||
* routine with current modifier.
|
||||
*/
|
||||
class CheckingModifierAdapter extends MouseAdapter{
|
||||
class CheckingModifierAdapterExtra extends MouseAdapter{
|
||||
int modifier;
|
||||
public CheckingModifierAdapter(int modifier){
|
||||
public CheckingModifierAdapterExtra(int modifier){
|
||||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ public class ToolkitPropertyTest_Enable extends Frame {
|
||||
int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks();
|
||||
for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
|
||||
buttonMasks[i] = InputEvent.getMaskForButton(i+1);
|
||||
System.out.println("TEST: "+buttonMasks[i]);
|
||||
System.out.println("TEST: buttonMasks["+ i +"] = " + buttonMasks[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
|
||||
|
||||
121
jdk/test/java/awt/image/GetSamplesTest.java
Normal file
121
jdk/test/java/awt/image/GetSamplesTest.java
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6735275
|
||||
* @summary Test verifies that SampleModel.getSamples() throws an appropriate
|
||||
* exception if coordinates are not in bounds.
|
||||
*
|
||||
* @run main GetSamplesTest
|
||||
*/
|
||||
|
||||
import java.awt.image.BandedSampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.MultiPixelPackedSampleModel;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.util.Vector;
|
||||
|
||||
public class GetSamplesTest {
|
||||
|
||||
public static int width = 100;
|
||||
public static int height = 100;
|
||||
public static int dataType = DataBuffer.TYPE_BYTE;
|
||||
public static int numBands = 4;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Vector<Class<? extends SampleModel>> classes = new Vector<Class<? extends SampleModel>>();
|
||||
|
||||
classes.add(ComponentSampleModel.class);
|
||||
classes.add(MultiPixelPackedSampleModel.class);
|
||||
classes.add(SinglePixelPackedSampleModel.class);
|
||||
classes.add(BandedSampleModel.class);
|
||||
classes.add(PixelInterleavedSampleModel.class);
|
||||
|
||||
for (Class<? extends SampleModel> c : classes) {
|
||||
doTest(c);
|
||||
}
|
||||
}
|
||||
private static void doTest(Class<? extends SampleModel> c) {
|
||||
System.out.println("Test for: " + c.getName());
|
||||
SampleModel sm = createSampleModel(c);
|
||||
|
||||
DataBuffer db = sm.createDataBuffer();
|
||||
|
||||
int[] iArray = new int[ width * height + numBands];
|
||||
float[] fArray = new float[ width * height + numBands];
|
||||
double[] dArray = new double[ width * height + numBands];
|
||||
|
||||
boolean iOk = false;
|
||||
boolean fOk = false;
|
||||
boolean dOk = false;
|
||||
|
||||
try {
|
||||
sm.getSamples(Integer.MAX_VALUE, 0, 1, 1, 0, iArray, db);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println(e.getMessage());
|
||||
iOk = true;
|
||||
}
|
||||
|
||||
try {
|
||||
sm.getSamples(Integer.MAX_VALUE, 0, 1, 1, 0, fArray, db);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println(e.getMessage());
|
||||
fOk = true;
|
||||
}
|
||||
|
||||
try {
|
||||
sm.getSamples(0, Integer.MAX_VALUE, 1, 1, 0, dArray, db);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println(e.getMessage());
|
||||
dOk = true;
|
||||
}
|
||||
if (!iOk || !fOk || !dOk) {
|
||||
throw new RuntimeException("Test for " + c.getSimpleName() +
|
||||
" failed: iOk=" + iOk + "; fOk=" + fOk + "; dOk=" + dOk);
|
||||
}
|
||||
}
|
||||
|
||||
private static SampleModel createSampleModel(Class<? extends SampleModel> cls) {
|
||||
SampleModel res = null;
|
||||
|
||||
if (cls == ComponentSampleModel.class) {
|
||||
res = new ComponentSampleModel(dataType, width, height, 4, width * 4, new int[] { 0, 1, 2, 3 } );
|
||||
} else if (cls == MultiPixelPackedSampleModel.class) {
|
||||
res = new MultiPixelPackedSampleModel(dataType, width, height, 4);
|
||||
} else if (cls == SinglePixelPackedSampleModel.class) {
|
||||
res = new SinglePixelPackedSampleModel(dataType, width, height,
|
||||
new int[]{ 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff });
|
||||
} else if (cls == BandedSampleModel.class) {
|
||||
res = new BandedSampleModel(dataType, width, height, numBands);
|
||||
} else if (cls == PixelInterleavedSampleModel.class) {
|
||||
res = new PixelInterleavedSampleModel(dataType, width, height, 4, width * 4, new int[] { 0, 1, 2, 3 });
|
||||
} else {
|
||||
throw new RuntimeException("Unknown class " + cls);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
71
jdk/test/java/beans/Introspector/6976577/Test6976577.java
Normal file
71
jdk/test/java/beans/Introspector/6976577/Test6976577.java
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6976577
|
||||
* @summary Tests public methods in non-public beans
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
|
||||
import test.Accessor;
|
||||
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.IndexedPropertyDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Test6976577 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class<?> bt = Accessor.getBeanType();
|
||||
Class<?> lt = Accessor.getListenerType();
|
||||
|
||||
// test PropertyDescriptor
|
||||
PropertyDescriptor pd = new PropertyDescriptor("boolean", bt);
|
||||
test(pd.getReadMethod());
|
||||
test(pd.getWriteMethod());
|
||||
|
||||
// test IndexedPropertyDescriptor
|
||||
IndexedPropertyDescriptor ipd = new IndexedPropertyDescriptor("indexed", bt);
|
||||
test(ipd.getReadMethod());
|
||||
test(ipd.getWriteMethod());
|
||||
test(ipd.getIndexedReadMethod());
|
||||
test(ipd.getIndexedWriteMethod());
|
||||
|
||||
// test EventSetDescriptor
|
||||
EventSetDescriptor esd = new EventSetDescriptor(bt, "test", lt, "process");
|
||||
test(esd.getAddListenerMethod());
|
||||
test(esd.getRemoveListenerMethod());
|
||||
test(esd.getGetListenerMethod());
|
||||
test(esd.getListenerMethods());
|
||||
}
|
||||
|
||||
private static void test(Method... methods) {
|
||||
for (Method method : methods) {
|
||||
if (method == null) {
|
||||
throw new Error("public method is not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
jdk/test/java/beans/Introspector/6976577/test/Accessor.java
Normal file
81
jdk/test/java/beans/Introspector/6976577/test/Accessor.java
Normal file
@ -0,0 +1,81 @@
|
||||
package test;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.EventListener;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
public class Accessor {
|
||||
|
||||
public static Class<?> getBeanType() {
|
||||
return Bean.class;
|
||||
}
|
||||
|
||||
public static Class<?> getListenerType() {
|
||||
return TestListener.class;
|
||||
}
|
||||
}
|
||||
|
||||
interface TestEvent {
|
||||
}
|
||||
|
||||
interface TestListener extends EventListener {
|
||||
void process(TestEvent event);
|
||||
}
|
||||
|
||||
class Bean {
|
||||
|
||||
private boolean b;
|
||||
private int[] indexed;
|
||||
private TestListener listener;
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addTestListener(TestListener listener) throws TooManyListenersException {
|
||||
if (listener != null) {
|
||||
if (this.listener != null) {
|
||||
throw new TooManyListenersException();
|
||||
}
|
||||
this.listener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTestListener(TestListener listener) {
|
||||
if (this.listener == listener) {
|
||||
this.listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
public TestListener[] getTestListeners() {
|
||||
return (this.listener != null)
|
||||
? new TestListener[] { this.listener }
|
||||
: new TestListener[0];
|
||||
}
|
||||
|
||||
public boolean isBoolean() {
|
||||
return this.b;
|
||||
}
|
||||
|
||||
public void setBoolean(boolean b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int[] getIndexed() {
|
||||
return this.indexed;
|
||||
}
|
||||
|
||||
public void setIndexed(int[] values) {
|
||||
this.indexed = values;
|
||||
}
|
||||
|
||||
public int getIndexed(int index) {
|
||||
return this.indexed[index];
|
||||
}
|
||||
|
||||
public void setIndexed(int index, int value) {
|
||||
this.indexed[index] = value;
|
||||
}
|
||||
}
|
||||
44
jdk/test/javax/swing/JComboBox/6632953/bug6632953.java
Normal file
44
jdk/test/javax/swing/JComboBox/6632953/bug6632953.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6632953
|
||||
* @summary MetalComboBoxUI.getBaseline(JComponent, int, int) throws IAE for valid width/height
|
||||
* @author Alexander Potochkin
|
||||
*/
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.plaf.metal.MetalComboBoxUI;
|
||||
|
||||
public class bug6632953 {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
MetalComboBoxUI ui = new MetalComboBoxUI();
|
||||
ui.installUI(new JComboBox());
|
||||
ui.getBaseline(new JComboBox(), 0, 0);
|
||||
ui.getBaseline(new JComboBox(), 1, 1);
|
||||
ui.getBaseline(new JComboBox(), 2, 2);
|
||||
ui.getBaseline(new JComboBox(), 3, 3);
|
||||
ui.getBaseline(new JComboBox(), 4, 4);
|
||||
}
|
||||
}
|
||||
92
jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java
Normal file
92
jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@bug 6542335
|
||||
@summary different behavior on knob of scroll bar between 1.4.2 and 5.0
|
||||
@author Alexander Potochkin
|
||||
@run main bug6542335
|
||||
*/
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
|
||||
public class bug6542335 {
|
||||
private static JScrollBar sb;
|
||||
private static MyScrollBarUI ui;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Robot robot = new Robot();
|
||||
robot.setAutoDelay(10);
|
||||
|
||||
SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
final JFrame frame = new JFrame("bug6542335");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
sb = new JScrollBar(0, 0, 1, 0, 1);
|
||||
|
||||
ui = new MyScrollBarUI();
|
||||
sb.setUI(ui);
|
||||
|
||||
sb.setPreferredSize(new Dimension(200, 17));
|
||||
DefaultBoundedRangeModel rangeModel = new DefaultBoundedRangeModel();
|
||||
rangeModel.setMaximum(100);
|
||||
rangeModel.setMinimum(0);
|
||||
rangeModel.setExtent(50);
|
||||
rangeModel.setValue(50);
|
||||
|
||||
sb.setModel(rangeModel);
|
||||
frame.add(sb);
|
||||
|
||||
frame.setSize(200, 100);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
Rectangle thumbBounds = new Rectangle(ui.getThumbBounds());
|
||||
|
||||
toolkit.realSync();
|
||||
Point l = sb.getLocationOnScreen();
|
||||
robot.mouseMove(l.x + (int) (0.75 * sb.getWidth()), l.y + sb.getHeight()/2);
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
toolkit.realSync();
|
||||
|
||||
if (!thumbBounds.equals(ui.getThumbBounds())) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
|
||||
static class MyScrollBarUI extends BasicScrollBarUI {
|
||||
public Rectangle getThumbBounds() {
|
||||
return super.getThumbBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 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
|
||||
@ -71,14 +71,14 @@ public class Test6888156 {
|
||||
table = new JTable(model);
|
||||
}
|
||||
|
||||
public void test(final LookAndFeel laf) throws Exception {
|
||||
public void test(final String laf) throws Exception {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
System.out.println(laf);
|
||||
UIManager.setLookAndFeel(laf);
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
System.err.println(laf.getDescription() +
|
||||
" is unsupported; continuing");
|
||||
} catch (Exception e) {
|
||||
System.err.println(laf + " is unsupported; continuing");
|
||||
return;
|
||||
}
|
||||
SwingUtilities.updateComponentTreeUI(table);
|
||||
@ -92,8 +92,10 @@ public class Test6888156 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Test6888156 t = new Test6888156();
|
||||
t.test(new javax.swing.plaf.nimbus.NimbusLookAndFeel());
|
||||
t.test(new com.sun.java.swing.plaf.gtk.GTKLookAndFeel());
|
||||
t.test("javax.swing.plaf.nimbus.NimbusLookAndFeel");
|
||||
t.test("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
|
||||
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
|
||||
t.test(laf.getClassName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -56,6 +56,7 @@ public class bug6940863 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
|
||||
System.out.println("The test is suitable only for Windows OS. Skipped");
|
||||
return;
|
||||
}
|
||||
|
||||
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
|
||||
|
||||
@ -86,3 +86,5 @@ a408ebb8b3d427dbb3d8ce153dfaeb060564a0a4 jdk7-b108
|
||||
4826378eaade4c6676c452efe954be4ee113cc11 jdk7-b109
|
||||
32da0f38d2fe96c558492b8707b40da24643d41e jdk7-b110
|
||||
8bec624274ef8535720cff553374347c2f4f5fb2 jdk7-b111
|
||||
fd2579b80b83bf5d4289426016c7d29174ba5dd9 jdk7-b112
|
||||
6dbd2d869b0573fa5b799a23cccff47d20c12696 jdk7-b113
|
||||
|
||||
@ -31,44 +31,44 @@
|
||||
-->
|
||||
|
||||
<project name="langtools-netbeans" default="build" basedir="../../..">
|
||||
|
||||
<property name="langtools.properties"
|
||||
|
||||
<property name="langtools.properties"
|
||||
location="make/netbeans/langtools/nbproject/private/langtools.properties"/>
|
||||
|
||||
<!--
|
||||
|
||||
<!--
|
||||
Instead of importing the main build file, we could call it when needed.
|
||||
That would reduce the list of Ant targets that get displayed for this
|
||||
file, but it also complicates the interface between the project build
|
||||
file, but it also complicates the interface between the project build
|
||||
file and the main build file. For example, some imported targets
|
||||
would have to be reclared, properties would have to be restructured,
|
||||
and it would be harder to run results (e.g. in properties) from nested
|
||||
and it would be harder to run results (e.g. in properties) from nested
|
||||
targets.
|
||||
-->
|
||||
<import file="../../build.xml"/>
|
||||
|
||||
<import file="../../build.xml"/>
|
||||
|
||||
<!-- Build project. (action: build; F11)
|
||||
If langtools.tool.name is set, then just build that tool; otherwise
|
||||
build all tools.
|
||||
-->
|
||||
|
||||
<target name="build" depends="-get-tool-if-set,-build-tool,-build-all"
|
||||
|
||||
<target name="build" depends="-get-tool-if-set,-build-tool,-build-all"
|
||||
description="Build one or all langtools tools"
|
||||
/>
|
||||
|
||||
|
||||
<target name="-build-tool" if="langtools.tool.name">
|
||||
<echo level="info" message="Building ${langtools.tool.name}"/>
|
||||
<echo level="verbose" message="(Unset langtools.tool.name to build all tools)"/>
|
||||
<antcall target="build-${langtools.tool.name}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-build-all" unless="langtools.tool.name">
|
||||
<echo level="info" message="Building all tools"/>
|
||||
<echo level="verbose" message="(Set langtools.tool.name to build a single tool)"/>
|
||||
<antcall target="build-all-tools"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Compile a single file. (action: compile.single; F9) -->
|
||||
|
||||
|
||||
<target name="compile-single" depends="build-bootstrap-javac">
|
||||
<fail unless="includes">Must set property 'includes'</fail>
|
||||
<javac fork="true" executable="${build.bootstrap.dir}/bin/javac"
|
||||
@ -78,38 +78,38 @@
|
||||
sourcepath=""
|
||||
includeAntRuntime="no"
|
||||
target="${javac.target}"
|
||||
debug="${javac.debug}"
|
||||
debug="${javac.debug}"
|
||||
debuglevel="${javac.debuglevel}"/>
|
||||
</target>
|
||||
|
||||
<!-- Run tool. (action: run; F6)
|
||||
|
||||
<!-- Run tool. (action: run; F6)
|
||||
Use langtools.tool.name and langtools.tool.args properties if set; otherwise prompt
|
||||
the user.
|
||||
-->
|
||||
|
||||
<target name="run" depends="-check-target.java.home,build,-def-run,-get-tool-and-args"
|
||||
|
||||
<target name="run" depends="-check-target.java.home,build,-def-run,-get-tool-and-args"
|
||||
description="run tool">
|
||||
<echo level="info" message="Run ${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<run mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Run a selected class. (action: run.single; shift-F6) -->
|
||||
|
||||
|
||||
<target name="run-single" depends="-check-target.java.home,-def-run">
|
||||
<fail unless="run.classname">Must set property 'run.classname' </fail>
|
||||
<echo level="info" message="run ${run.classname}"/>
|
||||
<run mainclass="${run.classname}" args=""/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Test project, and display results if tests failed. (action: test; Alt-F6)
|
||||
If langtools.tool.name is set, then just test that tool; otherwise
|
||||
test all tools.
|
||||
-->
|
||||
|
||||
<target name="jtreg" depends="-get-tool-if-set,-jtreg-tool,-jtreg-all"
|
||||
|
||||
<target name="jtreg" depends="-get-tool-if-set,-jtreg-tool,-jtreg-all"
|
||||
description="Test one or all langtools tools"
|
||||
/>
|
||||
|
||||
|
||||
<target name="-jtreg-tool" if="langtools.tool.name">
|
||||
<echo level="info" message="Testing ${langtools.tool.name}"/>
|
||||
<echo level="verbose" message="(Unset langtools.tool.name to test all tools)"/>
|
||||
@ -118,7 +118,7 @@
|
||||
<target name="-show-jtreg"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-jtreg-all" unless="langtools.tool.name">
|
||||
<echo level="info" message="Testing all tools"/>
|
||||
<echo level="verbose" message="(Set langtools.tool.name to test a single tool)"/>
|
||||
@ -127,36 +127,36 @@
|
||||
<target name="-show-jtreg"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-show-jtreg" if="netbeans.home" unless="jtreg.passed">
|
||||
<nbbrowse file="${jtreg.report}/report.html"/>
|
||||
<fail>Some tests failed; see report for details.</fail>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Debug tool in NetBeans. -->
|
||||
|
||||
|
||||
<target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,build" if="netbeans.home">
|
||||
<echo level="info" message="Debug ${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<start-debugger/>
|
||||
<run mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Debug a selected class . -->
|
||||
<target name="debug-single" depends="-check-target.java.home,-def-start-debugger,-def-run">
|
||||
<fail unless="debug.classname">Must set property 'debug.classname'</fail>
|
||||
<start-debugger/>
|
||||
<run mainclass="${debug.classname}" default.args="" jpda.jvmargs="${jpda.jvmargs}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Debug a jtreg test. -->
|
||||
<target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg">
|
||||
<fail unless="jtreg.tests">Must set property 'jtreg.tests'</fail>
|
||||
<start-debugger/>
|
||||
<jtreg-tool name="debug" samevm="false" tests="${jtreg.tests}" jpda.jvmargs="${jpda.jvmargs}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Update a class being debugged. -->
|
||||
|
||||
|
||||
<target name="debug-fix" if="langtools.tool.name">
|
||||
<fail unless="class">Must set property 'class'
|
||||
</fail>
|
||||
@ -169,16 +169,16 @@
|
||||
</fileset>
|
||||
</nbjpdareload>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Generate javadoc for one or all tools. (action: javadoc; Alt-F6)
|
||||
If langtools.tool.name is set, then just test that tool; otherwise
|
||||
test all tools.
|
||||
-->
|
||||
|
||||
<target name="javadoc" depends="-javadoc-tool,-javadoc-all"
|
||||
|
||||
<target name="javadoc" depends="-javadoc-tool,-javadoc-all"
|
||||
description="Generate javadoc for one or all langtools tools"
|
||||
/>
|
||||
|
||||
|
||||
<target name="-javadoc-tool" if="langtools.tool.name">
|
||||
<echo level="info" message="Generate javadoc for ${langtools.tool.name}"/>
|
||||
<echo level="verbose" message="(Unset langtools.tool.name to generate javadoc for all tools)"/>
|
||||
@ -187,7 +187,7 @@
|
||||
<target name="-show-javadoc"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-javadoc-all" unless="langtools.tool.name">
|
||||
<echo level="info" message="Generate javadoc for all tools"/>
|
||||
<echo level="verbose" message="(Set langtools.tool.name to generate javadoc for a single tool)"/>
|
||||
@ -196,26 +196,26 @@
|
||||
<target name="-show-javadoc"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-show-javadoc" if="netbeans.home">
|
||||
<!-- what if doing javadoc for all? -->
|
||||
<nbbrowse file="${build.javadoc.dir}/${langtools.tool.name}/index.html"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Prompt for values. -->
|
||||
|
||||
|
||||
<target name="-get-tool-if-set" depends="-def-select-tool">
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
propertyfile="${langtools.properties}"
|
||||
askIfUnset="false"
|
||||
/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-get-tool-and-args" depends="-def-select-tool">
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
argsproperty="langtools.tool.args"
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
argsproperty="langtools.tool.args"
|
||||
propertyfile="${langtools.properties}"
|
||||
askIfUnset="true"
|
||||
/>
|
||||
@ -236,7 +236,7 @@
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Macro to start the debugger and set a property containg the args needed by the run task -->
|
||||
<target name="-def-start-debugger" if="netbeans.home">
|
||||
<macrodef name="start-debugger">
|
||||
@ -251,28 +251,29 @@
|
||||
<pathelement location="${src.classes.dir}"/>
|
||||
</sourcepath>
|
||||
</nbjpdastart>
|
||||
<property
|
||||
name="@{jpda.jvmargs.property}"
|
||||
<property
|
||||
name="@{jpda.jvmargs.property}"
|
||||
value="-Xdebug -Xnoagent -Djava.compiler=none -Xrunjdwp:transport=dt_socket,address=${jpda.address}"
|
||||
/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="-def-select-tool">
|
||||
<mkdir dir="${build.toolclasses.dir}"/>
|
||||
<javac srcdir="${make.tools.dir}/SelectTool"
|
||||
destdir="${build.toolclasses.dir}/"
|
||||
classpath="${ant.home}/lib/ant.jar"
|
||||
debug="${javac.debug}"
|
||||
classpath="${ant.core.lib}"
|
||||
includeantruntime="false"
|
||||
debug="${javac.debug}"
|
||||
debuglevel="${javac.debuglevel}">
|
||||
<compilerarg line="-Xlint"/>
|
||||
</javac>
|
||||
<taskdef name="select-tool"
|
||||
classname="SelectToolTask"
|
||||
classname="SelectToolTask"
|
||||
classpath="${build.toolclasses.dir}/"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="select-tool" depends="-def-select-tool">
|
||||
<select-tool propertyfile="${langtools.properties}"/>
|
||||
</target>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 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
|
||||
@ -99,9 +99,6 @@ public class JavaCompiler extends com.sun.tools.javac.main.JavaCompiler {
|
||||
private static Context preRegister(Context context) {
|
||||
Bark.preRegister(context);
|
||||
|
||||
// force the use of the scanner that captures Javadoc comments
|
||||
DocCommentScanner.Factory.preRegister(context);
|
||||
|
||||
if (context.get(JavaFileManager.class) == null)
|
||||
JavacFileManager.preRegister(context);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -96,9 +96,6 @@ public class JavacTaskImpl extends JavacTask {
|
||||
args.getClass();
|
||||
context.getClass();
|
||||
fileObjects.getClass();
|
||||
|
||||
// force the use of the scanner that captures Javadoc comments
|
||||
com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context);
|
||||
}
|
||||
|
||||
JavacTaskImpl(JavacTool tool,
|
||||
@ -337,9 +334,13 @@ public class JavacTaskImpl extends JavacTask {
|
||||
|
||||
ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
|
||||
for (JCCompilationUnit unit : units) {
|
||||
for (JCTree node : unit.defs)
|
||||
if (node.getTag() == JCTree.CLASSDEF)
|
||||
elements.append(((JCTree.JCClassDecl) node).sym);
|
||||
for (JCTree node : unit.defs) {
|
||||
if (node.getTag() == JCTree.CLASSDEF) {
|
||||
JCClassDecl cdef = (JCClassDecl) node;
|
||||
if (cdef.sym != null) // maybe null if errors in anno processing
|
||||
elements.append(cdef.sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.toList();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -56,7 +56,6 @@ import com.sun.tools.javac.comp.Env;
|
||||
import com.sun.tools.javac.comp.MemberEnter;
|
||||
import com.sun.tools.javac.comp.Resolve;
|
||||
import com.sun.tools.javac.model.JavacElements;
|
||||
import com.sun.tools.javac.processing.JavacMessager;
|
||||
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
@ -81,14 +80,15 @@ import com.sun.tools.javac.util.Pair;
|
||||
*/
|
||||
public class JavacTrees extends Trees {
|
||||
|
||||
private final Resolve resolve;
|
||||
private final Enter enter;
|
||||
private final Log log;
|
||||
private final MemberEnter memberEnter;
|
||||
private final Attr attr;
|
||||
private final TreeMaker treeMaker;
|
||||
private final JavacElements elements;
|
||||
private final JavacTaskImpl javacTaskImpl;
|
||||
// in a world of a single context per compilation, these would all be final
|
||||
private Resolve resolve;
|
||||
private Enter enter;
|
||||
private Log log;
|
||||
private MemberEnter memberEnter;
|
||||
private Attr attr;
|
||||
private TreeMaker treeMaker;
|
||||
private JavacElements elements;
|
||||
private JavacTaskImpl javacTaskImpl;
|
||||
|
||||
public static JavacTrees instance(JavaCompiler.CompilationTask task) {
|
||||
if (!(task instanceof JavacTaskImpl))
|
||||
@ -111,6 +111,14 @@ public class JavacTrees extends Trees {
|
||||
|
||||
private JavacTrees(Context context) {
|
||||
context.put(JavacTrees.class, this);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public void updateContext(Context context) {
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
attr = Attr.instance(context);
|
||||
enter = Enter.instance(context);
|
||||
elements = JavacElements.instance(context);
|
||||
@ -337,6 +345,7 @@ public class JavacTrees extends Trees {
|
||||
super(M);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends JCTree> T copy(T t, JCTree leaf) {
|
||||
T t2 = super.copy(t, leaf);
|
||||
if (t == leaf)
|
||||
|
||||
@ -70,6 +70,45 @@ public class Scope {
|
||||
*/
|
||||
public int nelems = 0;
|
||||
|
||||
/** A timestamp - useful to quickly check whether a scope has changed or not
|
||||
*/
|
||||
public ScopeCounter scopeCounter;
|
||||
|
||||
static ScopeCounter dummyCounter = new ScopeCounter() {
|
||||
@Override
|
||||
public void inc() {
|
||||
//do nothing
|
||||
}
|
||||
};
|
||||
|
||||
public static class ScopeCounter {
|
||||
protected static final Context.Key<ScopeCounter> scopeCounterKey =
|
||||
new Context.Key<ScopeCounter>();
|
||||
|
||||
public static ScopeCounter instance(Context context) {
|
||||
ScopeCounter instance = context.get(scopeCounterKey);
|
||||
if (instance == null)
|
||||
instance = new ScopeCounter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected ScopeCounter(Context context) {
|
||||
context.put(scopeCounterKey, this);
|
||||
}
|
||||
|
||||
private ScopeCounter() {};
|
||||
|
||||
private long val = 0;
|
||||
|
||||
public void inc() {
|
||||
val++;
|
||||
}
|
||||
|
||||
public long val() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Every hash bucket is a list of Entry's which ends in sentinel.
|
||||
*/
|
||||
private static final Entry sentinel = new Entry(null, null, null, null);
|
||||
@ -80,12 +119,12 @@ public class Scope {
|
||||
|
||||
/** A value for the empty scope.
|
||||
*/
|
||||
public static final Scope emptyScope = new Scope(null, null, new Entry[]{});
|
||||
public static final Scope emptyScope = new Scope(null, null, new Entry[]{}, dummyCounter);
|
||||
|
||||
/** Construct a new scope, within scope next, with given owner, using
|
||||
* given table. The table's length must be an exponent of 2.
|
||||
*/
|
||||
Scope(Scope next, Symbol owner, Entry[] table) {
|
||||
private Scope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
|
||||
this.next = next;
|
||||
assert emptyScope == null || owner != null;
|
||||
this.owner = owner;
|
||||
@ -94,13 +133,18 @@ public class Scope {
|
||||
this.elems = null;
|
||||
this.nelems = 0;
|
||||
this.shared = 0;
|
||||
this.scopeCounter = scopeCounter;
|
||||
}
|
||||
|
||||
/** Construct a new scope, within scope next, with given owner,
|
||||
* using a fresh table of length INITIAL_SIZE.
|
||||
*/
|
||||
public Scope(Symbol owner) {
|
||||
this(null, owner, new Entry[INITIAL_SIZE]);
|
||||
this(owner, dummyCounter);
|
||||
}
|
||||
|
||||
protected Scope(Symbol owner, ScopeCounter scopeCounter) {
|
||||
this(null, owner, new Entry[INITIAL_SIZE], scopeCounter);
|
||||
for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel;
|
||||
}
|
||||
|
||||
@ -110,7 +154,7 @@ public class Scope {
|
||||
* of fresh tables.
|
||||
*/
|
||||
public Scope dup() {
|
||||
Scope result = new Scope(this, this.owner, this.table);
|
||||
Scope result = new Scope(this, this.owner, this.table, scopeCounter);
|
||||
shared++;
|
||||
// System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode());
|
||||
// new Error().printStackTrace(System.out);
|
||||
@ -123,7 +167,7 @@ public class Scope {
|
||||
* of fresh tables.
|
||||
*/
|
||||
public Scope dup(Symbol newOwner) {
|
||||
Scope result = new Scope(this, newOwner, this.table);
|
||||
Scope result = new Scope(this, newOwner, this.table, scopeCounter);
|
||||
shared++;
|
||||
// System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
|
||||
// new Error().printStackTrace(System.out);
|
||||
@ -135,7 +179,7 @@ public class Scope {
|
||||
* the table of its outer scope.
|
||||
*/
|
||||
public Scope dupUnshared() {
|
||||
return new Scope(this, this.owner, this.table.clone());
|
||||
return new Scope(this, this.owner, this.table.clone(), scopeCounter);
|
||||
}
|
||||
|
||||
/** Remove all entries of this scope from its table, if shared
|
||||
@ -211,6 +255,7 @@ public class Scope {
|
||||
table[hash] = e;
|
||||
elems = e;
|
||||
nelems++;
|
||||
scopeCounter.inc();
|
||||
}
|
||||
|
||||
Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
|
||||
@ -226,6 +271,8 @@ public class Scope {
|
||||
while (e.scope == this && e.sym != sym) e = e.next();
|
||||
if (e.scope == null) return;
|
||||
|
||||
scopeCounter.inc();
|
||||
|
||||
// remove e from table and shadowed list;
|
||||
Entry te = table[sym.name.hashCode() & hashMask];
|
||||
if (te == e)
|
||||
@ -472,7 +519,7 @@ public class Scope {
|
||||
public static final Entry[] emptyTable = new Entry[0];
|
||||
|
||||
public DelegatedScope(Scope outer) {
|
||||
super(outer, outer.owner, emptyTable);
|
||||
super(outer, outer.owner, emptyTable, outer.scopeCounter);
|
||||
delegatee = outer;
|
||||
}
|
||||
public Scope dup() {
|
||||
@ -498,10 +545,22 @@ public class Scope {
|
||||
}
|
||||
}
|
||||
|
||||
/** A class scope, for which a scope counter should be provided */
|
||||
public static class ClassScope extends Scope {
|
||||
|
||||
ClassScope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
|
||||
super(next, owner, table, scopeCounter);
|
||||
}
|
||||
|
||||
public ClassScope(Symbol owner, ScopeCounter scopeCounter) {
|
||||
super(owner, scopeCounter);
|
||||
}
|
||||
}
|
||||
|
||||
/** An error scope, for which the owner should be an error symbol. */
|
||||
public static class ErrorScope extends Scope {
|
||||
ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
|
||||
super(next, /*owner=*/errSymbol, table);
|
||||
super(next, /*owner=*/errSymbol, table, dummyCounter);
|
||||
}
|
||||
public ErrorScope(Symbol errSymbol) {
|
||||
super(errSymbol);
|
||||
|
||||
@ -25,11 +25,14 @@
|
||||
|
||||
package com.sun.tools.javac.code;
|
||||
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
import java.util.*;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import static javax.lang.model.SourceVersion.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
|
||||
import static com.sun.tools.javac.main.OptionName.*;
|
||||
|
||||
/** The source language version accepted.
|
||||
*
|
||||
@ -71,7 +74,7 @@ public enum Source {
|
||||
Source instance = context.get(sourceKey);
|
||||
if (instance == null) {
|
||||
Options options = Options.instance(context);
|
||||
String sourceString = options.get("-source");
|
||||
String sourceString = options.get(SOURCE);
|
||||
if (sourceString != null) instance = lookup(sourceString);
|
||||
if (instance == null) instance = DEFAULT;
|
||||
context.put(sourceKey, instance);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -960,6 +960,8 @@ public abstract class Symbol implements Element {
|
||||
return ElementKind.ENUM_CONSTANT;
|
||||
} else if (owner.kind == TYP || owner.kind == ERR) {
|
||||
return ElementKind.FIELD;
|
||||
} else if (isResourceVariable()) {
|
||||
return ElementKind.RESOURCE_VARIABLE;
|
||||
} else {
|
||||
return ElementKind.LOCAL_VARIABLE;
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ public class Symtab {
|
||||
public final JCNoType voidType = new JCNoType(TypeTags.VOID);
|
||||
|
||||
private final Names names;
|
||||
private final Scope.ScopeCounter scopeCounter;
|
||||
private final ClassReader reader;
|
||||
private final Target target;
|
||||
|
||||
@ -340,6 +341,7 @@ public class Symtab {
|
||||
context.put(symtabKey, this);
|
||||
|
||||
names = Names.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
target = Target.instance(context);
|
||||
|
||||
// Create the unknown type
|
||||
@ -386,7 +388,7 @@ public class Symtab {
|
||||
|
||||
// Create class to hold all predefined constants and operations.
|
||||
predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage);
|
||||
Scope scope = new Scope(predefClass);
|
||||
Scope scope = new Scope.ClassScope(predefClass, scopeCounter);
|
||||
predefClass.members_field = scope;
|
||||
|
||||
// Enter symbols for basic types.
|
||||
@ -476,7 +478,7 @@ public class Symtab {
|
||||
proprietarySymbol.completer = null;
|
||||
proprietarySymbol.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
|
||||
proprietarySymbol.erasure_field = proprietaryType;
|
||||
proprietarySymbol.members_field = new Scope(proprietarySymbol);
|
||||
proprietarySymbol.members_field = new Scope.ClassScope(proprietarySymbol, scopeCounter);
|
||||
proprietaryType.typarams_field = List.nil();
|
||||
proprietaryType.allparams_field = List.nil();
|
||||
proprietaryType.supertype_field = annotationType;
|
||||
@ -488,7 +490,7 @@ public class Symtab {
|
||||
ClassType arrayClassType = (ClassType)arrayClass.type;
|
||||
arrayClassType.supertype_field = objectType;
|
||||
arrayClassType.interfaces_field = List.of(cloneableType, serializableType);
|
||||
arrayClass.members_field = new Scope(arrayClass);
|
||||
arrayClass.members_field = new Scope.ClassScope(arrayClass, scopeCounter);
|
||||
lengthVar = new VarSymbol(
|
||||
PUBLIC | FINAL,
|
||||
names.length,
|
||||
|
||||
@ -69,6 +69,7 @@ public class Types {
|
||||
new Context.Key<Types>();
|
||||
|
||||
final Symtab syms;
|
||||
final Scope.ScopeCounter scopeCounter;
|
||||
final JavacMessages messages;
|
||||
final Names names;
|
||||
final boolean allowBoxing;
|
||||
@ -89,6 +90,7 @@ public class Types {
|
||||
protected Types(Context context) {
|
||||
context.put(typesKey, this);
|
||||
syms = Symtab.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
names = Names.instance(context);
|
||||
allowBoxing = Source.instance(context).allowBoxing();
|
||||
reader = ClassReader.instance(context);
|
||||
@ -1984,22 +1986,26 @@ public class Types {
|
||||
final MethodSymbol cachedImpl;
|
||||
final Filter<Symbol> implFilter;
|
||||
final boolean checkResult;
|
||||
final Scope.ScopeCounter scopeCounter;
|
||||
|
||||
public Entry(MethodSymbol cachedImpl,
|
||||
Filter<Symbol> scopeFilter,
|
||||
boolean checkResult) {
|
||||
boolean checkResult,
|
||||
Scope.ScopeCounter scopeCounter) {
|
||||
this.cachedImpl = cachedImpl;
|
||||
this.implFilter = scopeFilter;
|
||||
this.checkResult = checkResult;
|
||||
this.scopeCounter = scopeCounter;
|
||||
}
|
||||
|
||||
boolean matches(Filter<Symbol> scopeFilter, boolean checkResult) {
|
||||
boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, Scope.ScopeCounter scopeCounter) {
|
||||
return this.implFilter == scopeFilter &&
|
||||
this.checkResult == checkResult;
|
||||
this.checkResult == checkResult &&
|
||||
this.scopeCounter.val() >= scopeCounter.val();
|
||||
}
|
||||
}
|
||||
|
||||
MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
|
||||
MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter, Scope.ScopeCounter scopeCounter) {
|
||||
SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
|
||||
Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
|
||||
if (cache == null) {
|
||||
@ -2008,9 +2014,9 @@ public class Types {
|
||||
}
|
||||
Entry e = cache.get(origin);
|
||||
if (e == null ||
|
||||
!e.matches(implFilter, checkResult)) {
|
||||
!e.matches(implFilter, checkResult, scopeCounter)) {
|
||||
MethodSymbol impl = implementationInternal(ms, origin, Types.this, checkResult, implFilter);
|
||||
cache.put(origin, new Entry(impl, implFilter, checkResult));
|
||||
cache.put(origin, new Entry(impl, implFilter, checkResult, scopeCounter));
|
||||
return impl;
|
||||
}
|
||||
else {
|
||||
@ -2038,7 +2044,7 @@ public class Types {
|
||||
private ImplementationCache implCache = new ImplementationCache();
|
||||
|
||||
public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
|
||||
return implCache.get(ms, origin, checkResult, implFilter);
|
||||
return implCache.get(ms, origin, checkResult, implFilter, scopeCounter);
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
|
||||
@ -119,10 +119,10 @@ public class Attr extends JCTree.Visitor {
|
||||
allowAnonOuterThis = source.allowAnonOuterThis();
|
||||
allowStringsInSwitch = source.allowStringsInSwitch();
|
||||
sourceName = source.name;
|
||||
relax = (options.get("-retrofit") != null ||
|
||||
options.get("-relax") != null);
|
||||
useBeforeDeclarationWarning = options.get("useBeforeDeclarationWarning") != null;
|
||||
enableSunApiLintControl = options.get("enableSunApiLintControl") != null;
|
||||
relax = (options.isSet("-retrofit") ||
|
||||
options.isSet("-relax"));
|
||||
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
|
||||
enableSunApiLintControl = options.isSet("enableSunApiLintControl");
|
||||
}
|
||||
|
||||
/** Switch: relax some constraints for retrofit mode.
|
||||
@ -1422,7 +1422,8 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
// Compute the result type.
|
||||
Type restype = mtype.getReturnType();
|
||||
assert restype.tag != WILDCARD : mtype;
|
||||
if (restype.tag == WILDCARD)
|
||||
throw new AssertionError(mtype);
|
||||
|
||||
// as a special case, array.clone() has a result that is
|
||||
// the same as static type of the array being cloned
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import com.sun.source.tree.AssignmentTree;
|
||||
import java.util.*;
|
||||
import java.util.Set;
|
||||
|
||||
@ -46,6 +45,8 @@ import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Kinds.*;
|
||||
import static com.sun.tools.javac.code.TypeTags.*;
|
||||
|
||||
import static com.sun.tools.javac.main.OptionName.*;
|
||||
|
||||
/** Type checking helper class for the attribution phase.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
@ -60,6 +61,7 @@ public class Check {
|
||||
private final Names names;
|
||||
private final Log log;
|
||||
private final Symtab syms;
|
||||
private final Enter enter;
|
||||
private final Infer infer;
|
||||
private final Types types;
|
||||
private final JCDiagnostic.Factory diags;
|
||||
@ -86,6 +88,7 @@ public class Check {
|
||||
names = Names.instance(context);
|
||||
log = Log.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
enter = Enter.instance(context);
|
||||
infer = Infer.instance(context);
|
||||
this.types = Types.instance(context);
|
||||
diags = JCDiagnostic.Factory.instance(context);
|
||||
@ -97,10 +100,10 @@ public class Check {
|
||||
allowGenerics = source.allowGenerics();
|
||||
allowAnnotations = source.allowAnnotations();
|
||||
allowCovariantReturns = source.allowCovariantReturns();
|
||||
complexInference = options.get("-complexinference") != null;
|
||||
skipAnnotations = options.get("skipAnnotations") != null;
|
||||
warnOnSyntheticConflicts = options.get("warnOnSyntheticConflicts") != null;
|
||||
suppressAbortOnBadClassFile = options.get("suppressAbortOnBadClassFile") != null;
|
||||
complexInference = options.isSet(COMPLEXINFERENCE);
|
||||
skipAnnotations = options.isSet("skipAnnotations");
|
||||
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
|
||||
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
|
||||
|
||||
Target target = Target.instance(context);
|
||||
syntheticNameChar = target.syntheticNameChar();
|
||||
@ -1727,6 +1730,113 @@ public class Check {
|
||||
return undef;
|
||||
}
|
||||
|
||||
void checkNonCyclicDecl(JCClassDecl tree) {
|
||||
CycleChecker cc = new CycleChecker();
|
||||
cc.scan(tree);
|
||||
if (!cc.errorFound && !cc.partialCheck) {
|
||||
tree.sym.flags_field |= ACYCLIC;
|
||||
}
|
||||
}
|
||||
|
||||
class CycleChecker extends TreeScanner {
|
||||
|
||||
List<Symbol> seenClasses = List.nil();
|
||||
boolean errorFound = false;
|
||||
boolean partialCheck = false;
|
||||
|
||||
private void checkSymbol(DiagnosticPosition pos, Symbol sym) {
|
||||
if (sym != null && sym.kind == TYP) {
|
||||
Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym);
|
||||
if (classEnv != null) {
|
||||
DiagnosticSource prevSource = log.currentSource();
|
||||
try {
|
||||
log.useSource(classEnv.toplevel.sourcefile);
|
||||
scan(classEnv.tree);
|
||||
}
|
||||
finally {
|
||||
log.useSource(prevSource.getFile());
|
||||
}
|
||||
} else if (sym.kind == TYP) {
|
||||
checkClass(pos, sym, List.<JCTree>nil());
|
||||
}
|
||||
} else {
|
||||
//not completed yet
|
||||
partialCheck = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSelect(JCFieldAccess tree) {
|
||||
super.visitSelect(tree);
|
||||
checkSymbol(tree.pos(), tree.sym);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIdent(JCIdent tree) {
|
||||
checkSymbol(tree.pos(), tree.sym);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeApply(JCTypeApply tree) {
|
||||
scan(tree.clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArray(JCArrayTypeTree tree) {
|
||||
scan(tree.elemtype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
List<JCTree> supertypes = List.nil();
|
||||
if (tree.getExtendsClause() != null) {
|
||||
supertypes = supertypes.prepend(tree.getExtendsClause());
|
||||
}
|
||||
if (tree.getImplementsClause() != null) {
|
||||
for (JCTree intf : tree.getImplementsClause()) {
|
||||
supertypes = supertypes.prepend(intf);
|
||||
}
|
||||
}
|
||||
checkClass(tree.pos(), tree.sym, supertypes);
|
||||
}
|
||||
|
||||
void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) {
|
||||
if ((c.flags_field & ACYCLIC) != 0)
|
||||
return;
|
||||
if (seenClasses.contains(c)) {
|
||||
errorFound = true;
|
||||
noteCyclic(pos, (ClassSymbol)c);
|
||||
} else if (!c.type.isErroneous()) {
|
||||
try {
|
||||
seenClasses = seenClasses.prepend(c);
|
||||
if (c.type.tag == CLASS) {
|
||||
if (supertypes.nonEmpty()) {
|
||||
scan(supertypes);
|
||||
}
|
||||
else {
|
||||
ClassType ct = (ClassType)c.type;
|
||||
if (ct.supertype_field == null ||
|
||||
ct.interfaces_field == null) {
|
||||
//not completed yet
|
||||
partialCheck = true;
|
||||
return;
|
||||
}
|
||||
checkSymbol(pos, ct.supertype_field.tsym);
|
||||
for (Type intf : ct.interfaces_field) {
|
||||
checkSymbol(pos, intf.tsym);
|
||||
}
|
||||
}
|
||||
if (c.owner.kind == TYP) {
|
||||
checkSymbol(pos, c.owner);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
seenClasses = seenClasses.tail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Check for cyclic references. Issue an error if the
|
||||
* symbol of the type referred to has a LOCKED flag set.
|
||||
*
|
||||
|
||||
@ -94,6 +94,7 @@ public class Enter extends JCTree.Visitor {
|
||||
|
||||
Log log;
|
||||
Symtab syms;
|
||||
Scope.ScopeCounter scopeCounter;
|
||||
Check chk;
|
||||
TreeMaker make;
|
||||
ClassReader reader;
|
||||
@ -121,6 +122,7 @@ public class Enter extends JCTree.Visitor {
|
||||
reader = ClassReader.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
chk = Check.instance(context);
|
||||
memberEnter = MemberEnter.instance(context);
|
||||
types = Types.instance(context);
|
||||
@ -189,7 +191,7 @@ public class Enter extends JCTree.Visitor {
|
||||
*/
|
||||
public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
|
||||
Env<AttrContext> localEnv =
|
||||
env.dup(tree, env.info.dup(new Scope(tree.sym)));
|
||||
env.dup(tree, env.info.dup(new Scope.ClassScope(tree.sym, scopeCounter)));
|
||||
localEnv.enclClass = tree;
|
||||
localEnv.outer = env;
|
||||
localEnv.info.isSelfCall = false;
|
||||
@ -325,7 +327,7 @@ public class Enter extends JCTree.Visitor {
|
||||
c.flatname = names.fromString(tree.packge + "." + name);
|
||||
c.sourcefile = tree.sourcefile;
|
||||
c.completer = null;
|
||||
c.members_field = new Scope(c);
|
||||
c.members_field = new Scope.ClassScope(c, scopeCounter);
|
||||
tree.packge.package_info = c;
|
||||
}
|
||||
classEnter(tree.defs, topEnv);
|
||||
@ -393,7 +395,7 @@ public class Enter extends JCTree.Visitor {
|
||||
c.completer = memberEnter;
|
||||
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
|
||||
c.sourcefile = env.toplevel.sourcefile;
|
||||
c.members_field = new Scope(c);
|
||||
c.members_field = new Scope.ClassScope(c, scopeCounter);
|
||||
|
||||
ClassType ct = (ClassType)c.type;
|
||||
if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
|
||||
|
||||
@ -80,25 +80,12 @@ public class Infer {
|
||||
|
||||
}
|
||||
|
||||
public static class InferenceException extends RuntimeException {
|
||||
public static class InferenceException extends Resolve.InapplicableMethodException {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
JCDiagnostic diagnostic;
|
||||
JCDiagnostic.Factory diags;
|
||||
|
||||
InferenceException(JCDiagnostic.Factory diags) {
|
||||
this.diagnostic = null;
|
||||
this.diags = diags;
|
||||
super(diags);
|
||||
}
|
||||
|
||||
InferenceException setMessage(String key, Object... args) {
|
||||
this.diagnostic = diags.fragment(key, args);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JCDiagnostic getDiagnostic() {
|
||||
return diagnostic;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoInstanceException extends InferenceException {
|
||||
@ -320,7 +307,7 @@ public class Infer {
|
||||
Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
|
||||
if (!types.isSubtype(qtype1, to)) {
|
||||
throw unambiguousNoInstanceException
|
||||
.setMessage("no.conforming.instance.exists",
|
||||
.setMessage("infer.no.conforming.instance.exists",
|
||||
that.tvars, that.qtype, to);
|
||||
}
|
||||
for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail)
|
||||
@ -378,6 +365,11 @@ public class Infer {
|
||||
// instantiate all polymorphic argument types and
|
||||
// set up lower bounds constraints for undetvars
|
||||
Type varargsFormal = useVarargs ? formals.last() : null;
|
||||
if (varargsFormal == null &&
|
||||
actuals.size() != formals.size()) {
|
||||
throw unambiguousNoInstanceException
|
||||
.setMessage("infer.arg.length.mismatch");
|
||||
}
|
||||
while (actuals.nonEmpty() && formals.head != varargsFormal) {
|
||||
Type formal = formals.head;
|
||||
Type actual = actuals.head.baseType();
|
||||
@ -390,19 +382,16 @@ public class Infer {
|
||||
: types.isSubtypeUnchecked(actual, undetFormal, warn);
|
||||
if (!works) {
|
||||
throw unambiguousNoInstanceException
|
||||
.setMessage("no.conforming.assignment.exists",
|
||||
.setMessage("infer.no.conforming.assignment.exists",
|
||||
tvars, actualNoCapture, formal);
|
||||
}
|
||||
formals = formals.tail;
|
||||
actuals = actuals.tail;
|
||||
actualsNoCapture = actualsNoCapture.tail;
|
||||
}
|
||||
if (formals.head != varargsFormal || // not enough args
|
||||
!useVarargs && actuals.nonEmpty()) { // too many args
|
||||
// argument lists differ in length
|
||||
throw unambiguousNoInstanceException
|
||||
.setMessage("arg.length.mismatch");
|
||||
}
|
||||
|
||||
if (formals.head != varargsFormal) // not enough args
|
||||
throw unambiguousNoInstanceException.setMessage("infer.arg.length.mismatch");
|
||||
|
||||
// for varargs arguments as well
|
||||
if (useVarargs) {
|
||||
@ -416,7 +405,7 @@ public class Infer {
|
||||
boolean works = types.isConvertible(actual, elemUndet, warn);
|
||||
if (!works) {
|
||||
throw unambiguousNoInstanceException
|
||||
.setMessage("no.conforming.assignment.exists",
|
||||
.setMessage("infer.no.conforming.assignment.exists",
|
||||
tvars, actualNoCapture, elemType);
|
||||
}
|
||||
actuals = actuals.tail;
|
||||
|
||||
@ -68,6 +68,7 @@ public class Lower extends TreeTranslator {
|
||||
private Names names;
|
||||
private Log log;
|
||||
private Symtab syms;
|
||||
private Scope.ScopeCounter scopeCounter;
|
||||
private Resolve rs;
|
||||
private Check chk;
|
||||
private Attr attr;
|
||||
@ -90,6 +91,7 @@ public class Lower extends TreeTranslator {
|
||||
names = Names.instance(context);
|
||||
log = Log.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
rs = Resolve.instance(context);
|
||||
chk = Check.instance(context);
|
||||
attr = Attr.instance(context);
|
||||
@ -107,7 +109,7 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
types = Types.instance(context);
|
||||
Options options = Options.instance(context);
|
||||
debugLower = options.get("debuglower") != null;
|
||||
debugLower = options.isSet("debuglower");
|
||||
pkginfoOpt = PkgInfo.get(options);
|
||||
}
|
||||
|
||||
@ -569,7 +571,7 @@ public class Lower extends TreeTranslator {
|
||||
c.flatname = chk.localClassName(c);
|
||||
c.sourcefile = owner.sourcefile;
|
||||
c.completer = null;
|
||||
c.members_field = new Scope(c);
|
||||
c.members_field = new Scope.ClassScope(c, scopeCounter);
|
||||
c.flags_field = flags;
|
||||
ClassType ctype = (ClassType) c.type;
|
||||
ctype.supertype_field = syms.objectType;
|
||||
@ -2677,7 +2679,8 @@ public class Lower extends TreeTranslator {
|
||||
}
|
||||
//where
|
||||
private JCTree convert(JCTree tree, Type pt) {
|
||||
if (tree.type == pt) return tree;
|
||||
if (tree.type == pt || tree.type.tag == TypeTags.BOT)
|
||||
return tree;
|
||||
JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree);
|
||||
result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt)
|
||||
: pt;
|
||||
|
||||
@ -67,6 +67,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
private final Check chk;
|
||||
private final Attr attr;
|
||||
private final Symtab syms;
|
||||
private final Scope.ScopeCounter scopeCounter;
|
||||
private final TreeMaker make;
|
||||
private final ClassReader reader;
|
||||
private final Todo todo;
|
||||
@ -92,6 +93,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
chk = Check.instance(context);
|
||||
attr = Attr.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
todo = Todo.instance(context);
|
||||
@ -100,7 +102,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
diags = JCDiagnostic.Factory.instance(context);
|
||||
target = Target.instance(context);
|
||||
Options options = Options.instance(context);
|
||||
skipAnnotations = options.get("skipAnnotations") != null;
|
||||
skipAnnotations = options.isSet("skipAnnotations");
|
||||
}
|
||||
|
||||
/** A queue for classes whose members still need to be entered into the
|
||||
@ -925,7 +927,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
tp.accept(new TypeAnnotate(baseEnv));
|
||||
tree.accept(new TypeAnnotate(env));
|
||||
|
||||
chk.checkNonCyclic(tree.pos(), c.type);
|
||||
chk.checkNonCyclicDecl(tree);
|
||||
|
||||
attr.attribTypeVariables(tree.typarams, baseEnv);
|
||||
|
||||
@ -1087,7 +1089,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
|
||||
|
||||
private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
|
||||
Scope baseScope = new Scope(tree.sym);
|
||||
Scope baseScope = new Scope.ClassScope(tree.sym, scopeCounter);
|
||||
//import already entered local classes into base scope
|
||||
for (Scope.Entry e = env.outer.info.scope.elems ; e != null ; e = e.sibling) {
|
||||
if (e.sym.isLocal()) {
|
||||
|
||||
@ -110,15 +110,17 @@ public class Resolve {
|
||||
boxingEnabled = source.allowBoxing();
|
||||
varargsEnabled = source.allowVarargs();
|
||||
Options options = Options.instance(context);
|
||||
debugResolve = options.get("debugresolve") != null;
|
||||
allowTransitionalJSR292 = options.get("allowTransitionalJSR292") != null;
|
||||
debugResolve = options.isSet("debugresolve");
|
||||
allowTransitionalJSR292 = options.isSet("allowTransitionalJSR292");
|
||||
Target target = Target.instance(context);
|
||||
allowMethodHandles = allowTransitionalJSR292 ||
|
||||
target.hasMethodHandles();
|
||||
allowInvokeDynamic = (allowTransitionalJSR292 ||
|
||||
target.hasInvokedynamic()) &&
|
||||
options.get("invokedynamic") != null;
|
||||
options.isSet("invokedynamic");
|
||||
polymorphicSignatureScope = new Scope(syms.noSymbol);
|
||||
|
||||
inapplicableMethodException = new InapplicableMethodException(diags);
|
||||
}
|
||||
|
||||
/** error symbols, which are returned when resolution fails
|
||||
@ -318,7 +320,8 @@ public class Resolve {
|
||||
throws Infer.InferenceException {
|
||||
boolean polymorphicSignature = (m.isPolymorphicSignatureGeneric() && allowMethodHandles) ||
|
||||
isTransitionalDynamicCallSite(site, m);
|
||||
if (useVarargs && (m.flags() & VARARGS) == 0) return null;
|
||||
if (useVarargs && (m.flags() & VARARGS) == 0)
|
||||
throw inapplicableMethodException.setMessage(null);
|
||||
Type mt = types.memberType(site, m);
|
||||
|
||||
// tvars is the list of formal type variables for which type arguments
|
||||
@ -334,7 +337,7 @@ public class Resolve {
|
||||
} else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
|
||||
ForAll pmt = (ForAll) mt;
|
||||
if (typeargtypes.length() != pmt.tvars.length())
|
||||
return null;
|
||||
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
|
||||
// Check type arguments are within bounds
|
||||
List<Type> formals = pmt.tvars;
|
||||
List<Type> actuals = typeargtypes;
|
||||
@ -343,7 +346,7 @@ public class Resolve {
|
||||
pmt.tvars, typeargtypes);
|
||||
for (; bounds.nonEmpty(); bounds = bounds.tail)
|
||||
if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
|
||||
return null;
|
||||
throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
|
||||
formals = formals.tail;
|
||||
actuals = actuals.tail;
|
||||
}
|
||||
@ -375,11 +378,10 @@ public class Resolve {
|
||||
allowBoxing,
|
||||
useVarargs,
|
||||
warn);
|
||||
return
|
||||
argumentsAcceptable(argtypes, mt.getParameterTypes(),
|
||||
allowBoxing, useVarargs, warn)
|
||||
? mt
|
||||
: null;
|
||||
|
||||
checkRawArgumentsAcceptable(argtypes, mt.getParameterTypes(),
|
||||
allowBoxing, useVarargs, warn);
|
||||
return mt;
|
||||
}
|
||||
|
||||
boolean isTransitionalDynamicCallSite(Type site, Symbol sym) {
|
||||
@ -403,7 +405,7 @@ public class Resolve {
|
||||
try {
|
||||
return rawInstantiate(env, site, m, argtypes, typeargtypes,
|
||||
allowBoxing, useVarargs, warn);
|
||||
} catch (Infer.InferenceException ex) {
|
||||
} catch (InapplicableMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -415,26 +417,76 @@ public class Resolve {
|
||||
boolean allowBoxing,
|
||||
boolean useVarargs,
|
||||
Warner warn) {
|
||||
try {
|
||||
checkRawArgumentsAcceptable(argtypes, formals, allowBoxing, useVarargs, warn);
|
||||
return true;
|
||||
} catch (InapplicableMethodException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void checkRawArgumentsAcceptable(List<Type> argtypes,
|
||||
List<Type> formals,
|
||||
boolean allowBoxing,
|
||||
boolean useVarargs,
|
||||
Warner warn) {
|
||||
Type varargsFormal = useVarargs ? formals.last() : null;
|
||||
if (varargsFormal == null &&
|
||||
argtypes.size() != formals.size()) {
|
||||
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
|
||||
}
|
||||
|
||||
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
|
||||
boolean works = allowBoxing
|
||||
? types.isConvertible(argtypes.head, formals.head, warn)
|
||||
: types.isSubtypeUnchecked(argtypes.head, formals.head, warn);
|
||||
if (!works) return false;
|
||||
if (!works)
|
||||
throw inapplicableMethodException.setMessage("no.conforming.assignment.exists",
|
||||
argtypes.head,
|
||||
formals.head);
|
||||
argtypes = argtypes.tail;
|
||||
formals = formals.tail;
|
||||
}
|
||||
if (formals.head != varargsFormal) return false; // not enough args
|
||||
if (!useVarargs)
|
||||
return argtypes.isEmpty();
|
||||
Type elt = types.elemtype(varargsFormal);
|
||||
while (argtypes.nonEmpty()) {
|
||||
if (!types.isConvertible(argtypes.head, elt, warn))
|
||||
return false;
|
||||
argtypes = argtypes.tail;
|
||||
|
||||
if (formals.head != varargsFormal)
|
||||
throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
|
||||
|
||||
if (useVarargs) {
|
||||
Type elt = types.elemtype(varargsFormal);
|
||||
while (argtypes.nonEmpty()) {
|
||||
if (!types.isConvertible(argtypes.head, elt, warn))
|
||||
throw inapplicableMethodException.setMessage("varargs.argument.mismatch",
|
||||
argtypes.head,
|
||||
elt);
|
||||
argtypes = argtypes.tail;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
// where
|
||||
public static class InapplicableMethodException extends RuntimeException {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
JCDiagnostic diagnostic;
|
||||
JCDiagnostic.Factory diags;
|
||||
|
||||
InapplicableMethodException(JCDiagnostic.Factory diags) {
|
||||
this.diagnostic = null;
|
||||
this.diags = diags;
|
||||
}
|
||||
InapplicableMethodException setMessage(String key) {
|
||||
this.diagnostic = key != null ? diags.fragment(key) : null;
|
||||
return this;
|
||||
}
|
||||
InapplicableMethodException setMessage(String key, Object... args) {
|
||||
this.diagnostic = key != null ? diags.fragment(key, args) : null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JCDiagnostic getDiagnostic() {
|
||||
return diagnostic;
|
||||
}
|
||||
}
|
||||
private final InapplicableMethodException inapplicableMethodException;
|
||||
|
||||
/* ***************************************************************************
|
||||
* Symbol lookup
|
||||
@ -595,6 +647,7 @@ public class Resolve {
|
||||
* @param allowBoxing Allow boxing conversions of arguments.
|
||||
* @param useVarargs Box trailing arguments into an array for varargs.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
Symbol selectBest(Env<AttrContext> env,
|
||||
Type site,
|
||||
List<Type> argtypes,
|
||||
@ -608,21 +661,16 @@ public class Resolve {
|
||||
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
|
||||
assert sym.kind < AMBIGUOUS;
|
||||
try {
|
||||
if (rawInstantiate(env, site, sym, argtypes, typeargtypes,
|
||||
allowBoxing, useVarargs, Warner.noWarnings) == null) {
|
||||
// inapplicable
|
||||
switch (bestSoFar.kind) {
|
||||
case ABSENT_MTH: return wrongMethod.setWrongSym(sym);
|
||||
case WRONG_MTH: return wrongMethods;
|
||||
default: return bestSoFar;
|
||||
}
|
||||
}
|
||||
} catch (Infer.InferenceException ex) {
|
||||
rawInstantiate(env, site, sym, argtypes, typeargtypes,
|
||||
allowBoxing, useVarargs, Warner.noWarnings);
|
||||
} catch (InapplicableMethodException ex) {
|
||||
switch (bestSoFar.kind) {
|
||||
case ABSENT_MTH:
|
||||
return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
|
||||
case WRONG_MTH:
|
||||
return wrongMethods;
|
||||
wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
|
||||
case WRONG_MTHS:
|
||||
return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
|
||||
default:
|
||||
return bestSoFar;
|
||||
}
|
||||
@ -631,7 +679,7 @@ public class Resolve {
|
||||
return (bestSoFar.kind == ABSENT_MTH)
|
||||
? new AccessError(env, site, sym)
|
||||
: bestSoFar;
|
||||
}
|
||||
}
|
||||
return (bestSoFar.kind > AMBIGUOUS)
|
||||
? sym
|
||||
: mostSpecific(sym, bestSoFar, env, site,
|
||||
@ -1253,11 +1301,12 @@ public class Resolve {
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
Symbol sym = methodNotFound;
|
||||
Symbol sym = startResolution();
|
||||
List<MethodResolutionPhase> steps = methodResolutionSteps;
|
||||
while (steps.nonEmpty() &&
|
||||
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
|
||||
sym.kind >= ERRONEOUS) {
|
||||
currentStep = steps.head;
|
||||
sym = findFun(env, name, argtypes, typeargtypes,
|
||||
steps.head.isBoxingRequired,
|
||||
env.info.varArgs = steps.head.isVarargsRequired);
|
||||
@ -1274,6 +1323,12 @@ public class Resolve {
|
||||
return sym;
|
||||
}
|
||||
|
||||
private Symbol startResolution() {
|
||||
wrongMethod.clear();
|
||||
wrongMethods.clear();
|
||||
return methodNotFound;
|
||||
}
|
||||
|
||||
/** Resolve a qualified method identifier
|
||||
* @param pos The position to use for error reporting.
|
||||
* @param env The environment current at the method invocation.
|
||||
@ -1286,11 +1341,12 @@ public class Resolve {
|
||||
Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
|
||||
Type site, Name name, List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
Symbol sym = methodNotFound;
|
||||
Symbol sym = startResolution();
|
||||
List<MethodResolutionPhase> steps = methodResolutionSteps;
|
||||
while (steps.nonEmpty() &&
|
||||
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
|
||||
sym.kind >= ERRONEOUS) {
|
||||
currentStep = steps.head;
|
||||
sym = findMethod(env, site, name, argtypes, typeargtypes,
|
||||
steps.head.isBoxingRequired(),
|
||||
env.info.varArgs = steps.head.isVarargsRequired(), false);
|
||||
@ -1404,11 +1460,12 @@ public class Resolve {
|
||||
Type site,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
Symbol sym = methodNotFound;
|
||||
Symbol sym = startResolution();
|
||||
List<MethodResolutionPhase> steps = methodResolutionSteps;
|
||||
while (steps.nonEmpty() &&
|
||||
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
|
||||
sym.kind >= ERRONEOUS) {
|
||||
currentStep = steps.head;
|
||||
sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
|
||||
steps.head.isBoxingRequired(),
|
||||
env.info.varArgs = steps.head.isVarargsRequired());
|
||||
@ -1439,26 +1496,22 @@ public class Resolve {
|
||||
Type site,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
Symbol sym = methodNotFound;
|
||||
JCDiagnostic explanation = null;
|
||||
Symbol sym = startResolution();
|
||||
List<MethodResolutionPhase> steps = methodResolutionSteps;
|
||||
while (steps.nonEmpty() &&
|
||||
steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
|
||||
sym.kind >= ERRONEOUS) {
|
||||
currentStep = steps.head;
|
||||
sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
|
||||
steps.head.isBoxingRequired(),
|
||||
env.info.varArgs = steps.head.isVarargsRequired());
|
||||
methodResolutionCache.put(steps.head, sym);
|
||||
if (sym.kind == WRONG_MTH &&
|
||||
((InapplicableSymbolError)sym).explanation != null) {
|
||||
//if the symbol is an inapplicable method symbol, then the
|
||||
//explanation contains the reason for which inference failed
|
||||
explanation = ((InapplicableSymbolError)sym).explanation;
|
||||
}
|
||||
steps = steps.tail;
|
||||
}
|
||||
if (sym.kind >= AMBIGUOUS) {
|
||||
final JCDiagnostic details = explanation;
|
||||
final JCDiagnostic details = sym.kind == WRONG_MTH ?
|
||||
((InapplicableSymbolError)sym).explanation :
|
||||
null;
|
||||
Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
|
||||
@ -1860,7 +1913,8 @@ public class Resolve {
|
||||
*/
|
||||
InapplicableSymbolError setWrongSym(Symbol sym, JCDiagnostic explanation) {
|
||||
this.sym = sym;
|
||||
this.explanation = explanation;
|
||||
if (this.sym == sym && explanation != null)
|
||||
this.explanation = explanation; //update the details
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1868,7 +1922,6 @@ public class Resolve {
|
||||
*/
|
||||
InapplicableSymbolError setWrongSym(Symbol sym) {
|
||||
this.sym = sym;
|
||||
this.explanation = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1905,6 +1958,10 @@ public class Resolve {
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
explanation = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol access(Name name, TypeSymbol location) {
|
||||
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
|
||||
@ -1917,6 +1974,9 @@ public class Resolve {
|
||||
* given an actual arguments/type argument list.
|
||||
*/
|
||||
class InapplicableSymbolsError extends ResolveError {
|
||||
|
||||
private List<Candidate> candidates = List.nil();
|
||||
|
||||
InapplicableSymbolsError(Symbol sym) {
|
||||
super(WRONG_MTHS, "inapplicable symbols");
|
||||
}
|
||||
@ -1928,8 +1988,85 @@ public class Resolve {
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
|
||||
if (candidates.nonEmpty()) {
|
||||
JCDiagnostic err = diags.create(dkind,
|
||||
log.currentSource(),
|
||||
pos,
|
||||
"cant.apply.symbols",
|
||||
name == names.init ? KindName.CONSTRUCTOR : absentKind(kind),
|
||||
getName(),
|
||||
argtypes);
|
||||
return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(site));
|
||||
} else {
|
||||
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
|
||||
site, name, argtypes, typeargtypes);
|
||||
}
|
||||
}
|
||||
|
||||
//where
|
||||
List<JCDiagnostic> candidateDetails(Type site) {
|
||||
List<JCDiagnostic> details = List.nil();
|
||||
for (Candidate c : candidates)
|
||||
details = details.prepend(c.getDiagnostic(site));
|
||||
return details.reverse();
|
||||
}
|
||||
|
||||
Symbol addCandidate(MethodResolutionPhase currentStep, Symbol sym, JCDiagnostic details) {
|
||||
Candidate c = new Candidate(currentStep, sym, details);
|
||||
if (c.isValid() && !candidates.contains(c))
|
||||
candidates = candidates.append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
candidates = List.nil();
|
||||
}
|
||||
|
||||
private Name getName() {
|
||||
Symbol sym = candidates.head.sym;
|
||||
return sym.name == names.init ?
|
||||
sym.owner.name :
|
||||
sym.name;
|
||||
}
|
||||
|
||||
private class Candidate {
|
||||
|
||||
final MethodResolutionPhase step;
|
||||
final Symbol sym;
|
||||
final JCDiagnostic details;
|
||||
|
||||
private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details) {
|
||||
this.step = step;
|
||||
this.sym = sym;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
JCDiagnostic getDiagnostic(Type site) {
|
||||
return diags.fragment("inapplicable.method",
|
||||
Kinds.kindName(sym),
|
||||
sym.location(site, types),
|
||||
sym.asMemberOf(site, types),
|
||||
details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Candidate) {
|
||||
Symbol s1 = this.sym;
|
||||
Symbol s2 = ((Candidate)o).sym;
|
||||
if ((s1 != s2 &&
|
||||
(s1.overrides(s2, s1.owner.type.tsym, types, false) ||
|
||||
(s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
|
||||
((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isValid() {
|
||||
return (((sym.flags() & VARARGS) != 0 && step == VARARITY) ||
|
||||
(sym.flags() & VARARGS) == 0 && step == (boxingEnabled ? BOX : BASIC));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2093,6 +2230,8 @@ public class Resolve {
|
||||
|
||||
final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
|
||||
|
||||
private MethodResolutionPhase currentStep = null;
|
||||
|
||||
private MethodResolutionPhase firstErroneousResolutionPhase() {
|
||||
MethodResolutionPhase bestSoFar = BASIC;
|
||||
Symbol sym = methodNotFound;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -150,8 +150,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
|
||||
useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
|
||||
|
||||
mmappedIO = options.get("mmappedIO") != null;
|
||||
ignoreSymbolFile = options.get("ignore.symbol.file") != null;
|
||||
mmappedIO = options.isSet("mmappedIO");
|
||||
ignoreSymbolFile = options.isSet("ignore.symbol.file");
|
||||
}
|
||||
|
||||
public JavaFileObject getFileForInput(String name) {
|
||||
@ -435,7 +435,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
zdir = new ZipFile(zipFileName);
|
||||
}
|
||||
else {
|
||||
usePreindexedCache = options.get("usezipindex") != null;
|
||||
usePreindexedCache = options.isSet("usezipindex");
|
||||
preindexCacheLocation = options.get("java.io.tmpdir");
|
||||
String optCacheLoc = options.get("cachezipindexdir");
|
||||
|
||||
@ -469,7 +469,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
null,
|
||||
usePreindexedCache,
|
||||
preindexCacheLocation,
|
||||
options.get("writezipindexfiles") != null));
|
||||
options.isSet("writezipindexfiles")));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -482,7 +482,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
symbolFilePrefix,
|
||||
usePreindexedCache,
|
||||
preindexCacheLocation,
|
||||
options.get("writezipindexfiles") != null));
|
||||
options.isSet("writezipindexfiles")));
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
@ -605,7 +605,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
nullCheck(className);
|
||||
nullCheck(kind);
|
||||
if (!sourceOrClass.contains(kind))
|
||||
throw new IllegalArgumentException("Invalid kind " + kind);
|
||||
throw new IllegalArgumentException("Invalid kind: " + kind);
|
||||
return getFileForInput(location, RelativeFile.forClass(className, kind));
|
||||
}
|
||||
|
||||
@ -658,7 +658,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
nullCheck(className);
|
||||
nullCheck(kind);
|
||||
if (!sourceOrClass.contains(kind))
|
||||
throw new IllegalArgumentException("Invalid kind " + kind);
|
||||
throw new IllegalArgumentException("Invalid kind: " + kind);
|
||||
return getFileForOutput(location, RelativeFile.forClass(className, kind), sibling);
|
||||
}
|
||||
|
||||
@ -672,7 +672,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
// validatePackageName(packageName);
|
||||
nullCheck(packageName);
|
||||
if (!isRelativeUri(relativeName))
|
||||
throw new IllegalArgumentException("relativeName is invalid");
|
||||
throw new IllegalArgumentException("Invalid relative name: " + relativeName);
|
||||
RelativeFile name = packageName.length() == 0
|
||||
? new RelativeFile(relativeName)
|
||||
: new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
|
||||
@ -806,6 +806,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
String path = uri.normalize().getPath();
|
||||
if (path.length() == 0 /* isEmpty() is mustang API */)
|
||||
return false;
|
||||
if (!path.equals(uri.getPath())) // implicitly checks for embedded . and ..
|
||||
return false;
|
||||
char first = path.charAt(0);
|
||||
return first != '.' && first != '/';
|
||||
}
|
||||
|
||||
@ -56,6 +56,8 @@ import static com.sun.tools.javac.code.TypeTags.*;
|
||||
import static com.sun.tools.javac.jvm.ClassFile.*;
|
||||
import static com.sun.tools.javac.jvm.ClassFile.Version.*;
|
||||
|
||||
import static com.sun.tools.javac.main.OptionName.*;
|
||||
|
||||
/** This class provides operations to read a classfile into an internal
|
||||
* representation. The internal representation is anchored in a
|
||||
* ClassSymbol which contains in its scope symbol representations
|
||||
@ -122,6 +124,9 @@ public class ClassReader implements Completer {
|
||||
/** The symbol table. */
|
||||
Symtab syms;
|
||||
|
||||
/** The scope counter */
|
||||
Scope.ScopeCounter scopeCounter;
|
||||
|
||||
Types types;
|
||||
|
||||
/** The name table. */
|
||||
@ -244,6 +249,7 @@ public class ClassReader implements Completer {
|
||||
|
||||
names = Names.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
scopeCounter = Scope.ScopeCounter.instance(context);
|
||||
types = Types.instance(context);
|
||||
fileManager = context.get(JavaFileManager.class);
|
||||
if (fileManager == null)
|
||||
@ -255,23 +261,23 @@ public class ClassReader implements Completer {
|
||||
|
||||
Options options = Options.instance(context);
|
||||
annotate = Annotate.instance(context);
|
||||
verbose = options.get("-verbose") != null;
|
||||
checkClassFile = options.get("-checkclassfile") != null;
|
||||
verbose = options.isSet(VERBOSE);
|
||||
checkClassFile = options.isSet("-checkclassfile");
|
||||
Source source = Source.instance(context);
|
||||
allowGenerics = source.allowGenerics();
|
||||
allowVarargs = source.allowVarargs();
|
||||
allowAnnotations = source.allowAnnotations();
|
||||
saveParameterNames = options.get("save-parameter-names") != null;
|
||||
cacheCompletionFailure = options.get("dev") == null;
|
||||
saveParameterNames = options.isSet("save-parameter-names");
|
||||
cacheCompletionFailure = options.isUnset("dev");
|
||||
preferSource = "source".equals(options.get("-Xprefer"));
|
||||
|
||||
completionFailureName =
|
||||
(options.get("failcomplete") != null)
|
||||
options.isSet("failcomplete")
|
||||
? names.fromString(options.get("failcomplete"))
|
||||
: null;
|
||||
|
||||
typevars = new Scope(syms.noSymbol);
|
||||
debugJSR308 = options.get("TA:reader") != null;
|
||||
debugJSR308 = options.isSet("TA:reader");
|
||||
|
||||
initAttributeReaders();
|
||||
}
|
||||
@ -1984,7 +1990,7 @@ public class ClassReader implements Completer {
|
||||
ClassType ct = (ClassType)c.type;
|
||||
|
||||
// allocate scope for members
|
||||
c.members_field = new Scope(c);
|
||||
c.members_field = new Scope.ClassScope(c, scopeCounter);
|
||||
|
||||
// prepare type variable table
|
||||
typevars = typevars.dup(currentOwner);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user