This commit is contained in:
Lana Steuck 2010-10-13 17:51:41 -07:00
commit 0ffa1c4042
237 changed files with 11008 additions and 1648 deletions

View File

@ -86,3 +86,5 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99
e02b4d709e177d08d56130a4bc68061e4bbacc7d jdk7-b109
a6442d6bc38a44152e0662688213ce4d2701f42a jdk7-b110
69f3edf083477955b5bd2f754252c7504167d8e1 jdk7-b111
f960f117f1623629f64203e2b09a92a8f6f14ff5 jdk7-b112
1fee41c7ed2b3388970a756a85aa693c0de8407a jdk7-b113

View File

@ -86,3 +86,5 @@ f8be576feefce0c6695f188ef97ec16b73ad9cfd jdk7-b104
81dfc728d7bb7e1fff4a4dc6d0f7cea5a3315667 jdk7-b109
2a02d4a6955c7c078aee9a604cb3be409800d82c jdk7-b110
9702d6fef68e17533ee7fcf5923b11ead3e912ce jdk7-b111
b852103caf73da70068473777ae867a457bb3ae1 jdk7-b112
c1df968c4527bfab5f97662a89245f15d12d378b jdk7-b113

View File

@ -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 \

View File

@ -86,3 +86,5 @@ a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
c3dd858e09b20206459d9e7b0ead99d27ab00eab jdk7-b109
0e1f80fda2271f53d4bbb59ec3f301dfbcef6a0a jdk7-b110
640fa4d4e2ad4c2d7e4815c955026740d8c52b7a jdk7-b111
cc67fdc4fee9a5b25caee4e71b51a8ff24ae7d1a jdk7-b112
a89a6c5be9d1a754868d3d359cbf7ad36aa95631 jdk7-b113

View File

@ -121,3 +121,5 @@ e44a93947ccbfce712b51725f313163606f15486 jdk7-b108
cc4bb3022b3144dc5db0805b9ef6c7eff2aa3b81 jdk7-b109
2f25f2b8de2700a1822463b1bd3d02b5e218018f jdk7-b110
07b042e13dde4f3479ba9ec55120fcd5e8623323 jdk7-b111
5511edd5d719f3fc9fdd04879482026a3d2c8652 jdk7-b112
beef35b96b81129c375d572357fb9548d9020db1 jdk7-b113

View File

@ -86,3 +86,5 @@ d42c4acb6424a094bdafe2ad9c8c1c7ca7fb7b7e jdk7-b104
0f382d6120fc07aed2209484a42458cabf405916 jdk7-b109
d422dbdd09766269344b796b3a46a5b3f74557e1 jdk7-b110
8106c747067c905d814a737a57fea0e29057b33f jdk7-b111
1b05254242881527b4d5d711295c0fe708c8823a jdk7-b112
bc0c84ce54c34d3e8b0604b94da0d7c75c26755e jdk7-b113

View File

@ -86,3 +86,5 @@ b1ca39340238a239ba6d8489ad5315215e1366ca jdk7-b108
4f626e0d70bda68c76bbd0e89d2bc2407f979736 jdk7-b109
95ecac35fb11530752bd0404c9bf02bcfb30990e jdk7-b110
2575ebca96c7fb1b78f6ae025a97321210aba309 jdk7-b111
8e0f0054817f0f73fb33e80fb1333fb45b1d513d jdk7-b112
d35c94fd22362f478f75b4bfcd2bef6a83cb9b3f jdk7-b113

View File

@ -86,3 +86,5 @@ b91ef6b60f4e19bf4592c6dd594c9bac62487519 jdk7-b106
ab0d3f54a63f2aadfcdd2e14b81f79362ce454e2 jdk7-b109
176586cd040e4dd17a5ff6e91f72df10d7442453 jdk7-b110
fb63a2688db807a73e2a3de7d9bab298f1bff0e8 jdk7-b111
b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113

View File

@ -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

View 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)

View 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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}
);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
/**

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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
*/

View File

@ -1464,8 +1464,8 @@ public class GroupLayout implements LayoutManager2 {
* &lt;= {@code pref} &lt;= {@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

View File

@ -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);
}

View File

@ -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
*

View File

@ -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) {
}
}
}

View File

@ -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

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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) {

View File

@ -115,6 +115,9 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI
return new SynthTabbedPaneUI();
}
private SynthTabbedPaneUI() {
}
private boolean scrollableTabLayoutEnabled() {
return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
}

View File

@ -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);
}
/*

View File

@ -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

View File

@ -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);

View 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();
}
}
}

View File

@ -0,0 +1,3 @@
com.sun.nio.zipfs.ZipFileSystemProvider
com.sun.nio.zipfs.JarFileSystemProvider

View 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();

View File

@ -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
}
}
}

View 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;
}
}

View 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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View 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();
}
};
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}
}

View 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");
}
}

View 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;
}
}
}
}

View 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();
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
}
}
}

View File

@ -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();
}

View File

@ -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);
}
/*

View File

@ -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;

View File

@ -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) {}

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View 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;
}
}
}

View 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();
}
}

View 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;
}
}

View 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

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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++){

View 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;
}
}

View 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");
}
}
}
}

View 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;
}
}

View 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);
}
}

View 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();
}
}
}

View File

@ -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());
}
}
}

View File

@ -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");

View File

@ -86,3 +86,5 @@ a408ebb8b3d427dbb3d8ce153dfaeb060564a0a4 jdk7-b108
4826378eaade4c6676c452efe954be4ee113cc11 jdk7-b109
32da0f38d2fe96c558492b8707b40da24643d41e jdk7-b110
8bec624274ef8535720cff553374347c2f4f5fb2 jdk7-b111
fd2579b80b83bf5d4289426016c7d29174ba5dd9 jdk7-b112
6dbd2d869b0573fa5b799a23cccff47d20c12696 jdk7-b113

View File

@ -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>

View File

@ -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);

View File

@ -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();
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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>

View File

@ -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

View File

@ -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.
*

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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()) {

View File

@ -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;

View File

@ -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 != '/';
}

View File

@ -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