--- a/jdk/make/CompileDemos.gmk Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/CompileDemos.gmk Wed Apr 16 10:53:10 2014 -0700
@@ -176,7 +176,6 @@
$(eval $(call SetupDemo,JTop,management,,JTop,,,README*))
$(eval $(call SetupDemo,MemoryMonitor,management,,MemoryMonitor,,,README*))
$(eval $(call SetupDemo,VerboseGC,management,,VerboseGC,,,README*))
-$(eval $(call SetupDemo,zipfs,nio,,,,,README* *.java,,,,Main-Class: \n))
ifndef OPENJDK
$(eval $(call SetupDemo,Laffy,jfc,,,,closed/,*))
--- a/jdk/make/CopyFiles.gmk Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/CopyFiles.gmk Wed Apr 16 10:53:10 2014 -0700
@@ -158,15 +158,6 @@
##########################################################################################
-CONTENT_TYPES_SRC = $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib
-
-$(LIBDIR)/content-types.properties: $(CONTENT_TYPES_SRC)/content-types.properties
- $(call install-file)
-
-COPY_FILES += $(LIBDIR)/content-types.properties
-
-##########################################################################################
-
CALENDARS_SRC := $(JDK_TOPDIR)/src/share/lib
$(LIBDIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties
--- a/jdk/make/CopyIntoClasses.gmk Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/CopyIntoClasses.gmk Wed Apr 16 10:53:10 2014 -0700
@@ -26,7 +26,7 @@
# Copy icu and _dict files used by the text break iterator
COPY_PATTERNS := .icu _dict .dat _options .js aliasmap .spp .wav .css \
- .png .gif .xml .dtd .txt oqlhelp.html
+ .png .gif .xml .dtd .txt oqlhelp.html content-types.properties
# These directories should not be copied at all
EXCLUDES += \
--- a/jdk/make/CreateJars.gmk Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/CreateJars.gmk Wed Apr 16 10:53:10 2014 -0700
@@ -160,11 +160,13 @@
javax/swing/JWindowBeanInfo.class \
javax/swing/SwingBeanInfoBase.class \
javax/swing/text/JTextComponentBeanInfo.class \
+ jdk/nio/zipfs \
META-INF/services/com.sun.jdi.connect.Connector \
META-INF/services/com.sun.jdi.connect.spi.TransportService \
META-INF/services/com.sun.tools.attach.spi.AttachProvider \
META-INF/services/com.sun.tools.xjc.Plugin \
META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \
+ META-INF/services/java.nio.file.spi.FileSystemProvider \
org/relaxng/datatype \
sun/awt/HKSCS.class \
sun/awt/motif/X11GB2312.class \
@@ -356,6 +358,16 @@
##########################################################################################
+$(eval $(call SetupArchive,BUILD_ZIPFS_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes, \
+ INCLUDES := jdk/nio/zipfs, \
+ EXTRA_FILES := META-INF/services/java.nio.file.spi.FileSystemProvider, \
+ JAR := $(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar, \
+ SKIP_METAINF := true, \
+ CHECK_COMPRESS_JAR := true))
+
+##########################################################################################
+
ifndef OPENJDK
ifeq ($(ENABLE_JFR), true)
$(eval $(call SetupArchive,BUILD_JFR_JAR, , \
@@ -660,11 +672,6 @@
##########################################################################################
-$(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar: $(JDK_OUTPUTDIR)/demo/nio/zipfs/zipfs.jar
- $(install-file)
-
-##########################################################################################
-
# This file is imported from hotspot in Import.gmk. Copying it into images/lib so that
# all jars can be found in one place when creating images in Images.gmk. It needs to be
# done here so that clean targets can be simple and accurate.
--- a/jdk/make/data/jdwp/jdwp.spec Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/data/jdwp/jdwp.spec Wed Apr 16 10:53:10 2014 -0700
@@ -1079,7 +1079,7 @@
(Command InvokeMethod=3
"Invokes a static method. "
"The method must be member of the class type "
- "or one of its superclasses, superinterfaces, or implemented interfaces. "
+ "or one of its superclasses. "
"Access control is not enforced; for example, private "
"methods can be invoked."
"<p>"
--- a/jdk/make/profile-includes.txt Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/make/profile-includes.txt Wed Apr 16 10:53:10 2014 -0700
@@ -56,7 +56,6 @@
$(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/Xusage.txt \
calendars.properties \
classlist \
- content-types.properties \
currency.data \
ext/localedata.jar \
ext/meta-index \
--- a/jdk/src/macosx/classes/sun/font/CFontManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/classes/sun/font/CFontManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -27,6 +27,8 @@
import java.awt.*;
import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
@@ -38,6 +40,7 @@
import sun.awt.FontConfiguration;
import sun.awt.HeadlessToolkit;
+import sun.misc.ThreadGroupUtils;
import sun.lwawt.macosx.*;
public class CFontManager extends SunFontManager {
@@ -215,24 +218,19 @@
});
}
};
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Object>() {
- public Object run() {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup tg =
- Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- fileCloser = new Thread(tg, fileCloserRunnable);
- fileCloser.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(fileCloser);
- return null;
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ fileCloser = new Thread(rootTG, fileCloserRunnable);
+ fileCloser.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(fileCloser);
+ return null;
+ }
+ );
}
}
}
--- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Apr 16 10:53:10 2014 -0700
@@ -35,6 +35,7 @@
import sun.awt.*;
import sun.print.*;
+import sun.misc.ThreadGroupUtils;
import static sun.lwawt.LWWindowPeer.PeerType;
@@ -70,30 +71,17 @@
protected final void init() {
AWTAutoShutdown.notifyToolkitThreadBusy();
- ThreadGroup mainTG = AccessController.doPrivileged(
- new PrivilegedAction<ThreadGroup>() {
- public ThreadGroup run() {
- ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = currentTG.getParent();
- while (parentTG != null) {
- currentTG = parentTG;
- parentTG = currentTG.getParent();
- }
- return currentTG;
- }
- }
- );
+ ThreadGroup rootTG = AccessController.doPrivileged(
+ (PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);
Runtime.getRuntime().addShutdownHook(
- new Thread(mainTG, new Runnable() {
- public void run() {
- shutdown();
- waitForRunState(STATE_CLEANUP);
- }
+ new Thread(rootTG, () -> {
+ shutdown();
+ waitForRunState(STATE_CLEANUP);
})
);
- Thread toolkitThread = new Thread(mainTG, this, "AWT-LW");
+ Thread toolkitThread = new Thread(rootTG, this, "AWT-LW");
toolkitThread.setDaemon(true);
toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
toolkitThread.start();
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java Wed Apr 16 10:53:10 2014 -0700
@@ -58,7 +58,7 @@
@Override
protected void setContentsNative(Transferable contents) {
-
+ FlavorTable flavorMap = getDefaultFlavorTable();
// Don't use delayed Clipboard rendering for the Transferable's data.
// If we did that, we would call Transferable.getTransferData on
// the Toolkit thread, which is a security hole.
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Apr 16 10:53:10 2014 -0700
@@ -483,8 +483,12 @@
private static final String APPKIT_THREAD_NAME = "AppKit Thread";
// Intended to be called from the LWCToolkit.m only.
- private static void installToolkitThreadNameInJava() {
+ private static void installToolkitThreadInJava() {
Thread.currentThread().setName(APPKIT_THREAD_NAME);
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ Thread.currentThread().setContextClassLoader(null);
+ return null;
+ });
}
@Override
--- a/jdk/src/macosx/lib/content-types.properties Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-# <description> ::= 'description' '=' <descriptive string>
-# <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-# <image> ::= 'icon' '=' <filename of icon image>
-# <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-# <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: /tmp/%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
- description=Generic Binary Stream;\
- file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
-
-application/oda: \
- description=ODA Document;\
- file_extensions=.oda
-
-application/pdf: \
- description=Adobe PDF Format;\
- file_extensions=.pdf
-
-application/postscript: \
- description=Postscript File;\
- file_extensions=.eps,.ai,.ps;\
- icon=ps;\
- action=application;\
- application=imagetool %s
-
-application/x-dvi: \
- description=TeX DVI File;\
- file_extensions=.dvi;\
- action=application;\
- application=xdvi %s
-
-application/x-hdf: \
- description=Hierarchical Data Format;\
- file_extensions=.hdf;\
- action=save
-
-application/x-latex: \
- description=LaTeX Source;\
- file_extensions=.latex
-
-application/x-netcdf: \
- description=Unidata netCDF Data Format;\
- file_extensions=.nc,.cdf;\
- action=save
-
-application/x-tex: \
- description=TeX Source;\
- file_extensions=.tex
-
-application/x-texinfo: \
- description=Gnu Texinfo;\
- file_extensions=.texinfo,.texi
-
-application/x-troff: \
- description=Troff Source;\
- file_extensions=.t,.tr,.roff;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
-
-application/x-troff-man: \
- description=Troff Manpage Source;\
- file_extensions=.man;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
-
-application/x-troff-me: \
- description=Troff ME Macros;\
- file_extensions=.me;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
-
-application/x-troff-ms: \
- description=Troff MS Macros;\
- file_extensions=.ms;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
-
-application/x-wais-source: \
- description=Wais Source;\
- file_extensions=.src,.wsrc
-
-application/zip: \
- description=Zip File;\
- file_extensions=.zip;\
- icon=zip;\
- action=save
-
-application/x-bcpio: \
- description=Old Binary CPIO Archive;\
- file_extensions=.bcpio; action=save
-
-application/x-cpio: \
- description=Unix CPIO Archive;\
- file_extensions=.cpio; action=save
-
-application/x-gtar: \
- description=Gnu Tar Archive;\
- file_extensions=.gtar;\
- icon=tar;\
- action=save
-
-application/x-shar: \
- description=Shell Archive;\
- file_extensions=.sh,.shar;\
- action=save
-
-application/x-sv4cpio: \
- description=SVR4 CPIO Archive;\
- file_extensions=.sv4cpio; action=save
-
-application/x-sv4crc: \
- description=SVR4 CPIO with CRC;\
- file_extensions=.sv4crc; action=save
-
-application/x-tar: \
- description=Tar Archive;\
- file_extensions=.tar;\
- icon=tar;\
- action=save
-
-application/x-ustar: \
- description=US Tar Archive;\
- file_extensions=.ustar;\
- action=save
-
-audio/basic: \
- description=Basic Audio;\
- file_extensions=.snd,.au;\
- icon=audio;\
- action=application;\
- application=audiotool %s
-
-audio/x-aiff: \
- description=Audio Interchange Format File;\
- file_extensions=.aifc,.aif,.aiff;\
- icon=aiff
-
-audio/x-wav: \
- description=Wav Audio;\
- file_extensions=.wav;\
- icon=wav
-
-image/gif: \
- description=GIF Image;\
- file_extensions=.gif;\
- icon=gif;\
- action=browser
-
-image/ief: \
- description=Image Exchange Format;\
- file_extensions=.ief
-
-image/jpeg: \
- description=JPEG Image;\
- file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
- icon=jpeg;\
- action=browser;\
- application=imagetool %s
-
-image/tiff: \
- description=TIFF Image;\
- file_extensions=.tif,.tiff;\
- icon=tiff
-
-image/vnd.fpx: \
- description=FlashPix Image;\
- file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
- description=CMU Raster Image;\
- file_extensions=.ras
-
-image/x-portable-anymap: \
- description=PBM Anymap Format;\
- file_extensions=.pnm
-
-image/x-portable-bitmap: \
- description=PBM Bitmap Format;\
- file_extensions=.pbm
-
-image/x-portable-graymap: \
- description=PBM Graymap Format;\
- file_extensions=.pgm
-
-image/x-portable-pixmap: \
- description=PBM Pixmap Format;\
- file_extensions=.ppm
-
-image/x-rgb: \
- description=RGB Image;\
- file_extensions=.rgb
-
-image/x-xbitmap: \
- description=X Bitmap Image;\
- file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
- description=X Window Dump Image;\
- file_extensions=.xwd
-
-image/png: \
- description=PNG Image;\
- file_extensions=.png;\
- icon=png;\
- action=browser
-
-text/html: \
- description=HTML Document;\
- file_extensions=.htm,.html;\
- icon=html
-
-text/plain: \
- description=Plain Text;\
- file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
- icon=text;\
- action=browser
-
-text/tab-separated-values: \
- description=Tab Separated Values Text;\
- file_extensions=.tsv
-
-text/x-setext: \
- description=Structure Enhanced Text;\
- file_extensions=.etx
-
-video/mpeg: \
- description=MPEG Video Clip;\
- file_extensions=.mpg,.mpe,.mpeg;\
- icon=mpeg;\
- action=application;\
- application=mpeg_play %s
-
-video/quicktime: \
- description=QuickTime Video Clip;\
- file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
- description=AVI Video;\
- file_extensions=.avi;\
- icon=avi
-
-video/x-sgi-movie: \
- description=SGI Movie;\
- file_extensions=.movie,.mv
-
-message/rfc822: \
- description=Internet Email Message;\
- file_extensions=.mime
-
-application/xml: \
- description=XML document;\
- file_extensions=.xml
-
-
-
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Wed Apr 16 10:53:10 2014 -0700
@@ -233,15 +233,16 @@
Java_sun_lwawt_macosx_LWCToolkit_initIDs
(JNIEnv *env, jclass klass) {
// set thread names
- dispatch_async(dispatch_get_main_queue(), ^(void){
- [[NSThread currentThread] setName:@"AppKit Thread"];
-
- JNIEnv *env = [ThreadUtilities getJNIEnv];
- static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
- static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadNameInJava, jc_LWCToolkit, "installToolkitThreadNameInJava", "()V");
- JNFCallStaticVoidMethod(env, jsm_installToolkitThreadNameInJava);
- });
-
+ if (![ThreadUtilities isAWTEmbedded]) {
+ dispatch_async(dispatch_get_main_queue(), ^(void){
+ [[NSThread currentThread] setName:@"AppKit Thread"];
+ JNIEnv *env = [ThreadUtilities getJNIEnv];
+ static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
+ static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
+ JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava);
+ });
+ }
+
gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS;
jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent");
--- a/jdk/src/macosx/native/sun/awt/awt.m Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/native/sun/awt/awt.m Wed Apr 16 10:53:10 2014 -0700
@@ -363,6 +363,7 @@
// AppKit Application.
NSApplication *app = [NSApplicationAWT sharedApplication];
isEmbedded = ![NSApp isKindOfClass:[NSApplicationAWT class]];
+ [ThreadUtilities setAWTEmbedded:isEmbedded];
if (!isEmbedded) {
// Install run loop observers and set the AppKit Java thread name
@@ -433,6 +434,14 @@
if (isSWTInWebStart(env)) {
forceEmbeddedMode = YES;
}
+ JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
+ jclass jc_ThreadGroupUtils = (*env)->FindClass(env, "sun/misc/ThreadGroupUtils");
+ jmethodID sjm_getRootThreadGroup = (*env)->GetStaticMethodID(env, jc_ThreadGroupUtils, "getRootThreadGroup", "()Ljava/lang/ThreadGroup;");
+ jobject rootThreadGroup = (*env)->CallStaticObjectMethod(env, jc_ThreadGroupUtils, sjm_getRootThreadGroup);
+ [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, rootThreadGroup)];
+ // The current thread was attached in getJNIEnvUnchached.
+ // Detach it back. It will be reattached later if needed with a proper TG
+ [ThreadUtilities detachCurrentThread];
BOOL headless = isHeadless(env);
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h Wed Apr 16 10:53:10 2014 -0700
@@ -127,6 +127,10 @@
+ (JNIEnv*)getJNIEnv;
+ (JNIEnv*)getJNIEnvUncached;
++ (void)detachCurrentThread;
++ (void)setAppkitThreadGroup:(jobject)group;
++ (void)setAWTEmbedded:(BOOL)embedded;
++ (BOOL)isAWTEmbedded;
//Wrappers for the corresponding JNFRunLoop methods with a check for main thread
+ (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block;
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m Wed Apr 16 10:53:10 2014 -0700
@@ -33,23 +33,45 @@
// The following must be named "jvm", as there are extern references to it in AWT
JavaVM *jvm = NULL;
static JNIEnv *appKitEnv = NULL;
+static jobject appkitThreadGroup = NULL;
+static BOOL awtEmbedded = NO;
+
+inline void attachCurrentThread(void** env) {
+ if ([NSThread isMainThread]) {
+ JavaVMAttachArgs args;
+ args.version = JNI_VERSION_1_4;
+ args.name = "AppKit Thread";
+ args.group = appkitThreadGroup;
+ (*jvm)->AttachCurrentThreadAsDaemon(jvm, env, &args);
+ } else {
+ (*jvm)->AttachCurrentThreadAsDaemon(jvm, env, NULL);
+ }
+}
@implementation ThreadUtilities
+ (JNIEnv*)getJNIEnv {
AWT_ASSERT_APPKIT_THREAD;
if (appKitEnv == NULL) {
- (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&appKitEnv, NULL);
+ attachCurrentThread((void **)&appKitEnv);
}
return appKitEnv;
}
+ (JNIEnv*)getJNIEnvUncached {
JNIEnv *env = NULL;
- (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&env, nil);
+ attachCurrentThread((void **)&env);
return env;
}
++ (void)detachCurrentThread {
+ (*jvm)->DetachCurrentThread(jvm);
+}
+
++ (void)setAppkitThreadGroup:(jobject)group {
+ appkitThreadGroup = group;
+}
+
+ (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block {
if ([NSThread isMainThread] && wait == YES) {
block();
@@ -66,6 +88,14 @@
}
}
++ (void)setAWTEmbedded:(BOOL)embedded {
+ awtEmbedded = embedded;
+}
+
++ (BOOL)isAWTEmbedded {
+ return awtEmbedded;
+}
+
@end
--- a/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java Wed Apr 16 10:53:10 2014 -0700
@@ -35,6 +35,8 @@
import javax.management.remote.SubjectDelegationPermission;
import com.sun.jmx.remote.util.CacheMap;
+import java.util.ArrayList;
+import java.util.Collection;
public class SubjectDelegator {
private static final int PRINCIPALS_CACHE_SIZE = 10;
@@ -53,11 +55,14 @@
boolean removeCallerContext)
throws SecurityException {
+ if (System.getSecurityManager() != null && authenticatedACC == null) {
+ throw new SecurityException("Illegal AccessControlContext: null");
+ }
if (principalsCache == null || accCache == null) {
principalsCache =
- new CacheMap<Subject, Principal[]>(PRINCIPALS_CACHE_SIZE);
+ new CacheMap<>(PRINCIPALS_CACHE_SIZE);
accCache =
- new CacheMap<Subject, AccessControlContext>(ACC_CACHE_SIZE);
+ new CacheMap<>(ACC_CACHE_SIZE);
}
// Retrieve the principals for the given
@@ -101,14 +106,15 @@
// principal in the delegated subject
//
final Principal[] dp = delegatedPrincipals;
+ final Collection<Permission> permissions = new ArrayList<>(dp.length);
+ for(Principal p : dp) {
+ final String pname = p.getClass().getName() + "." + p.getName();
+ permissions.add(new SubjectDelegationPermission(pname));
+ }
PrivilegedAction<Void> action =
new PrivilegedAction<Void>() {
public Void run() {
- for (int i = 0 ; i < dp.length ; i++) {
- final String pname =
- dp[i].getClass().getName() + "." + dp[i].getName();
- Permission sdp =
- new SubjectDelegationPermission(pname);
+ for (Permission sdp : permissions) {
AccessController.checkPermission(sdp);
}
return null;
--- a/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java Wed Apr 16 10:53:10 2014 -0700
@@ -30,13 +30,14 @@
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.Socket;
+import java.security.SecureRandom;
import javax.naming.*;
import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
+
+import sun.security.jca.JCAUtil;
// Some of this code began life as part of sun.javaos.net.DnsClient
// originally by sritchie@eng 1/96. It was first hacked up for JNDI
@@ -77,6 +78,8 @@
};
private static final int DEFAULT_PORT = 53;
+ private static final int TRANSACTION_ID_BOUND = 0x10000;
+ private static final SecureRandom random = JCAUtil.getSecureRandom();
private InetAddress[] servers;
private int[] serverPorts;
private int timeout; // initial timeout on UDP queries in ms
@@ -85,7 +88,7 @@
private DatagramSocket udpSocket;
// Requests sent
- private Set<Integer> reqs;
+ private Map<Integer, ResourceRecord> reqs;
// Responses received
private Map<Integer, byte[]> resps;
@@ -134,7 +137,8 @@
throw ne;
}
}
- reqs = Collections.synchronizedSet(new HashSet<Integer>());
+ reqs = Collections.synchronizedMap(
+ new HashMap<Integer, ResourceRecord>());
resps = Collections.synchronizedMap(new HashMap<Integer, byte[]>());
}
@@ -153,10 +157,6 @@
}
}
-
- private int ident = 0; // used to set the msg ID field
- private Object identLock = new Object();
-
/*
* If recursion is true, recursion is requested on the query.
* If auth is true, only authoritative responses are accepted; other
@@ -167,15 +167,19 @@
throws NamingException {
int xid;
- synchronized (identLock) {
- ident = 0xFFFF & (ident + 1);
- xid = ident;
- }
+ Packet pkt;
+ ResourceRecord collision;
- // enqueue the outstanding request
- reqs.add(xid);
+ do {
+ // Generate a random transaction ID
+ xid = random.nextInt(TRANSACTION_ID_BOUND);
+ pkt = makeQueryPacket(fqdn, xid, qclass, qtype, recursion);
- Packet pkt = makeQueryPacket(fqdn, xid, qclass, qtype, recursion);
+ // enqueue the outstanding request
+ collision = reqs.putIfAbsent(xid, new ResourceRecord(pkt.getData(),
+ pkt.length(), Header.HEADER_SIZE, true, false));
+
+ } while (collision != null);
Exception caughtException = null;
boolean[] doNotRetry = new boolean[servers.length];
@@ -305,11 +309,8 @@
ResourceRecords queryZone(DnsName zone, int qclass, boolean recursion)
throws NamingException {
- int xid;
- synchronized (identLock) {
- ident = 0xFFFF & (ident + 1);
- xid = ident;
- }
+ int xid = random.nextInt(TRANSACTION_ID_BOUND);
+
Packet pkt = makeQueryPacket(zone, xid, qclass,
ResourceRecord.QTYPE_AXFR, recursion);
Exception caughtException = null;
@@ -390,6 +391,7 @@
DatagramPacket opkt = new DatagramPacket(
pkt.getData(), pkt.length(), server, port);
DatagramPacket ipkt = new DatagramPacket(new byte[8000], 8000);
+ // Packets may only be sent to or received from this server address
udpSocket.connect(server, port);
int pktTimeout = (timeout * (1 << retry));
try {
@@ -542,6 +544,9 @@
* Checks the header of an incoming DNS response.
* Returns true if it matches the given xid and throws a naming
* exception, if appropriate, based on the response code.
+ *
+ * Also checks that the domain name, type and class in the response
+ * match those in the original query.
*/
private boolean isMatchResponse(byte[] pkt, int xid)
throws NamingException {
@@ -551,7 +556,7 @@
throw new CommunicationException("DNS error: expecting response");
}
- if (!reqs.contains(xid)) { // already received, ignore the response
+ if (!reqs.containsKey(xid)) { // already received, ignore the response
return false;
}
@@ -560,14 +565,47 @@
if (debug) {
dprint("XID MATCH:" + xid);
}
+ checkResponseCode(hdr);
+ if (!hdr.query && hdr.numQuestions == 1) {
- checkResponseCode(hdr);
- // remove the response for the xid if received by some other thread.
- synchronized (queuesLock) {
- resps.remove(xid);
- reqs.remove(xid);
+ ResourceRecord rr = new ResourceRecord(pkt, pkt.length,
+ Header.HEADER_SIZE, true, false);
+
+ // Retrieve the original query
+ ResourceRecord query = reqs.get(xid);
+ int qtype = query.getType();
+ int qclass = query.getRrclass();
+ DnsName qname = query.getName();
+
+ // Check that the type/class/name in the query section of the
+ // response match those in the original query
+ if ((qtype == ResourceRecord.QTYPE_STAR ||
+ qtype == rr.getType()) &&
+ (qclass == ResourceRecord.QCLASS_STAR ||
+ qclass == rr.getRrclass()) &&
+ qname.equals(rr.getName())) {
+
+ if (debug) {
+ dprint("MATCH NAME:" + qname + " QTYPE:" + qtype +
+ " QCLASS:" + qclass);
+ }
+
+ // Remove the response for the xid if received by some other
+ // thread.
+ synchronized (queuesLock) {
+ resps.remove(xid);
+ reqs.remove(xid);
+ }
+ return true;
+
+ } else {
+ if (debug) {
+ dprint("NO-MATCH NAME:" + qname + " QTYPE:" + qtype +
+ " QCLASS:" + qclass);
+ }
+ }
}
- return true;
+ return false;
}
//
@@ -576,7 +614,7 @@
// enqueue only the first response, responses for retries are ignored.
//
synchronized (queuesLock) {
- if (reqs.contains(hdr.xid)) { // enqueue only the first response
+ if (reqs.containsKey(hdr.xid)) { // enqueue only the first response
resps.put(hdr.xid, pkt);
}
}
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,6 +25,10 @@
package com.sun.jndi.ldap;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.Vector;
import javax.naming.*;
import javax.naming.directory.*;
@@ -36,6 +40,8 @@
final class LdapBindingEnumeration
extends AbstractLdapNamingEnumeration<Binding> {
+ private final AccessControlContext acc = AccessController.getContext();
+
LdapBindingEnumeration(LdapCtx homeCtx, LdapResult answer, Name remain,
Continuation cont) throws NamingException
{
@@ -52,7 +58,16 @@
if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) {
// serialized object or object reference
- obj = Obj.decodeObject(attrs);
+ try {
+ obj = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws NamingException {
+ return Obj.decodeObject(attrs);
+ }
+ }, acc);
+ } catch (PrivilegedActionException e) {
+ throw (NamingException)e.getException();
+ }
}
if (obj == null) {
// DirContext object
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,6 +25,10 @@
package com.sun.jndi.ldap;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.Vector;
import javax.naming.*;
import javax.naming.directory.*;
@@ -40,6 +44,8 @@
private Name startName; // prefix of names of search results
private LdapCtx.SearchArgs searchArgs = null;
+ private final AccessControlContext acc = AccessController.getContext();
+
LdapSearchEnumeration(LdapCtx homeCtx, LdapResult search_results,
String starter, LdapCtx.SearchArgs args, Continuation cont)
throws NamingException {
@@ -112,8 +118,16 @@
if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) {
// Entry contains Java-object attributes (ser/ref object)
// serialized object or object reference
- obj = Obj.decodeObject(attrs);
-
+ try {
+ obj = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws NamingException {
+ return Obj.decodeObject(attrs);
+ }
+ }, acc);
+ } catch (PrivilegedActionException e) {
+ throw (NamingException)e.getException();
+ }
}
if (obj == null) {
obj = new LdapCtx(homeCtx, dn);
--- a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,27 +25,33 @@
package com.sun.media.sound;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Properties;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Transmitter;
+import javax.sound.midi.spi.MidiDeviceProvider;
+import javax.sound.midi.spi.MidiFileReader;
+import javax.sound.midi.spi.MidiFileWriter;
+import javax.sound.midi.spi.SoundbankReader;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Port;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
+import javax.sound.sampled.spi.AudioFileReader;
+import javax.sound.sampled.spi.AudioFileWriter;
+import javax.sound.sampled.spi.FormatConversionProvider;
+import javax.sound.sampled.spi.MixerProvider;
/**
- * JDK13Services uses the Service class in JDK 1.3
- * to discover a list of service providers installed
- * in the system.
- *
+ * JDK13Services uses the Service class in JDK 1.3 to discover a list of service
+ * providers installed in the system.
+ * <p>
* This class is public because it is called from javax.sound.midi.MidiSystem
* and javax.sound.sampled.AudioSystem. The alternative would be to make
* JSSecurityManager public, which is considered worse.
@@ -54,80 +60,55 @@
*/
public final class JDK13Services {
- /** The default for the length of the period to hold the cache.
- This value is given in milliseconds. It is equivalent to
- 1 minute.
- */
- private static final long DEFAULT_CACHING_PERIOD = 60000;
-
- /** Filename of the properties file for default provider properties.
- This file is searched in the subdirectory "lib" of the JRE directory
- (this behaviour is hardcoded).
- */
+ /**
+ * Filename of the properties file for default provider properties. This
+ * file is searched in the subdirectory "lib" of the JRE directory (this
+ * behaviour is hardcoded).
+ */
private static final String PROPERTIES_FILENAME = "sound.properties";
- /** Cache for the providers.
- Class objects of the provider type (MixerProvider, MidiDeviceProvider
- ...) are used as keys. The values are instances of ProviderCache.
- */
- private static final Map providersCacheMap = new HashMap();
-
-
- /** The length of the period to hold the cache.
- This value is given in milliseconds.
- */
- private static long cachingPeriod = DEFAULT_CACHING_PERIOD;
-
- /** Properties loaded from the properties file for default provider
- properties.
- */
+ /**
+ * Properties loaded from the properties file for default provider
+ * properties.
+ */
private static Properties properties;
-
- /** Private, no-args constructor to ensure against instantiation.
+ /**
+ * Private, no-args constructor to ensure against instantiation.
*/
private JDK13Services() {
}
-
- /** Set the period provider lists are cached.
- This method is only intended for testing.
+ /**
+ * Obtains a List containing installed instances of the providers for the
+ * requested service. The returned List is immutable.
+ *
+ * @param serviceClass The type of providers requested. This should be one
+ * of AudioFileReader.class, AudioFileWriter.class,
+ * FormatConversionProvider.class, MixerProvider.class,
+ * MidiDeviceProvider.class, MidiFileReader.class,
+ * MidiFileWriter.class or SoundbankReader.class.
+ *
+ * @return A List of providers of the requested type. This List is
+ * immutable.
*/
- public static void setCachingPeriod(int seconds) {
- cachingPeriod = seconds * 1000L;
+ public static List<?> getProviders(final Class<?> serviceClass) {
+ final List<?> providers;
+ if (!MixerProvider.class.equals(serviceClass)
+ && !FormatConversionProvider.class.equals(serviceClass)
+ && !AudioFileReader.class.equals(serviceClass)
+ && !AudioFileWriter.class.equals(serviceClass)
+ && !MidiDeviceProvider.class.equals(serviceClass)
+ && !SoundbankReader.class.equals(serviceClass)
+ && !MidiFileWriter.class.equals(serviceClass)
+ && !MidiFileReader.class.equals(serviceClass)) {
+ providers = new ArrayList<>(0);
+ } else {
+ providers = JSSecurityManager.getProviders(serviceClass);
+ }
+ return Collections.unmodifiableList(providers);
}
-
- /** Obtains a List containing installed instances of the
- providers for the requested service.
- The List of providers is cached for the period of time given by
- {@link #cachingPeriod cachingPeriod}. During this period, the same
- List instance is returned for the same type of provider. After this
- period, a new instance is constructed and returned. The returned
- List is immutable.
- @param serviceClass The type of providers requested. This should be one
- of AudioFileReader.class, AudioFileWriter.class,
- FormatConversionProvider.class, MixerProvider.class,
- MidiDeviceProvider.class, MidiFileReader.class, MidiFileWriter.class or
- SoundbankReader.class.
- @return A List of providers of the requested type. This List is
- immutable.
- */
- public static synchronized List getProviders(Class serviceClass) {
- ProviderCache cache = (ProviderCache) providersCacheMap.get(serviceClass);
- if (cache == null) {
- cache = new ProviderCache();
- providersCacheMap.put(serviceClass, cache);
- }
- if (cache.providers == null ||
- System.currentTimeMillis() > cache.lastUpdate + cachingPeriod) {
- cache.providers = Collections.unmodifiableList(JSSecurityManager.getProviders(serviceClass));
- cache.lastUpdate = System.currentTimeMillis();
- }
- return cache.providers;
- }
-
-
/** Obtain the provider class name part of a default provider property.
@param typeClass The type of the default provider property. This
should be one of Receiver.class, Transmitter.class, Sequencer.class,
@@ -219,14 +200,4 @@
}
return properties;
}
-
- // INNER CLASSES
-
- private static class ProviderCache {
- // System time of the last update in milliseconds.
- public long lastUpdate;
-
- // The providers.
- public List providers;
- }
}
--- a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -185,8 +185,8 @@
return thread;
}
- static <T> List<T> getProviders(final Class<T> providerClass) {
- List<T> p = new ArrayList<>();
+ static synchronized <T> List<T> getProviders(final Class<T> providerClass) {
+ List<T> p = new ArrayList<>(7);
// ServiceLoader creates "lazy" iterator instance, but it ensures that
// next/hasNext run with permissions that are restricted by whatever
// creates the ServiceLoader instance, so it requires to be called from
--- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Wed Apr 16 10:53:10 2014 -0700
@@ -37,6 +37,7 @@
import javax.sql.rowset.serial.*;
import com.sun.rowset.internal.*;
import com.sun.rowset.providers.*;
+import sun.reflect.misc.ReflectUtil;
/**
* The standard implementation of the <code>CachedRowSet</code> interface.
@@ -2959,13 +2960,9 @@
// create new instance of the class
SQLData obj = null;
try {
- obj = (SQLData)c.newInstance();
- } catch (java.lang.InstantiationException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
- } catch (java.lang.IllegalAccessException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
+ obj = (SQLData) ReflectUtil.newInstance(c);
+ } catch(Exception ex) {
+ throw new SQLException("Unable to Instantiate: ", ex);
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
@@ -5710,13 +5707,9 @@
// create new instance of the class
SQLData obj = null;
try {
- obj = (SQLData)c.newInstance();
- } catch (java.lang.InstantiationException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
- } catch (java.lang.IllegalAccessException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
+ obj = (SQLData) ReflectUtil.newInstance(c);
+ } catch(Exception ex) {
+ throw new SQLException("Unable to Instantiate: ", ex);
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -29,6 +29,7 @@
import javax.sql.*;
import java.util.*;
import java.io.*;
+import sun.reflect.misc.ReflectUtil;
import com.sun.rowset.*;
import java.text.MessageFormat;
@@ -572,13 +573,9 @@
// create new instance of the class
SQLData obj = null;
try {
- obj = (SQLData)c.newInstance();
- } catch (java.lang.InstantiationException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
- } catch (java.lang.IllegalAccessException ex) {
- throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
- ex.getMessage()));
+ obj = (SQLData)ReflectUtil.newInstance(c);
+ } catch (Exception ex) {
+ throw new SQLException("Unable to Instantiate: ", ex);
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/java/awt/EventQueue.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/awt/EventQueue.java Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -1061,11 +1061,11 @@
t.setContextClassLoader(classLoader);
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(false);
+ AWTAutoShutdown.getInstance().notifyThreadBusy(t);
return t;
}
}
);
- AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
dispatchThread.start();
}
} finally {
--- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Wed Apr 16 10:53:10 2014 -0700
@@ -46,6 +46,7 @@
import java.util.Set;
import java.util.WeakHashMap;
+import sun.awt.AppContext;
import sun.awt.datatransfer.DataTransferer;
/**
@@ -65,10 +66,7 @@
*/
private static String JavaMIME = "JAVA_DATAFLAVOR:";
- /**
- * System singleton which maps a thread's ClassLoader to a SystemFlavorMap.
- */
- private static final WeakHashMap<ClassLoader, FlavorMap> flavorMaps = new WeakHashMap<>();
+ private static final Object FLAVOR_MAP_KEY = new Object();
/**
* Copied from java.util.Properties.
@@ -183,22 +181,12 @@
* @return the default FlavorMap for this thread's ClassLoader
*/
public static FlavorMap getDefaultFlavorMap() {
- ClassLoader contextClassLoader =
- Thread.currentThread().getContextClassLoader();
- if (contextClassLoader == null) {
- contextClassLoader = ClassLoader.getSystemClassLoader();
+ AppContext context = AppContext.getAppContext();
+ FlavorMap fm = (FlavorMap) context.get(FLAVOR_MAP_KEY);
+ if (fm == null) {
+ fm = new SystemFlavorMap();
+ context.put(FLAVOR_MAP_KEY, fm);
}
-
- FlavorMap fm;
-
- synchronized(flavorMaps) {
- fm = flavorMaps.get(contextClassLoader);
- if (fm == null) {
- fm = new SystemFlavorMap();
- flavorMaps.put(contextClassLoader, fm);
- }
- }
-
return fm;
}
@@ -239,26 +227,11 @@
}
});
- BufferedReader flavormapURL =
+ String url =
java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<BufferedReader>() {
- public BufferedReader run() {
- String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
-
- if (url == null) {
- return null;
- }
-
- try {
- return new BufferedReader
- (new InputStreamReader
- (new URL(url).openStream(), "ISO-8859-1"));
- } catch (MalformedURLException e) {
- System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
- } catch (IOException e) {
- System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
- }
- return null;
+ new java.security.PrivilegedAction<String>() {
+ public String run() {
+ return Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
}
});
@@ -270,6 +243,19 @@
}
}
+ BufferedReader flavormapURL = null;
+ if (url != null) {
+ try {
+ flavormapURL = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "ISO-8859-1"));
+ } catch (MalformedURLException e) {
+ System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
+ } catch (IOException e) {
+ System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
+ } catch (SecurityException e) {
+ // ignored
+ }
+ }
+
if (flavormapURL != null) {
try {
parseAndStoreReader(flavormapURL);
--- a/jdk/src/share/classes/java/lang/Thread.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java Wed Apr 16 10:53:10 2014 -0700
@@ -366,6 +366,8 @@
throw new NullPointerException("name cannot be null");
}
+ this.name = name.toCharArray();
+
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
@@ -402,7 +404,6 @@
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
- this.name = name.toCharArray();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
--- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 16 10:53:10 2014 -0700
@@ -140,7 +140,7 @@
* Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
* static field containing this value, and they must accordingly implement this method.
*/
- protected abstract SpeciesData speciesData();
+ /*non-public*/ abstract SpeciesData speciesData();
@Override
final Object internalProperties() {
@@ -156,7 +156,7 @@
return Arrays.asList(boundValues);
}
- public final Object arg(int i) {
+ /*non-public*/ final Object arg(int i) {
try {
switch (speciesData().fieldType(i)) {
case 'L': return argL(i);
@@ -170,22 +170,22 @@
}
throw new InternalError("unexpected type: " + speciesData().types+"."+i);
}
- public final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); }
- public final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); }
- public final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); }
- public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
- public final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); }
+ /*non-public*/ final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); }
+ /*non-public*/ final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); }
+ /*non-public*/ final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); }
+ /*non-public*/ final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
+ /*non-public*/ final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); }
//
// cloning API
//
- public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
- public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable;
+ /*non-public*/ abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
// The following is a grossly irregular hack:
@Override MethodHandle reinvokerTarget() {
@@ -203,39 +203,39 @@
private // make it private to force users to access the enclosing class first
static final class Species_L extends BoundMethodHandle {
final Object argL0;
- public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
+ /*non-public*/ Species_L(MethodType mt, LambdaForm lf, Object argL0) {
super(mt, lf);
this.argL0 = argL0;
}
// The following is a grossly irregular hack:
@Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
@Override
- public SpeciesData speciesData() {
+ /*non-public*/ SpeciesData speciesData() {
return SPECIES_DATA;
}
- public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
+ /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
@Override
- public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
+ /*non-public*/ final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
return new Species_L(mt, lf, argL0);
}
@Override
- public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
+ /*non-public*/ final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
}
@Override
- public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
+ /*non-public*/ final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
}
@Override
- public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
+ /*non-public*/ final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
}
@Override
- public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
+ /*non-public*/ final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
}
@Override
- public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
+ /*non-public*/ final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
}
}
@@ -338,10 +338,10 @@
final MethodHandle[] getters;
final SpeciesData[] extensions;
- public int fieldCount() {
+ /*non-public*/ int fieldCount() {
return types.length();
}
- public char fieldType(int i) {
+ /*non-public*/ char fieldType(int i) {
return types.charAt(i);
}
@@ -551,30 +551,30 @@
* final Object argL0;
* final Object argL1;
* final int argI2;
- * public Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
+ * Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
* super(mt, lf);
* this.argL0 = argL0;
* this.argL1 = argL1;
* this.argI2 = argI2;
* }
- * public final SpeciesData speciesData() { return SPECIES_DATA; }
- * public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
- * public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
+ * final SpeciesData speciesData() { return SPECIES_DATA; }
+ * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
+ * final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
* return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
* }
- * public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
+ * final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
* return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
- * public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
+ * final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
* return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
- * public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
+ * final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
* return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
- * public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
+ * final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
* return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
- * public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
+ * final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
* return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
* }
@@ -588,11 +588,12 @@
final String className = SPECIES_PREFIX_PATH + types;
final String sourceFile = SPECIES_PREFIX_NAME + types;
- cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
+ final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
+ cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
cw.visitSource(sourceFile, null);
// emit static types and SPECIES_DATA fields
- cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
+ cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
// emit bound argument fields
for (int i = 0; i < types.length(); ++i) {
@@ -605,7 +606,7 @@
MethodVisitor mv;
// emit constructor
- mv = cw.visitMethod(ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
@@ -629,7 +630,7 @@
mv.visitEnd();
// emit implementation of reinvokerTarget()
- mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG);
@@ -639,7 +640,7 @@
mv.visitEnd();
// emit implementation of speciesData()
- mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
mv.visitInsn(ARETURN);
@@ -647,7 +648,7 @@
mv.visitEnd();
// emit clone()
- mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
mv.visitCode();
// return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
// obtain constructor
@@ -670,7 +671,7 @@
// for each type, emit cloneExtendT()
for (Class<?> c : TYPES) {
char t = Wrapper.basicTypeChar(c);
- mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
mv.visitCode();
// return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
// obtain constructor
@@ -697,7 +698,7 @@
}
// emit class initializer
- mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
+ mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
mv.visitCode();
mv.visitLdcInsn(types);
mv.visitLdcInsn(Type.getObjectType(className));
--- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Apr 16 10:53:10 2014 -0700
@@ -272,8 +272,9 @@
* Set up class file generation.
*/
private void classFilePrologue() {
+ final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
- cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
+ cw.visit(Opcodes.V1_8, NOT_ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
cw.visitSource(sourceFile, null);
String invokerDesc = invokerType.toMethodDescriptorString();
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Wed Apr 16 10:53:10 2014 -0700
@@ -2070,6 +2070,7 @@
*/
public static
MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
+ reorder = reorder.clone();
checkReorder(reorder, newType, target.type());
return target.permuteArguments(newType, reorder);
}
@@ -2264,6 +2265,7 @@
throw newIllegalArgumentException("no argument type to remove");
ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList());
ptypes.addAll(pos, valueTypes);
+ if (ptypes.size() != inargs) throw newIllegalArgumentException("valueTypes");
MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
return target.dropArguments(newType, pos, dropped);
}
--- a/jdk/src/share/classes/java/nio/file/Files.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java Wed Apr 16 10:53:10 2014 -0700
@@ -38,7 +38,6 @@
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
@@ -739,7 +738,7 @@
// don't have permission to get absolute path
se = x;
}
- // find a decendent that exists
+ // find a descendant that exists
Path parent = dir.getParent();
while (parent != null) {
try {
@@ -1400,7 +1399,7 @@
return target;
}
- // -- Miscellenous --
+ // -- Miscellaneous --
/**
* Reads the target of a symbolic link <i>(optional operation)</i>.
@@ -1535,7 +1534,7 @@
private static class FileTypeDetectors{
static final FileTypeDetector defaultFileTypeDetector =
createDefaultFileTypeDetector();
- static final List<FileTypeDetector> installeDetectors =
+ static final List<FileTypeDetector> installedDetectors =
loadInstalledDetectors();
// creates the default file type detector
@@ -1614,7 +1613,7 @@
throws IOException
{
// try installed file type detectors
- for (FileTypeDetector detector: FileTypeDetectors.installeDetectors) {
+ for (FileTypeDetector detector: FileTypeDetectors.installedDetectors) {
String result = detector.probeContentType(path);
if (result != null)
return result;
@@ -1922,7 +1921,7 @@
* </tr>
* <tr>
* <td> {@code "posix:permissions,owner,size"} </td>
- * <td> Reads the POSX file permissions, owner, and file size. </td>
+ * <td> Reads the POSIX file permissions, owner, and file size. </td>
* </tr>
* </table>
* </blockquote>
@@ -2448,7 +2447,7 @@
}
/**
- * Used by isReadbale, isWritable, isExecutable to test access to a file.
+ * Used by isReadable, isWritable, isExecutable to test access to a file.
*/
private static boolean isAccessible(Path path, AccessMode... modes) {
try {
--- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Wed Apr 16 10:53:10 2014 -0700
@@ -81,7 +81,7 @@
// installed providers
private static volatile List<FileSystemProvider> installedProviders;
- // used to avoid recursive loading of instaled providers
+ // used to avoid recursive loading of installed providers
private static boolean loadingProviders = false;
private static Void checkPermission() {
--- a/jdk/src/share/classes/java/security/Provider.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/security/Provider.java Wed Apr 16 10:53:10 2014 -0700
@@ -1332,7 +1332,7 @@
addEngine("SSLContext", false, null);
addEngine("TrustManagerFactory", false, null);
// JGSS
- addEngine("GssApiMechanism", true, "sun.security.jgss.GSSCaller");
+ addEngine("GssApiMechanism", false, null);
// SASL
addEngine("SaslClientFactory", false, null);
addEngine("SaslServerFactory", false, null);
--- a/jdk/src/share/classes/java/util/ServiceLoader.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/util/ServiceLoader.java Wed Apr 16 10:53:10 2014 -0700
@@ -382,7 +382,7 @@
return p;
} catch (Throwable x) {
fail(service,
- "Provider " + cn + " could not be instantiated: " + x,
+ "Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
--- a/jdk/src/share/classes/java/util/jar/JarVerifier.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java Wed Apr 16 10:53:10 2014 -0700
@@ -676,6 +676,8 @@
} else {
matchUnsigned = true;
}
+ } else {
+ matchUnsigned = true;
}
}
@@ -778,23 +780,7 @@
// true if file is part of the signature mechanism itself
static boolean isSigningRelated(String name) {
- name = name.toUpperCase(Locale.ENGLISH);
- if (!name.startsWith("META-INF/")) {
- return false;
- }
- name = name.substring(9);
- if (name.indexOf('/') != -1) {
- return false;
- }
- if (name.endsWith(".DSA")
- || name.endsWith(".RSA")
- || name.endsWith(".SF")
- || name.endsWith(".EC")
- || name.startsWith("SIG-")
- || name.equals("MANIFEST.MF")) {
- return true;
- }
- return false;
+ return SignatureFileVerifier.isSigningRelated(name);
}
private Enumeration<String> unsignedEntryNames(JarFile jar) {
--- a/jdk/src/share/classes/java/util/logging/LogManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -464,7 +464,7 @@
Logger result = getLogger(name);
if (result == null) {
// only allocate the new logger once
- Logger newLogger = new Logger(name, resourceBundleName, caller, this);
+ Logger newLogger = new Logger(name, resourceBundleName, caller, this, false);
do {
if (addLogger(newLogger)) {
// We successfully added the new Logger that we
@@ -511,13 +511,13 @@
} while (logger == null);
// LogManager will set the sysLogger's handlers via LogManager.addLogger method.
- if (logger != sysLogger && sysLogger.getHandlers().length == 0) {
+ if (logger != sysLogger && sysLogger.accessCheckedHandlers().length == 0) {
// if logger already exists but handlers not set
final Logger l = logger;
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
- for (Handler hdl : l.getHandlers()) {
+ for (Handler hdl : l.accessCheckedHandlers()) {
sysLogger.addHandler(hdl);
}
return null;
@@ -835,7 +835,7 @@
Logger result = findLogger(name);
if (result == null) {
// only allocate the new system logger once
- Logger newLogger = new Logger(name, resourceBundleName, null, getOwner());
+ Logger newLogger = new Logger(name, resourceBundleName, null, getOwner(), true);
do {
if (addLocalLogger(newLogger)) {
// We successfully added the new Logger that we
@@ -1527,7 +1527,7 @@
// We do not call the protected Logger two args constructor here,
// to avoid calling LogManager.getLogManager() from within the
// RootLogger constructor.
- super("", null, null, LogManager.this);
+ super("", null, null, LogManager.this, true);
}
@Override
@@ -1550,9 +1550,9 @@
}
@Override
- public Handler[] getHandlers() {
+ Handler[] accessCheckedHandlers() {
initializeGlobalHandlers();
- return super.getHandlers();
+ return super.accessCheckedHandlers();
}
}
--- a/jdk/src/share/classes/java/util/logging/Logger.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Apr 16 10:53:10 2014 -0700
@@ -277,6 +277,7 @@
private volatile Level levelObject;
private volatile int levelValue; // current effective level value
private WeakReference<ClassLoader> callersClassLoaderRef;
+ private final boolean isSystemLogger;
/**
* GLOBAL_LOGGER_NAME is a name for the global logger.
@@ -370,11 +371,12 @@
* no corresponding resource can be found.
*/
protected Logger(String name, String resourceBundleName) {
- this(name, resourceBundleName, null, LogManager.getLogManager());
+ this(name, resourceBundleName, null, LogManager.getLogManager(), false);
}
- Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager) {
+ Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager, boolean isSystemLogger) {
this.manager = manager;
+ this.isSystemLogger = isSystemLogger;
setupResourceInfo(resourceBundleName, caller);
this.name = name;
levelValue = Level.INFO.intValue();
@@ -401,6 +403,7 @@
private Logger(String name) {
// The manager field is not initialized here.
this.name = name;
+ this.isSystemLogger = true;
levelValue = Level.INFO.intValue();
}
@@ -635,7 +638,7 @@
// cleanup some Loggers that have been GC'ed
manager.drainLoggerRefQueueBounded();
Logger result = new Logger(null, resourceBundleName,
- Reflection.getCallerClass(), manager);
+ Reflection.getCallerClass(), manager, false);
result.anonymous = true;
Logger root = manager.getLogger("");
result.doSetParent(root);
@@ -727,15 +730,23 @@
Logger logger = this;
while (logger != null) {
- for (Handler handler : logger.getHandlers()) {
+ final Handler[] loggerHandlers = isSystemLogger
+ ? logger.accessCheckedHandlers()
+ : logger.getHandlers();
+
+ for (Handler handler : loggerHandlers) {
handler.publish(record);
}
- if (!logger.getUseParentHandlers()) {
+ final boolean useParentHdls = isSystemLogger
+ ? logger.useParentHandlers
+ : logger.getUseParentHandlers();
+
+ if (!useParentHdls) {
break;
}
- logger = logger.getParent();
+ logger = isSystemLogger ? logger.parent : logger.getParent();
}
}
@@ -1762,6 +1773,12 @@
* @return an array of all registered Handlers
*/
public Handler[] getHandlers() {
+ return accessCheckedHandlers();
+ }
+
+ // This method should ideally be marked final - but unfortunately
+ // it needs to be overridden by LogManager.RootLogger
+ Handler[] accessCheckedHandlers() {
return handlers.toArray(emptyHandlers);
}
@@ -2149,12 +2166,14 @@
if (trb.userBundle != null) {
return trb;
}
- final String rbName = target.getResourceBundleName();
+ final String rbName = isSystemLogger
+ ? trb.resourceBundleName
+ : target.getResourceBundleName();
if (rbName != null) {
return LoggerBundle.get(rbName,
findResourceBundle(rbName, true));
}
- target = target.getParent();
+ target = isSystemLogger ? target.parent : target.getParent();
}
return NO_RESOURCE_BUNDLE;
}
--- a/jdk/src/share/classes/javax/script/ScriptEngineManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/script/ScriptEngineManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -81,23 +81,28 @@
nameAssociations = new HashMap<String, ScriptEngineFactory>();
extensionAssociations = new HashMap<String, ScriptEngineFactory>();
mimeTypeAssociations = new HashMap<String, ScriptEngineFactory>();
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- initEngines(loader);
- return null;
- }
- });
+ initEngines(loader);
+ }
+
+ private ServiceLoader<ScriptEngineFactory> getServiceLoader(final ClassLoader loader) {
+ if (loader != null) {
+ return ServiceLoader.load(ScriptEngineFactory.class, loader);
+ } else {
+ return ServiceLoader.loadInstalled(ScriptEngineFactory.class);
+ }
}
private void initEngines(final ClassLoader loader) {
Iterator<ScriptEngineFactory> itr = null;
try {
- ServiceLoader<ScriptEngineFactory> sl;
- if (loader != null) {
- sl = ServiceLoader.load(ScriptEngineFactory.class, loader);
- } else {
- sl = ServiceLoader.loadInstalled(ScriptEngineFactory.class);
- }
+ ServiceLoader<ScriptEngineFactory> sl = AccessController.doPrivileged(
+ new PrivilegedAction<ServiceLoader<ScriptEngineFactory>>() {
+ @Override
+ public ServiceLoader<ScriptEngineFactory> run() {
+ return getServiceLoader(loader);
+ }
+ });
+
itr = sl.iterator();
} catch (ServiceConfigurationError err) {
System.err.println("Can't find ScriptEngineFactory providers: " +
--- a/jdk/src/share/classes/javax/security/auth/Subject.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/security/auth/Subject.java Wed Apr 16 10:53:10 2014 -0700
@@ -959,14 +959,30 @@
/**
* Reads this object from a stream (i.e., deserializes it)
*/
+ @SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
+ ObjectInputStream.GetField gf = s.readFields();
+
+ readOnly = gf.get("readOnly", false);
+
+ Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
// Rewrap the principals into a SecureSet
- principals = Collections.synchronizedSet(new SecureSet<Principal>
- (this, PRINCIPAL_SET, principals));
+ if (inputPrincs == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+ try {
+ principals = Collections.synchronizedSet(new SecureSet<Principal>
+ (this, PRINCIPAL_SET, inputPrincs));
+ } catch (NullPointerException npe) {
+ // Sometimes people deserialize the principals set only.
+ // Subject is not accessible, so just don't fail.
+ principals = Collections.synchronizedSet
+ (new SecureSet<Principal>(this, PRINCIPAL_SET));
+ }
// The Credential {@code Set} is not serialized, but we do not
// want the default deserialization routine to set it to null.
--- a/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java Wed Apr 16 10:53:10 2014 -0700
@@ -28,8 +28,11 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.SQLException;
+import java.util.PropertyPermission;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
+import javax.sql.rowset.spi.SyncFactoryException;
+import sun.reflect.misc.ReflectUtil;
/**
* A factory API that enables applications to obtain a
@@ -129,15 +132,11 @@
factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
if (factoryClassName != null) {
trace("Found system property, value=" + factoryClassName);
- factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance();
+ factory = (RowSetFactory) ReflectUtil.newInstance(getFactoryClass(factoryClassName, null, true));
}
- } catch (ClassNotFoundException e) {
- throw new SQLException(
- "RowSetFactory: " + factoryClassName + " not found", e);
- } catch (Exception e) {
- throw new SQLException(
- "RowSetFactory: " + factoryClassName + " could not be instantiated: " + e,
- e);
+ } catch (Exception e) {
+ throw new SQLException( "RowSetFactory: " + factoryClassName +
+ " could not be instantiated: ", e);
}
// Check to see if we found the RowSetFactory via a System property
@@ -182,6 +181,16 @@
throws SQLException {
trace("***In newInstance()");
+
+ if(factoryClassName == null) {
+ throw new SQLException("Error: factoryClassName cannot be null");
+ }
+ try {
+ ReflectUtil.checkPackageAccess(factoryClassName);
+ } catch (java.security.AccessControlException e) {
+ throw new SQLException("Access Exception",e);
+ }
+
try {
Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);
RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
@@ -291,8 +300,9 @@
public String run() {
return System.getProperty(propName);
}
- });
+ }, null, new PropertyPermission(propName, "read"));
} catch (SecurityException se) {
+ trace("error getting " + propName + ": "+ se);
if (debug) {
se.printStackTrace();
}
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Wed Apr 16 10:53:10 2014 -0700
@@ -27,6 +27,7 @@
import java.sql.*;
import java.util.Arrays;
import java.util.Map;
+import sun.reflect.misc.ReflectUtil;
/**
* An input stream used for custom mapping user-defined types (UDTs).
@@ -476,13 +477,9 @@
// create new instance of the class
SQLData obj = null;
try {
- obj = (SQLData)c.newInstance();
- } catch (java.lang.InstantiationException ex) {
- throw new SQLException("Unable to instantiate: " +
- ex.getMessage());
- } catch (java.lang.IllegalAccessException ex) {
- throw new SQLException("Unable to instantiate: " +
- ex.getMessage());
+ obj = (SQLData)ReflectUtil.newInstance(c);
+ } catch (Exception ex) {
+ throw new SQLException("Unable to Instantiate: ", ex);
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java Wed Apr 16 10:53:10 2014 -0700
@@ -37,8 +37,11 @@
import java.io.FileNotFoundException;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import javax.naming.*;
+import sun.reflect.misc.ReflectUtil;
/**
* The Service Provider Interface (SPI) mechanism that generates <code>SyncProvider</code>
@@ -329,7 +332,7 @@
// Local implementation class names and keys from Properties
// file, translate names into Class objects using Class.forName
// and store mappings
- Properties properties = new Properties();
+ final Properties properties = new Properties();
if (implementations == null) {
implementations = new Hashtable<>();
@@ -356,10 +359,11 @@
public String run() {
return System.getProperty("rowset.properties");
}
- }, null, new PropertyPermission("rowset.properties","read"));
+ }, null, new PropertyPermission("rowset.properties", "read"));
} catch (Exception ex) {
+ System.out.println("errorget rowset.properties: " + ex);
strRowsetProperties = null;
- }
+ };
if (strRowsetProperties != null) {
// Load user's implementation of SyncProvider
@@ -380,14 +384,27 @@
ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try (InputStream stream =
- (cl == null) ? ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
- : cl.getResourceAsStream(ROWSET_PROPERTIES)) {
- if (stream == null) {
- throw new SyncFactoryException(
- "Resource " + ROWSET_PROPERTIES + " not found");
+ try {
+ AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+ try (InputStream stream = (cl == null) ?
+ ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
+ : cl.getResourceAsStream(ROWSET_PROPERTIES)) {
+ if (stream == null) {
+ throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
+ }
+ properties.load(stream);
+ }
+ return null;
+ });
+ } catch (PrivilegedActionException ex) {
+ Throwable e = ex.getException();
+ if (e instanceof SyncFactoryException) {
+ throw (SyncFactoryException) e;
+ } else {
+ SyncFactoryException sfe = new SyncFactoryException();
+ sfe.initCause(ex.getException());
+ throw sfe;
}
- properties.load(stream);
}
parseProperties(properties);
@@ -411,7 +428,7 @@
public String run() {
return System.getProperty(ROWSET_SYNC_PROVIDER);
}
- }, null, new PropertyPermission(ROWSET_SYNC_PROVIDER,"read"));
+ }, null, new PropertyPermission(ROWSET_SYNC_PROVIDER, "read"));
} catch (Exception ex) {
providerImpls = null;
}
@@ -547,6 +564,14 @@
return new com.sun.rowset.providers.RIOptimisticProvider();
}
+ try {
+ ReflectUtil.checkPackageAccess(providerID);
+ } catch (java.security.AccessControlException e) {
+ SyncFactoryException sfe = new SyncFactoryException();
+ sfe.initCause(e);
+ throw sfe;
+ }
+
// Attempt to invoke classname from registered SyncProvider list
Class<?> c = null;
try {
@@ -555,7 +580,7 @@
/**
* The SyncProvider implementation of the user will be in
* the classpath. We need to find the ClassLoader which loads
- * this SyncFactory and try to laod the SyncProvider class from
+ * this SyncFactory and try to load the SyncProvider class from
* there.
**/
c = Class.forName(providerID, true, cl);
--- a/jdk/src/share/classes/javax/swing/JTable.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/javax/swing/JTable.java Wed Apr 16 10:53:10 2014 -0700
@@ -4042,7 +4042,7 @@
}
// Restore the lead
int viewLeadIndex = modelSelection.getLeadSelectionIndex();
- if (viewLeadIndex != -1) {
+ if (viewLeadIndex != -1 && !modelSelection.isSelectionEmpty()) {
viewLeadIndex = convertRowIndexToView(viewLeadIndex);
}
SwingUtilities2.setLeadAnchorWithoutSelection(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/JarFileSystemProvider.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007, 2014, 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.
+ */
+
+package jdk.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;
+
+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
+ }
+ }
+
+ @Override
+ public Path getPath(URI uri) {
+ FileSystem fs = getFileSystem(uri);
+ String path = uri.getFragment();
+ if (path == null) {
+ String uristr = uri.toString();
+ int off = uristr.indexOf("!/");
+ if (off != -1)
+ path = uristr.substring(off + 2);
+ }
+ if (path != null)
+ return fs.getPath(path);
+ throw new IllegalArgumentException("URI: "
+ + uri
+ + " does not contain path fragment ex. jar:///c:/foo.zip!/BAR");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,2 @@
+jdk.nio.zipfs.ZipFileSystemProvider
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipCoder.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipConstants.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+/**
+ *
+ * @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;
+ static final int METHOD_AES = 99;
+
+ /*
+ * 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
+ static final int EXTID_EFS = 0x0017; // Strong Encryption
+ static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp
+
+ /*
+ * fields access methods
+ */
+ ///////////////////////////////////////////////////////
+ static final int CH(byte[] b, int n) {
+ return Byte.toUnsignedInt(b[n]);
+ }
+
+ static final int SH(byte[] b, int n) {
+ return Byte.toUnsignedInt(b[n]) | (Byte.toUnsignedInt(b[n + 1]) << 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
+
+ // central directory header (CEN) fields
+ static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
+ static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
+ static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
+ static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
+ static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
+ static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
+ static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
+ static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
+ static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
+ static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
+ static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
+ static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
+ static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
+ static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
+ static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
+ static final long CENOFF(byte[] 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.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;
+
+/**
+ *
+ * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+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;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributeView.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/*
+ * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+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);
+ if (AttrID.valueOf(attribute) == AttrID.lastAccessTime)
+ setTimes (null, (FileTime)value, null);
+ if (AttrID.valueOf(attribute) == AttrID.creationTime)
+ setTimes (null, null, (FileTime)value);
+ return;
+ } catch (IllegalArgumentException x) {}
+ throw new UnsupportedOperationException("'" + attribute +
+ "' is unknown or read-only attribute");
+ }
+
+ Map<String, Object> readAttributes(String attributes)
+ throws IOException
+ {
+ ZipFileAttributes zfas = readAttributes();
+ LinkedHashMap<String, Object> map = new LinkedHashMap<>();
+ if ("*".equals(attributes)) {
+ for (AttrID id : AttrID.values()) {
+ try {
+ map.put(id.name(), attribute(id, zfas));
+ } catch (IllegalArgumentException x) {}
+ }
+ } else {
+ String[] as = attributes.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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributes.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.Arrays;
+import java.util.Formatter;
+import static jdk.nio.zipfs.ZipUtils.*;
+
+/**
+ *
+ * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+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(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(e.atime);
+ return null;
+ }
+
+ @Override
+ public FileTime lastModifiedTime() {
+ return FileTime.fromMillis(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 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(1024);
+ Formatter fm = new Formatter(sb);
+ if (creationTime() != null)
+ fm.format(" creationTime : %tc%n", creationTime().toMillis());
+ else
+ fm.format(" creationTime : null%n");
+
+ 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileStore.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileStoreAttributeView;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.util.Formatter;
+
+/*
+ *
+ * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+class ZipFileStore extends FileStore {
+
+ private final ZipFileSystem zfs;
+
+ ZipFileStore(ZipPath zpath) {
+ this.zfs = 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();
+ return (V)null;
+ }
+
+ @Override
+ public long getTotalSpace() throws IOException {
+ return new ZipFileStoreAttributes(this).totalSpace();
+ }
+
+ @Override
+ public long getUsableSpace() throws IOException {
+ return new ZipFileStoreAttributes(this).usableSpace();
+ }
+
+ @Override
+ public long getUnallocatedSpace() throws IOException {
+ return new ZipFileStoreAttributes(this).unallocatedSpace();
+ }
+
+ @Override
+ public Object getAttribute(String attribute) throws IOException {
+ if (attribute.equals("totalSpace"))
+ return getTotalSpace();
+ if (attribute.equals("usableSpace"))
+ return getUsableSpace();
+ if (attribute.equals("unallocatedSpace"))
+ return getUnallocatedSpace();
+ throw new UnsupportedOperationException("does not support the given attribute");
+ }
+
+ private static class ZipFileStoreAttributes {
+ final FileStore fstore;
+ final long size;
+
+ public ZipFileStoreAttributes(ZipFileStore fileStore)
+ throws IOException
+ {
+ Path path = FileSystems.getDefault().getPath(fileStore.name());
+ this.size = Files.size(path);
+ this.fstore = Files.getFileStore(path);
+ }
+
+ public long totalSpace() {
+ return size;
+ }
+
+ public long usableSpace() throws IOException {
+ if (!fstore.isReadOnly())
+ return fstore.getUsableSpace();
+ return 0;
+ }
+
+ public long unallocatedSpace() throws IOException {
+ if (!fstore.isReadOnly())
+ return fstore.getUnallocatedSpace();
+ return 0;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.Inflater;
+import java.util.zip.Deflater;
+import java.util.zip.InflaterInputStream;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.ZipException;
+import java.util.zip.ZipError;
+import static java.lang.Boolean.*;
+import static jdk.nio.zipfs.ZipConstants.*;
+import static jdk.nio.zipfs.ZipUtils.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/**
+ * A FileSystem built on a zip file
+ *
+ * @author Xueming Shen
+ */
+
+class ZipFileSystem extends FileSystem {
+
+ private final ZipFileSystemProvider provider;
+ private final ZipPath defaultdir;
+ private boolean readOnly = false;
+ private final Path zfpath;
+ private final ZipCoder zc;
+
+ // configurable by env map
+ private final String defaultDir; // default dir for the file system
+ private final String nameEncoding; // default encoding for name/comment
+ private final boolean useTempFile; // use a temp file for newOS, default
+ // is to use BAOS for better performance
+ private final boolean createNew; // create a new zip if not exists
+ private static final boolean isWindows = AccessController.doPrivileged(
+ (PrivilegedAction<Boolean>) () -> System.getProperty("os.name")
+ .startsWith("Windows"));
+
+ ZipFileSystem(ZipFileSystemProvider provider,
+ Path zfpath,
+ Map<String, ?> env)
+ throws IOException
+ {
+ // configurable env setup
+ this.createNew = "true".equals(env.get("create"));
+ this.nameEncoding = env.containsKey("encoding") ?
+ (String)env.get("encoding") : "UTF-8";
+ this.useTempFile = TRUE.equals(env.get("useTempFile"));
+ this.defaultDir = env.containsKey("default.dir") ?
+ (String)env.get("default.dir") : "/";
+ if (this.defaultDir.charAt(0) != '/')
+ throw new IllegalArgumentException("default dir should be absolute");
+
+ this.provider = provider;
+ this.zfpath = zfpath;
+ if (Files.notExists(zfpath)) {
+ if (createNew) {
+ try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) {
+ new END().write(os, 0);
+ }
+ } else {
+ throw new FileSystemNotFoundException(zfpath.toString());
+ }
+ }
+ // sm and existence check
+ zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
+ if (!Files.isWritable(zfpath))
+ this.readOnly = true;
+ this.zc = ZipCoder.get(nameEncoding);
+ this.defaultdir = new ZipPath(this, getBytes(defaultDir));
+ this.ch = Files.newByteChannel(zfpath, READ);
+ this.cen = initCEN();
+ }
+
+ @Override
+ public FileSystemProvider provider() {
+ return provider;
+ }
+
+ @Override
+ public String getSeparator() {
+ return "/";
+ }
+
+ @Override
+ public boolean isOpen() {
+ return isOpen;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ private void checkWritable() throws IOException {
+ if (readOnly)
+ throw new ReadOnlyFileSystemException();
+ }
+
+ @Override
+ public Iterable<Path> getRootDirectories() {
+ ArrayList<Path> pathArr = new ArrayList<>();
+ pathArr.add(new ZipPath(this, new byte[]{'/'}));
+ return pathArr;
+ }
+
+ ZipPath getDefaultDir() { // package private
+ return defaultdir;
+ }
+
+ @Override
+ public ZipPath getPath(String first, String... more) {
+ String path;
+ if (more.length == 0) {
+ path = first;
+ } else {
+ StringBuilder sb = new StringBuilder();
+ sb.append(first);
+ for (String segment: more) {
+ if (segment.length() > 0) {
+ if (sb.length() > 0)
+ sb.append('/');
+ sb.append(segment);
+ }
+ }
+ path = sb.toString();
+ }
+ return new ZipPath(this, getBytes(path));
+ }
+
+ @Override
+ public UserPrincipalLookupService getUserPrincipalLookupService() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WatchService newWatchService() {
+ throw new UnsupportedOperationException();
+ }
+
+ FileStore getFileStore(ZipPath path) {
+ return new ZipFileStore(path);
+ }
+
+ @Override
+ public Iterable<FileStore> getFileStores() {
+ ArrayList<FileStore> list = new ArrayList<>(1);
+ list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'})));
+ return list;
+ }
+
+ private static final Set<String> supportedFileAttributeViews =
+ Collections.unmodifiableSet(
+ new HashSet<String>(Arrays.asList("basic", "zip")));
+
+ @Override
+ public Set<String> supportedFileAttributeViews() {
+ return supportedFileAttributeViews;
+ }
+
+ @Override
+ public String toString() {
+ return zfpath.toString();
+ }
+
+ Path getZipFile() {
+ return zfpath;
+ }
+
+ private static final String GLOB_SYNTAX = "glob";
+ private static final String REGEX_SYNTAX = "regex";
+
+ @Override
+ public PathMatcher getPathMatcher(String syntaxAndInput) {
+ int pos = syntaxAndInput.indexOf(':');
+ if (pos <= 0 || pos == syntaxAndInput.length()) {
+ throw new IllegalArgumentException();
+ }
+ String syntax = syntaxAndInput.substring(0, pos);
+ String input = syntaxAndInput.substring(pos + 1);
+ String expr;
+ if (syntax.equals(GLOB_SYNTAX)) {
+ expr = toRegexPattern(input);
+ } else {
+ if (syntax.equals(REGEX_SYNTAX)) {
+ expr = input;
+ } else {
+ throw new UnsupportedOperationException("Syntax '" + syntax +
+ "' not recognized");
+ }
+ }
+ // return matcher
+ final Pattern pattern = Pattern.compile(expr);
+ return new PathMatcher() {
+ @Override
+ public boolean matches(Path path) {
+ return pattern.matcher(path.toString()).matches();
+ }
+ };
+ }
+
+ @Override
+ public void close() throws IOException {
+ beginWrite();
+ try {
+ if (!isOpen)
+ return;
+ isOpen = false; // set closed
+ } finally {
+ endWrite();
+ }
+ if (!streams.isEmpty()) { // unlock and close all remaining streams
+ Set<InputStream> copy = new HashSet<>(streams);
+ for (InputStream is: copy)
+ is.close();
+ }
+ beginWrite(); // lock and sync
+ try {
+ sync();
+ ch.close(); // close the ch just in case no update
+ } finally { // and sync dose not close the ch
+ endWrite();
+ }
+
+ synchronized (inflaters) {
+ for (Inflater inf : inflaters)
+ inf.end();
+ }
+ synchronized (deflaters) {
+ for (Deflater def : deflaters)
+ def.end();
+ }
+
+ IOException ioe = null;
+ synchronized (tmppaths) {
+ for (Path p: tmppaths) {
+ try {
+ Files.deleteIfExists(p);
+ } catch (IOException x) {
+ if (ioe == null)
+ ioe = x;
+ else
+ ioe.addSuppressed(x);
+ }
+ }
+ }
+ provider.removeFileSystem(zfpath, this);
+ if (ioe != null)
+ throw ioe;
+ }
+
+ ZipFileAttributes getFileAttributes(byte[] path)
+ throws IOException
+ {
+ Entry e;
+ beginRead();
+ try {
+ ensureOpen();
+ e = getEntry0(path);
+ if (e == null) {
+ IndexNode inode = getInode(path);
+ if (inode == null)
+ return null;
+ e = new Entry(inode.name); // pseudo directory
+ e.method = METHOD_STORED; // STORED for dir
+ e.mtime = e.atime = e.ctime = -1;// -1 for all times
+ }
+ } finally {
+ endRead();
+ }
+ return new ZipFileAttributes(e);
+ }
+
+ void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
+ throws IOException
+ {
+ checkWritable();
+ beginWrite();
+ try {
+ ensureOpen();
+ Entry e = getEntry0(path); // ensureOpen checked
+ if (e == null)
+ throw new NoSuchFileException(getString(path));
+ if (e.type == Entry.CEN)
+ e.type = Entry.COPY; // copy e
+ if (mtime != null)
+ e.mtime = mtime.toMillis();
+ if (atime != null)
+ e.atime = atime.toMillis();
+ if (ctime != null)
+ e.ctime = ctime.toMillis();
+ update(e);
+ } finally {
+ endWrite();
+ }
+ }
+
+ boolean exists(byte[] path)
+ throws IOException
+ {
+ beginRead();
+ try {
+ ensureOpen();
+ return getInode(path) != null;
+ } finally {
+ endRead();
+ }
+ }
+
+ boolean isDirectory(byte[] path)
+ throws IOException
+ {
+ beginRead();
+ try {
+ IndexNode n = getInode(path);
+ return n != null && n.isDir();
+ } finally {
+ endRead();
+ }
+ }
+
+ private ZipPath toZipPath(byte[] path) {
+ // make it absolute
+ byte[] p = new byte[path.length + 1];
+ p[0] = '/';
+ System.arraycopy(path, 0, p, 1, path.length);
+ return new ZipPath(this, p);
+ }
+
+ // returns the list of child paths of "path"
+ Iterator<Path> iteratorOf(byte[] path,
+ DirectoryStream.Filter<? super Path> filter)
+ throws IOException
+ {
+ beginWrite(); // iteration of inodes needs exclusive lock
+ try {
+ ensureOpen();
+ IndexNode inode = getInode(path);
+ if (inode == null)
+ throw new NotDirectoryException(getString(path));
+ List<Path> list = new ArrayList<>();
+ IndexNode child = inode.child;
+ while (child != null) {
+ ZipPath zp = toZipPath(child.name);
+ if (filter == null || filter.accept(zp))
+ list.add(zp);
+ child = child.sibling;
+ }
+ return list.iterator();
+ } finally {
+ endWrite();
+ }
+ }
+
+ void createDirectory(byte[] dir, FileAttribute<?>... attrs)
+ throws IOException
+ {
+ checkWritable();
+ dir = toDirectoryPath(dir);
+ beginWrite();
+ try {
+ ensureOpen();
+ if (dir.length == 0 || exists(dir)) // root dir, or exiting dir
+ throw new FileAlreadyExistsException(getString(dir));
+ checkParents(dir);
+ Entry e = new Entry(dir, Entry.NEW);
+ e.method = METHOD_STORED; // STORED for dir
+ update(e);
+ } finally {
+ endWrite();
+ }
+ }
+
+ void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options)
+ throws IOException
+ {
+ checkWritable();
+ if (Arrays.equals(src, dst))
+ return; // do nothing, src and dst are the same
+
+ beginWrite();
+ try {
+ ensureOpen();
+ Entry eSrc = getEntry0(src); // ensureOpen checked
+ if (eSrc == null)
+ throw new NoSuchFileException(getString(src));
+ if (eSrc.isDir()) { // spec says to create dst dir
+ createDirectory(dst);
+ return;
+ }
+ boolean hasReplace = false;
+ boolean hasCopyAttrs = false;
+ for (CopyOption opt : options) {
+ if (opt == REPLACE_EXISTING)
+ hasReplace = true;
+ else if (opt == COPY_ATTRIBUTES)
+ hasCopyAttrs = true;
+ }
+ Entry eDst = getEntry0(dst);
+ if (eDst != null) {
+ if (!hasReplace)
+ throw new FileAlreadyExistsException(getString(dst));
+ } else {
+ checkParents(dst);
+ }
+ Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
+ u.name(dst); // change name
+ if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
+ {
+ u.type = eSrc.type; // make it the same type
+ if (deletesrc) { // if it's a "rename", take the data
+ u.bytes = eSrc.bytes;
+ u.file = eSrc.file;
+ } else { // if it's not "rename", copy the data
+ if (eSrc.bytes != null)
+ u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
+ else if (eSrc.file != null) {
+ u.file = getTempPathForEntry(null);
+ Files.copy(eSrc.file, u.file, REPLACE_EXISTING);
+ }
+ }
+ }
+ if (!hasCopyAttrs)
+ u.mtime = u.atime= u.ctime = System.currentTimeMillis();
+ update(u);
+ if (deletesrc)
+ updateDelete(eSrc);
+ } finally {
+ endWrite();
+ }
+ }
+
+ // Returns an output stream for writing the contents into the specified
+ // entry.
+ OutputStream newOutputStream(byte[] path, OpenOption... options)
+ throws IOException
+ {
+ checkWritable();
+ boolean hasCreateNew = false;
+ boolean hasCreate = false;
+ boolean hasAppend = false;
+ for (OpenOption opt: options) {
+ if (opt == READ)
+ throw new IllegalArgumentException("READ not allowed");
+ if (opt == CREATE_NEW)
+ hasCreateNew = true;
+ if (opt == CREATE)
+ hasCreate = true;
+ if (opt == APPEND)
+ hasAppend = true;
+ }
+ beginRead(); // only need a readlock, the "update()" will
+ try { // try to obtain a writelock when the os is
+ ensureOpen(); // being closed.
+ Entry e = getEntry0(path);
+ if (e != null) {
+ if (e.isDir() || hasCreateNew)
+ throw new FileAlreadyExistsException(getString(path));
+ if (hasAppend) {
+ InputStream is = getInputStream(e);
+ OutputStream os = getOutputStream(new Entry(e, Entry.NEW));
+ copyStream(is, os);
+ is.close();
+ return os;
+ }
+ return getOutputStream(new Entry(e, Entry.NEW));
+ } else {
+ if (!hasCreate && !hasCreateNew)
+ throw new NoSuchFileException(getString(path));
+ checkParents(path);
+ return getOutputStream(new Entry(path, Entry.NEW));
+ }
+ } finally {
+ endRead();
+ }
+ }
+
+ // Returns an input stream for reading the contents of the specified
+ // file entry.
+ InputStream newInputStream(byte[] path) throws IOException {
+ beginRead();
+ try {
+ ensureOpen();
+ Entry e = getEntry0(path);
+ if (e == null)
+ throw new NoSuchFileException(getString(path));
+ if (e.isDir())
+ throw new FileSystemException(getString(path), "is a directory", null);
+ return getInputStream(e);
+ } finally {
+ endRead();
+ }
+ }
+
+ private void checkOptions(Set<? extends OpenOption> options) {
+ // check for options of null type and option is an intance of StandardOpenOption
+ for (OpenOption option : options) {
+ if (option == null)
+ throw new NullPointerException();
+ if (!(option instanceof StandardOpenOption))
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // Returns a Writable/ReadByteChannel for now. Might consdier to use
+ // newFileChannel() instead, which dump the entry data into a regular
+ // file on the default file system and create a FileChannel on top of
+ // it.
+ SeekableByteChannel newByteChannel(byte[] path,
+ Set<? extends OpenOption> options,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ checkOptions(options);
+ if (options.contains(StandardOpenOption.WRITE) ||
+ options.contains(StandardOpenOption.APPEND)) {
+ checkWritable();
+ beginRead();
+ try {
+ final WritableByteChannel wbc = Channels.newChannel(
+ newOutputStream(path, options.toArray(new OpenOption[0])));
+ long leftover = 0;
+ if (options.contains(StandardOpenOption.APPEND)) {
+ Entry e = getEntry0(path);
+ if (e != null && e.size >= 0)
+ leftover = e.size;
+ }
+ final long offset = leftover;
+ return new SeekableByteChannel() {
+ long written = offset;
+ public boolean isOpen() {
+ return wbc.isOpen();
+ }
+
+ public long position() throws IOException {
+ return written;
+ }
+
+ public SeekableByteChannel position(long pos)
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int read(ByteBuffer dst) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public SeekableByteChannel truncate(long size)
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int write(ByteBuffer src) throws IOException {
+ int n = wbc.write(src);
+ written += n;
+ return n;
+ }
+
+ public long size() throws IOException {
+ return written;
+ }
+
+ public void close() throws IOException {
+ wbc.close();
+ }
+ };
+ } finally {
+ endRead();
+ }
+ } else {
+ beginRead();
+ try {
+ ensureOpen();
+ Entry e = getEntry0(path);
+ if (e == null || e.isDir())
+ throw new NoSuchFileException(getString(path));
+ final ReadableByteChannel rbc =
+ Channels.newChannel(getInputStream(e));
+ final long size = e.size;
+ return new SeekableByteChannel() {
+ long read = 0;
+ public boolean isOpen() {
+ return rbc.isOpen();
+ }
+
+ public long position() throws IOException {
+ return read;
+ }
+
+ public SeekableByteChannel position(long pos)
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int read(ByteBuffer dst) throws IOException {
+ int n = rbc.read(dst);
+ if (n > 0) {
+ read += n;
+ }
+ return n;
+ }
+
+ public SeekableByteChannel truncate(long size)
+ throws IOException
+ {
+ throw new NonWritableChannelException();
+ }
+
+ public int write (ByteBuffer src) throws IOException {
+ throw new NonWritableChannelException();
+ }
+
+ public long size() throws IOException {
+ return size;
+ }
+
+ public void close() throws IOException {
+ rbc.close();
+ }
+ };
+ } finally {
+ endRead();
+ }
+ }
+ }
+
+ // Returns a FileChannel of the specified entry.
+ //
+ // This implementation creates a temporary file on the default file system,
+ // copy the entry data into it if the entry exists, and then create a
+ // FileChannel on top of it.
+ FileChannel newFileChannel(byte[] path,
+ Set<? extends OpenOption> options,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ checkOptions(options);
+ final boolean forWrite = (options.contains(StandardOpenOption.WRITE) ||
+ options.contains(StandardOpenOption.APPEND));
+ beginRead();
+ try {
+ ensureOpen();
+ Entry e = getEntry0(path);
+ if (forWrite) {
+ checkWritable();
+ if (e == null) {
+ if (!options.contains(StandardOpenOption.CREATE_NEW))
+ throw new NoSuchFileException(getString(path));
+ } else {
+ if (options.contains(StandardOpenOption.CREATE_NEW))
+ throw new FileAlreadyExistsException(getString(path));
+ if (e.isDir())
+ throw new FileAlreadyExistsException("directory <"
+ + getString(path) + "> exists");
+ }
+ options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile
+ } else if (e == null || e.isDir()) {
+ throw new NoSuchFileException(getString(path));
+ }
+
+ final boolean isFCH = (e != null && e.type == Entry.FILECH);
+ final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path);
+ final FileChannel fch = tmpfile.getFileSystem()
+ .provider()
+ .newFileChannel(tmpfile, options, attrs);
+ final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
+ if (forWrite) {
+ u.flag = FLAG_DATADESCR;
+ u.method = METHOD_DEFLATED;
+ }
+ // is there a better way to hook into the FileChannel's close method?
+ return new FileChannel() {
+ public int write(ByteBuffer src) throws IOException {
+ return fch.write(src);
+ }
+ public long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException
+ {
+ return fch.write(srcs, offset, length);
+ }
+ public long position() throws IOException {
+ return fch.position();
+ }
+ public FileChannel position(long newPosition)
+ throws IOException
+ {
+ fch.position(newPosition);
+ return this;
+ }
+ public long size() throws IOException {
+ return fch.size();
+ }
+ public FileChannel truncate(long size)
+ throws IOException
+ {
+ fch.truncate(size);
+ return this;
+ }
+ public void force(boolean metaData)
+ throws IOException
+ {
+ fch.force(metaData);
+ }
+ public long transferTo(long position, long count,
+ WritableByteChannel target)
+ throws IOException
+ {
+ return fch.transferTo(position, count, target);
+ }
+ public long transferFrom(ReadableByteChannel src,
+ long position, long count)
+ throws IOException
+ {
+ return fch.transferFrom(src, position, count);
+ }
+ public int read(ByteBuffer dst) throws IOException {
+ return fch.read(dst);
+ }
+ public int read(ByteBuffer dst, long position)
+ throws IOException
+ {
+ return fch.read(dst, position);
+ }
+ public long read(ByteBuffer[] dsts, int offset, int length)
+ throws IOException
+ {
+ return fch.read(dsts, offset, length);
+ }
+ public int write(ByteBuffer src, long position)
+ throws IOException
+ {
+ return fch.write(src, position);
+ }
+ public MappedByteBuffer map(MapMode mode,
+ long position, long size)
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+ public FileLock lock(long position, long size, boolean shared)
+ throws IOException
+ {
+ return fch.lock(position, size, shared);
+ }
+ public FileLock tryLock(long position, long size, boolean shared)
+ throws IOException
+ {
+ return fch.tryLock(position, size, shared);
+ }
+ protected void implCloseChannel() throws IOException {
+ fch.close();
+ if (forWrite) {
+ u.mtime = System.currentTimeMillis();
+ u.size = Files.size(u.file);
+
+ update(u);
+ } else {
+ if (!isFCH) // if this is a new fch for reading
+ removeTempPathForEntry(tmpfile);
+ }
+ }
+ };
+ } finally {
+ endRead();
+ }
+ }
+
+ // the outstanding input streams that need to be closed
+ private Set<InputStream> streams =
+ Collections.synchronizedSet(new HashSet<InputStream>());
+
+ // the ex-channel and ex-path that need to close when their outstanding
+ // input streams are all closed by the obtainers.
+ private Set<ExChannelCloser> exChClosers = new HashSet<>();
+
+ private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
+ private Path getTempPathForEntry(byte[] path) throws IOException {
+ Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
+ if (path != null) {
+ Entry e = getEntry0(path);
+ if (e != null) {
+ try (InputStream is = newInputStream(path)) {
+ Files.copy(is, tmpPath, REPLACE_EXISTING);
+ }
+ }
+ }
+ return tmpPath;
+ }
+
+ private void removeTempPathForEntry(Path path) throws IOException {
+ Files.delete(path);
+ tmppaths.remove(path);
+ }
+
+ // check if all parents really exit. ZIP spec does not require
+ // the existence of any "parent directory".
+ private void checkParents(byte[] path) throws IOException {
+ beginRead();
+ try {
+ while ((path = getParent(path)) != null && path.length != 0) {
+ if (!inodes.containsKey(IndexNode.keyOf(path))) {
+ throw new NoSuchFileException(getString(path));
+ }
+ }
+ } finally {
+ endRead();
+ }
+ }
+
+ private static byte[] ROOTPATH = new byte[0];
+ private static byte[] getParent(byte[] path) {
+ int off = path.length - 1;
+ if (off > 0 && path[off] == '/') // isDirectory
+ off--;
+ while (off > 0 && path[off] != '/') { off--; }
+ if (off <= 0)
+ return ROOTPATH;
+ return Arrays.copyOf(path, off + 1);
+ }
+
+ private final void beginWrite() {
+ rwlock.writeLock().lock();
+ }
+
+ private final void endWrite() {
+ rwlock.writeLock().unlock();
+ }
+
+ private final void beginRead() {
+ rwlock.readLock().lock();
+ }
+
+ private final void endRead() {
+ rwlock.readLock().unlock();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+
+ private volatile boolean isOpen = true;
+ private final SeekableByteChannel ch; // channel to the zipfile
+ final byte[] cen; // CEN & ENDHDR
+ private END end;
+ private long locpos; // position of first LOC header (usually 0)
+
+ private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
+
+ // name -> pos (in cen), IndexNode itself can be used as a "key"
+ private LinkedHashMap<IndexNode, IndexNode> inodes;
+
+ final byte[] getBytes(String name) {
+ return zc.getBytes(name);
+ }
+
+ final String getString(byte[] name) {
+ return zc.toString(name);
+ }
+
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ private long getDataPos(Entry e) throws IOException {
+ if (e.locoff == -1) {
+ Entry e2 = getEntry0(e.name);
+ if (e2 == null)
+ throw new ZipException("invalid loc for entry <" + e.name + ">");
+ e.locoff = e2.locoff;
+ }
+ byte[] buf = new byte[LOCHDR];
+ if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length)
+ throw new ZipException("invalid loc for entry <" + e.name + ">");
+ return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf);
+ }
+
+ // Reads len bytes of data from the specified offset into buf.
+ // Returns the total number of bytes read.
+ // Each/every byte read from here (except the cen, which is mapped).
+ final long readFullyAt(byte[] buf, int off, long len, long pos)
+ throws IOException
+ {
+ ByteBuffer bb = ByteBuffer.wrap(buf);
+ bb.position(off);
+ bb.limit((int)(off + len));
+ return readFullyAt(bb, pos);
+ }
+
+ private final long readFullyAt(ByteBuffer bb, long pos)
+ throws IOException
+ {
+ synchronized(ch) {
+ return ch.position(pos).read(bb);
+ }
+ }
+
+ // Searches for end of central directory (END) header. The contents of
+ // the END header will be read and placed in endbuf. Returns the file
+ // position of the END header, otherwise returns -1 if the END header
+ // was not found or an error occurred.
+ private END findEND() throws IOException
+ {
+ byte[] buf = new byte[READBLOCKSZ];
+ long ziplen = ch.size();
+ long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
+ long minPos = minHDR - (buf.length - ENDHDR);
+
+ for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR))
+ {
+ int off = 0;
+ if (pos < 0) {
+ // Pretend there are some NUL bytes before start of file
+ off = (int)-pos;
+ Arrays.fill(buf, 0, off, (byte)0);
+ }
+ int len = buf.length - off;
+ if (readFullyAt(buf, off, len, pos + off) != len)
+ zerror("zip END header not found");
+
+ // Now scan the block backwards for END header signature
+ for (int i = buf.length - ENDHDR; i >= 0; i--) {
+ if (buf[i+0] == (byte)'P' &&
+ buf[i+1] == (byte)'K' &&
+ buf[i+2] == (byte)'\005' &&
+ buf[i+3] == (byte)'\006' &&
+ (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) {
+ // Found END header
+ buf = Arrays.copyOfRange(buf, i, i + ENDHDR);
+ END end = new END();
+ end.endsub = ENDSUB(buf);
+ end.centot = ENDTOT(buf);
+ end.cenlen = ENDSIZ(buf);
+ end.cenoff = ENDOFF(buf);
+ end.comlen = ENDCOM(buf);
+ end.endpos = pos + i;
+ if (end.cenlen == ZIP64_MINVAL ||
+ end.cenoff == ZIP64_MINVAL ||
+ end.centot == ZIP64_MINVAL32)
+ {
+ // need to find the zip64 end;
+ byte[] loc64 = new byte[ZIP64_LOCHDR];
+ if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
+ != loc64.length) {
+ return end;
+ }
+ long end64pos = ZIP64_LOCOFF(loc64);
+ byte[] end64buf = new byte[ZIP64_ENDHDR];
+ if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
+ != end64buf.length) {
+ return end;
+ }
+ // end64 found, re-calcualte everything.
+ end.cenlen = ZIP64_ENDSIZ(end64buf);
+ end.cenoff = ZIP64_ENDOFF(end64buf);
+ end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
+ end.endpos = end64pos;
+ }
+ return end;
+ }
+ }
+ }
+ zerror("zip END header not found");
+ return null; //make compiler happy
+ }
+
+ // Reads zip file central directory. Returns the file position of first
+ // CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
+ // then the error was a zip format error and zip->msg has the error text.
+ // Always pass in -1 for knownTotal; it's used for a recursive call.
+ private byte[] initCEN() throws IOException {
+ end = findEND();
+ if (end.endpos == 0) {
+ inodes = new LinkedHashMap<>(10);
+ locpos = 0;
+ buildNodeTree();
+ return null; // only END header present
+ }
+ if (end.cenlen > end.endpos)
+ zerror("invalid END header (bad central directory size)");
+ long cenpos = end.endpos - end.cenlen; // position of CEN table
+
+ // Get position of first local file (LOC) header, taking into
+ // account that there may be a stub prefixed to the zip file.
+ locpos = cenpos - end.cenoff;
+ if (locpos < 0)
+ zerror("invalid END header (bad central directory offset)");
+
+ // read in the CEN and END
+ byte[] cen = new byte[(int)(end.cenlen + ENDHDR)];
+ if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
+ zerror("read CEN tables failed");
+ }
+ // Iterate through the entries in the central directory
+ inodes = new LinkedHashMap<>(end.centot + 1);
+ int pos = 0;
+ int limit = cen.length - ENDHDR;
+ while (pos < limit) {
+ if (CENSIG(cen, pos) != CENSIG)
+ zerror("invalid CEN header (bad signature)");
+ int method = CENHOW(cen, pos);
+ int nlen = CENNAM(cen, pos);
+ int elen = CENEXT(cen, pos);
+ int clen = CENCOM(cen, pos);
+ if ((CENFLG(cen, pos) & 1) != 0)
+ zerror("invalid CEN header (encrypted entry)");
+ if (method != METHOD_STORED && method != METHOD_DEFLATED)
+ zerror("invalid CEN header (unsupported compression method: " + method + ")");
+ if (pos + CENHDR + nlen > limit)
+ zerror("invalid CEN header (bad header size)");
+ byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen);
+ IndexNode inode = new IndexNode(name, pos);
+ inodes.put(inode, inode);
+ // skip ext and comment
+ pos += (CENHDR + nlen + elen + clen);
+ }
+ if (pos + ENDHDR != cen.length) {
+ zerror("invalid CEN header (bad header size)");
+ }
+ buildNodeTree();
+ return cen;
+ }
+
+ private void ensureOpen() throws IOException {
+ if (!isOpen)
+ throw new ClosedFileSystemException();
+ }
+
+ // Creates a new empty temporary file in the same directory as the
+ // specified file. A variant of Files.createTempFile.
+ private Path createTempFileInSameDirectoryAs(Path path)
+ throws IOException
+ {
+ Path parent = path.toAbsolutePath().getParent();
+ Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+ Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
+ tmppaths.add(tmpPath);
+ return tmpPath;
+ }
+
+ ////////////////////update & sync //////////////////////////////////////
+
+ private boolean hasUpdate = false;
+
+ // shared key. consumer guarantees the "writeLock" before use it.
+ private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
+
+ private void updateDelete(IndexNode inode) {
+ beginWrite();
+ try {
+ removeFromTree(inode);
+ inodes.remove(inode);
+ hasUpdate = true;
+ } finally {
+ endWrite();
+ }
+ }
+
+ private void update(Entry e) {
+ beginWrite();
+ try {
+ IndexNode old = inodes.put(e, e);
+ if (old != null) {
+ removeFromTree(old);
+ }
+ if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
+ IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
+ e.sibling = parent.child;
+ parent.child = e;
+ }
+ hasUpdate = true;
+ } finally {
+ endWrite();
+ }
+ }
+
+ // copy over the whole LOC entry (header if necessary, data and ext) from
+ // old zip to the new one.
+ private long copyLOCEntry(Entry e, boolean updateHeader,
+ OutputStream os,
+ long written, byte[] buf)
+ throws IOException
+ {
+ long locoff = e.locoff; // where to read
+ e.locoff = written; // update the e.locoff with new value
+
+ // calculate the size need to write out
+ long size = 0;
+ // if there is A ext
+ if ((e.flag & FLAG_DATADESCR) != 0) {
+ if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL)
+ size = 24;
+ else
+ size = 16;
+ }
+ // read loc, use the original loc.elen/nlen
+ if (readFullyAt(buf, 0, LOCHDR , locoff) != LOCHDR)
+ throw new ZipException("loc: reading failed");
+ if (updateHeader) {
+ locoff += LOCHDR + LOCNAM(buf) + LOCEXT(buf); // skip header
+ size += e.csize;
+ written = e.writeLOC(os) + size;
+ } else {
+ os.write(buf, 0, LOCHDR); // write out the loc header
+ locoff += LOCHDR;
+ // use e.csize, LOCSIZ(buf) is zero if FLAG_DATADESCR is on
+ // size += LOCNAM(buf) + LOCEXT(buf) + LOCSIZ(buf);
+ size += LOCNAM(buf) + LOCEXT(buf) + e.csize;
+ written = LOCHDR + size;
+ }
+ int n;
+ while (size > 0 &&
+ (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
+ {
+ if (size < n)
+ n = (int)size;
+ os.write(buf, 0, n);
+ size -= n;
+ locoff += n;
+ }
+ return written;
+ }
+
+ // sync the zip file system, if there is any udpate
+ private void sync() throws IOException {
+ //System.out.printf("->sync(%s) starting....!%n", toString());
+ // check ex-closer
+ if (!exChClosers.isEmpty()) {
+ for (ExChannelCloser ecc : exChClosers) {
+ if (ecc.streams.isEmpty()) {
+ ecc.ch.close();
+ Files.delete(ecc.path);
+ exChClosers.remove(ecc);
+ }
+ }
+ }
+ if (!hasUpdate)
+ return;
+ Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
+ try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
+ {
+ ArrayList<Entry> elist = new ArrayList<>(inodes.size());
+ long written = 0;
+ byte[] buf = new byte[8192];
+ Entry e = null;
+
+ // write loc
+ for (IndexNode inode : inodes.values()) {
+ if (inode instanceof Entry) { // an updated inode
+ e = (Entry)inode;
+ try {
+ if (e.type == Entry.COPY) {
+ // entry copy: the only thing changed is the "name"
+ // and "nlen" in LOC header, so we udpate/rewrite the
+ // LOC in new file and simply copy the rest (data and
+ // ext) without enflating/deflating from the old zip
+ // file LOC entry.
+ written += copyLOCEntry(e, true, os, written, buf);
+ } else { // NEW, FILECH or CEN
+ e.locoff = written;
+ written += e.writeLOC(os); // write loc header
+ if (e.bytes != null) { // in-memory, deflated
+ os.write(e.bytes); // already
+ written += e.bytes.length;
+ } else if (e.file != null) { // tmp file
+ try (InputStream is = Files.newInputStream(e.file)) {
+ int n;
+ if (e.type == Entry.NEW) { // deflated already
+ while ((n = is.read(buf)) != -1) {
+ os.write(buf, 0, n);
+ written += n;
+ }
+ } else if (e.type == Entry.FILECH) {
+ // the data are not deflated, use ZEOS
+ try (OutputStream os2 = new EntryOutputStream(e, os)) {
+ while ((n = is.read(buf)) != -1) {
+ os2.write(buf, 0, n);
+ }
+ }
+ written += e.csize;
+ if ((e.flag & FLAG_DATADESCR) != 0)
+ written += e.writeEXT(os);
+ }
+ }
+ Files.delete(e.file);
+ tmppaths.remove(e.file);
+ } else {
+ // dir, 0-length data
+ }
+ }
+ elist.add(e);
+ } catch (IOException x) {
+ x.printStackTrace(); // skip any in-accurate entry
+ }
+ } else { // unchanged inode
+ if (inode.pos == -1) {
+ continue; // pseudo directory node
+ }
+ e = Entry.readCEN(this, inode.pos);
+ try {
+ written += copyLOCEntry(e, false, os, written, buf);
+ elist.add(e);
+ } catch (IOException x) {
+ x.printStackTrace(); // skip any wrong entry
+ }
+ }
+ }
+
+ // now write back the cen and end table
+ end.cenoff = written;
+ for (Entry entry : elist) {
+ written += entry.writeCEN(os);
+ }
+ end.centot = elist.size();
+ end.cenlen = written - end.cenoff;
+ end.write(os, written);
+ }
+ if (!streams.isEmpty()) {
+ //
+ // TBD: ExChannelCloser should not be necessary if we only
+ // sync when being closed, all streams should have been
+ // closed already. Keep the logic here for now.
+ //
+ // There are outstanding input streams open on existing "ch",
+ // so, don't close the "cha" and delete the "file for now, let
+ // the "ex-channel-closer" to handle them
+ ExChannelCloser ecc = new ExChannelCloser(
+ createTempFileInSameDirectoryAs(zfpath),
+ ch,
+ streams);
+ Files.move(zfpath, ecc.path, REPLACE_EXISTING);
+ exChClosers.add(ecc);
+ streams = Collections.synchronizedSet(new HashSet<InputStream>());
+ } else {
+ ch.close();
+ Files.delete(zfpath);
+ }
+
+ Files.move(tmpFile, zfpath, REPLACE_EXISTING);
+ hasUpdate = false; // clear
+ /*
+ if (isOpen) {
+ ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen"
+ cen = initCEN();
+ }
+ */
+ //System.out.printf("->sync(%s) done!%n", toString());
+ }
+
+ private IndexNode getInode(byte[] path) {
+ if (path == null)
+ throw new NullPointerException("path");
+ IndexNode key = IndexNode.keyOf(path);
+ IndexNode inode = inodes.get(key);
+ if (inode == null &&
+ (path.length == 0 || path[path.length -1] != '/')) {
+ // if does not ends with a slash
+ path = Arrays.copyOf(path, path.length + 1);
+ path[path.length - 1] = '/';
+ inode = inodes.get(key.as(path));
+ }
+ return inode;
+ }
+
+ private Entry getEntry0(byte[] path) throws IOException {
+ IndexNode inode = getInode(path);
+ if (inode instanceof Entry)
+ return (Entry)inode;
+ if (inode == null || inode.pos == -1)
+ return null;
+ return Entry.readCEN(this, inode.pos);
+ }
+
+ public void deleteFile(byte[] path, boolean failIfNotExists)
+ throws IOException
+ {
+ checkWritable();
+
+ IndexNode inode = getInode(path);
+ if (inode == null) {
+ if (path != null && path.length == 0)
+ throw new ZipException("root directory </> can't not be delete");
+ if (failIfNotExists)
+ throw new NoSuchFileException(getString(path));
+ } else {
+ if (inode.isDir() && inode.child != null)
+ throw new DirectoryNotEmptyException(getString(path));
+ updateDelete(inode);
+ }
+ }
+
+ private static void copyStream(InputStream is, OutputStream os)
+ throws IOException
+ {
+ byte[] copyBuf = new byte[8192];
+ int n;
+ while ((n = is.read(copyBuf)) != -1) {
+ os.write(copyBuf, 0, n);
+ }
+ }
+
+ // Returns an out stream for either
+ // (1) writing the contents of a new entry, if the entry exits, or
+ // (2) updating/replacing the contents of the specified existing entry.
+ private OutputStream getOutputStream(Entry e) throws IOException {
+
+ if (e.mtime == -1)
+ e.mtime = System.currentTimeMillis();
+ if (e.method == -1)
+ e.method = METHOD_DEFLATED; // TBD: use default method
+ // store size, compressed size, and crc-32 in LOC header
+ e.flag = 0;
+ if (zc.isUTF8())
+ e.flag |= FLAG_EFS;
+ OutputStream os;
+ if (useTempFile) {
+ e.file = getTempPathForEntry(null);
+ os = Files.newOutputStream(e.file, WRITE);
+ } else {
+ os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
+ }
+ return new EntryOutputStream(e, os);
+ }
+
+ private InputStream getInputStream(Entry e)
+ throws IOException
+ {
+ InputStream eis = null;
+
+ if (e.type == Entry.NEW) {
+ if (e.bytes != null)
+ eis = new ByteArrayInputStream(e.bytes);
+ else if (e.file != null)
+ eis = Files.newInputStream(e.file);
+ else
+ throw new ZipException("update entry data is missing");
+ } else if (e.type == Entry.FILECH) {
+ // FILECH result is un-compressed.
+ eis = Files.newInputStream(e.file);
+ // TBD: wrap to hook close()
+ // streams.add(eis);
+ return eis;
+ } else { // untouced CEN or COPY
+ eis = new EntryInputStream(e, ch);
+ }
+ if (e.method == METHOD_DEFLATED) {
+ // MORE: Compute good size for inflater stream:
+ long bufSize = e.size + 2; // Inflater likes a bit of slack
+ if (bufSize > 65536)
+ bufSize = 8192;
+ final long size = e.size;
+ eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) {
+
+ private boolean isClosed = false;
+ public void close() throws IOException {
+ if (!isClosed) {
+ releaseInflater(inf);
+ this.in.close();
+ isClosed = true;
+ streams.remove(this);
+ }
+ }
+ // Override fill() method to provide an extra "dummy" byte
+ // at the end of the input stream. This is required when
+ // using the "nowrap" Inflater option. (it appears the new
+ // zlib in 7 does not need it, but keep it for now)
+ protected void fill() throws IOException {
+ if (eof) {
+ throw new EOFException(
+ "Unexpected end of ZLIB input stream");
+ }
+ len = this.in.read(buf, 0, buf.length);
+ if (len == -1) {
+ buf[0] = 0;
+ len = 1;
+ eof = true;
+ }
+ inf.setInput(buf, 0, len);
+ }
+ private boolean eof;
+
+ public int available() throws IOException {
+ if (isClosed)
+ return 0;
+ long avail = size - inf.getBytesWritten();
+ return avail > (long) Integer.MAX_VALUE ?
+ Integer.MAX_VALUE : (int) avail;
+ }
+ };
+ } else if (e.method == METHOD_STORED) {
+ // TBD: wrap/ it does not seem necessary
+ } else {
+ throw new ZipException("invalid compression method");
+ }
+ streams.add(eis);
+ return eis;
+ }
+
+ // Inner class implementing the input stream used to read
+ // a (possibly compressed) zip file entry.
+ private class EntryInputStream extends InputStream {
+ private final SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might
+ // point to a new channel after sync()
+ private long pos; // current position within entry data
+ protected long rem; // number of remaining bytes within entry
+ protected final long size; // uncompressed size of this entry
+
+ EntryInputStream(Entry e, SeekableByteChannel zfch)
+ throws IOException
+ {
+ this.zfch = zfch;
+ rem = e.csize;
+ size = e.size;
+ pos = getDataPos(e);
+ }
+ public int read(byte b[], int off, int len) throws IOException {
+ ensureOpen();
+ if (rem == 0) {
+ return -1;
+ }
+ if (len <= 0) {
+ return 0;
+ }
+ if (len > rem) {
+ len = (int) rem;
+ }
+ // readFullyAt()
+ long n = 0;
+ ByteBuffer bb = ByteBuffer.wrap(b);
+ bb.position(off);
+ bb.limit(off + len);
+ synchronized(zfch) {
+ n = zfch.position(pos).read(bb);
+ }
+ if (n > 0) {
+ pos += n;
+ rem -= n;
+ }
+ if (rem == 0) {
+ close();
+ }
+ return (int)n;
+ }
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ if (read(b, 0, 1) == 1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+ public long skip(long n) throws IOException {
+ ensureOpen();
+ if (n > rem)
+ n = rem;
+ pos += n;
+ rem -= n;
+ if (rem == 0) {
+ close();
+ }
+ return n;
+ }
+ public int available() {
+ return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
+ }
+ public long size() {
+ return size;
+ }
+ public void close() {
+ rem = 0;
+ streams.remove(this);
+ }
+ }
+
+ class EntryOutputStream extends DeflaterOutputStream
+ {
+ private CRC32 crc;
+ private Entry e;
+ private long written;
+
+ EntryOutputStream(Entry e, OutputStream os)
+ throws IOException
+ {
+ super(os, getDeflater());
+ if (e == null)
+ throw new NullPointerException("Zip entry is null");
+ this.e = e;
+ crc = new CRC32();
+ }
+
+ @Override
+ public void write(byte b[], int off, int len) throws IOException {
+ if (e.type != Entry.FILECH) // only from sync
+ ensureOpen();
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+ switch (e.method) {
+ case METHOD_DEFLATED:
+ super.write(b, off, len);
+ break;
+ case METHOD_STORED:
+ written += len;
+ out.write(b, off, len);
+ break;
+ default:
+ throw new ZipException("invalid compression method");
+ }
+ crc.update(b, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // TBD ensureOpen();
+ switch (e.method) {
+ case METHOD_DEFLATED:
+ finish();
+ e.size = def.getBytesRead();
+ e.csize = def.getBytesWritten();
+ e.crc = crc.getValue();
+ break;
+ case METHOD_STORED:
+ // we already know that both e.size and e.csize are the same
+ e.size = e.csize = written;
+ e.crc = crc.getValue();
+ break;
+ default:
+ throw new ZipException("invalid compression method");
+ }
+ //crc.reset();
+ if (out instanceof ByteArrayOutputStream)
+ e.bytes = ((ByteArrayOutputStream)out).toByteArray();
+
+ if (e.type == Entry.FILECH) {
+ releaseDeflater(def);
+ return;
+ }
+ super.close();
+ releaseDeflater(def);
+ update(e);
+ }
+ }
+
+ static void zerror(String msg) {
+ throw new ZipError(msg);
+ }
+
+ // Maxmum number of de/inflater we cache
+ private final int MAX_FLATER = 20;
+ // List of available Inflater objects for decompression
+ private final List<Inflater> inflaters = new ArrayList<>();
+
+ // Gets an inflater from the list of available inflaters or allocates
+ // a new one.
+ private Inflater getInflater() {
+ synchronized (inflaters) {
+ int size = inflaters.size();
+ if (size > 0) {
+ Inflater inf = inflaters.remove(size - 1);
+ return inf;
+ } else {
+ return new Inflater(true);
+ }
+ }
+ }
+
+ // Releases the specified inflater to the list of available inflaters.
+ private void releaseInflater(Inflater inf) {
+ synchronized (inflaters) {
+ if (inflaters.size() < MAX_FLATER) {
+ inf.reset();
+ inflaters.add(inf);
+ } else {
+ inf.end();
+ }
+ }
+ }
+
+ // List of available Deflater objects for compression
+ private final List<Deflater> deflaters = new ArrayList<>();
+
+ // Gets an deflater from the list of available deflaters or allocates
+ // a new one.
+ private Deflater getDeflater() {
+ synchronized (deflaters) {
+ int size = deflaters.size();
+ if (size > 0) {
+ Deflater def = deflaters.remove(size - 1);
+ return def;
+ } else {
+ return new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+ }
+ }
+ }
+
+ // Releases the specified inflater to the list of available inflaters.
+ private void releaseDeflater(Deflater def) {
+ synchronized (deflaters) {
+ if (inflaters.size() < MAX_FLATER) {
+ def.reset();
+ deflaters.add(def);
+ } else {
+ def.end();
+ }
+ }
+ }
+
+ // End of central directory record
+ static class END {
+ int disknum;
+ int sdisknum;
+ int endsub; // endsub
+ int centot; // 4 bytes
+ long cenlen; // 4 bytes
+ long cenoff; // 4 bytes
+ int comlen; // comment length
+ byte[] comment;
+
+ /* members of Zip64 end of central directory locator */
+ int diskNum;
+ long endpos;
+ int disktot;
+
+ void write(OutputStream os, long offset) throws IOException {
+ boolean hasZip64 = false;
+ long xlen = cenlen;
+ long xoff = cenoff;
+ if (xlen >= ZIP64_MINVAL) {
+ xlen = ZIP64_MINVAL;
+ hasZip64 = true;
+ }
+ if (xoff >= ZIP64_MINVAL) {
+ xoff = ZIP64_MINVAL;
+ hasZip64 = true;
+ }
+ int count = centot;
+ if (count >= ZIP64_MINVAL32) {
+ count = ZIP64_MINVAL32;
+ hasZip64 = true;
+ }
+ if (hasZip64) {
+ long off64 = offset;
+ //zip64 end of central directory record
+ writeInt(os, ZIP64_ENDSIG); // zip64 END record signature
+ writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end
+ writeShort(os, 45); // version made by
+ writeShort(os, 45); // version needed to extract
+ writeInt(os, 0); // number of this disk
+ writeInt(os, 0); // central directory start disk
+ writeLong(os, centot); // number of directory entires on disk
+ writeLong(os, centot); // number of directory entires
+ writeLong(os, cenlen); // length of central directory
+ writeLong(os, cenoff); // offset of central directory
+
+ //zip64 end of central directory locator
+ writeInt(os, ZIP64_LOCSIG); // zip64 END locator signature
+ writeInt(os, 0); // zip64 END start disk
+ writeLong(os, off64); // offset of zip64 END
+ writeInt(os, 1); // total number of disks (?)
+ }
+ writeInt(os, ENDSIG); // END record signature
+ writeShort(os, 0); // number of this disk
+ writeShort(os, 0); // central directory start disk
+ writeShort(os, count); // number of directory entries on disk
+ writeShort(os, count); // total number of directory entries
+ writeInt(os, xlen); // length of central directory
+ writeInt(os, xoff); // offset of central directory
+ if (comment != null) { // zip file comment
+ writeShort(os, comment.length);
+ writeBytes(os, comment);
+ } else {
+ writeShort(os, 0);
+ }
+ }
+ }
+
+ // Internal node that links a "name" to its pos in cen table.
+ // The node itself can be used as a "key" to lookup itself in
+ // the HashMap inodes.
+ static class IndexNode {
+ byte[] name;
+ int hashcode; // node is hashable/hashed by its name
+ int pos = -1; // position in cen table, -1 menas the
+ // entry does not exists in zip file
+ IndexNode(byte[] name, int pos) {
+ name(name);
+ this.pos = pos;
+ }
+
+ final static IndexNode keyOf(byte[] name) { // get a lookup key;
+ return new IndexNode(name, -1);
+ }
+
+ final void name(byte[] name) {
+ this.name = name;
+ this.hashcode = Arrays.hashCode(name);
+ }
+
+ final IndexNode as(byte[] name) { // reuse the node, mostly
+ name(name); // as a lookup "key"
+ return this;
+ }
+
+ boolean isDir() {
+ return name != null &&
+ (name.length == 0 || name[name.length - 1] == '/');
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof IndexNode)) {
+ return false;
+ }
+ return Arrays.equals(name, ((IndexNode)other).name);
+ }
+
+ public int hashCode() {
+ return hashcode;
+ }
+
+ IndexNode() {}
+ IndexNode sibling;
+ IndexNode child; // 1st child
+ }
+
+ static class Entry extends IndexNode {
+
+ static final int CEN = 1; // entry read from cen
+ static final int NEW = 2; // updated contents in bytes or file
+ static final int FILECH = 3; // fch update in "file"
+ static final int COPY = 4; // copy of a CEN entry
+
+
+ byte[] bytes; // updated content bytes
+ Path file; // use tmp file to store bytes;
+ int type = CEN; // default is the entry read from cen
+
+ // entry attributes
+ int version;
+ int flag;
+ int method = -1; // compression method
+ long mtime = -1; // last modification time (in DOS time)
+ long atime = -1; // last access time
+ long ctime = -1; // create time
+ long crc = -1; // crc-32 of entry data
+ long csize = -1; // compressed size of entry data
+ long size = -1; // uncompressed size of entry data
+ byte[] extra;
+
+ // cen
+ int versionMade;
+ int disk;
+ int attrs;
+ long attrsEx;
+ long locoff;
+ byte[] comment;
+
+ Entry() {}
+
+ Entry(byte[] name) {
+ name(name);
+ this.mtime = this.ctime = this.atime = System.currentTimeMillis();
+ this.crc = 0;
+ this.size = 0;
+ this.csize = 0;
+ this.method = METHOD_DEFLATED;
+ }
+
+ Entry(byte[] name, int type) {
+ this(name);
+ this.type = type;
+ }
+
+ Entry (Entry e, int type) {
+ name(e.name);
+ this.version = e.version;
+ this.ctime = e.ctime;
+ this.atime = e.atime;
+ this.mtime = e.mtime;
+ this.crc = e.crc;
+ this.size = e.size;
+ this.csize = e.csize;
+ this.method = e.method;
+ this.extra = e.extra;
+ this.versionMade = e.versionMade;
+ this.disk = e.disk;
+ this.attrs = e.attrs;
+ this.attrsEx = e.attrsEx;
+ this.locoff = e.locoff;
+ this.comment = e.comment;
+ this.type = type;
+ }
+
+ Entry (byte[] name, Path file, int type) {
+ this(name, type);
+ this.file = file;
+ this.method = METHOD_STORED;
+ }
+
+ int version() throws ZipException {
+ if (method == METHOD_DEFLATED)
+ return 20;
+ else if (method == METHOD_STORED)
+ return 10;
+ throw new ZipException("unsupported compression method");
+ }
+
+ ///////////////////// CEN //////////////////////
+ static Entry readCEN(ZipFileSystem zipfs, int pos)
+ throws IOException
+ {
+ return new Entry().cen(zipfs, pos);
+ }
+
+ private Entry cen(ZipFileSystem zipfs, int pos)
+ throws IOException
+ {
+ byte[] cen = zipfs.cen;
+ if (CENSIG(cen, pos) != CENSIG)
+ zerror("invalid CEN header (bad signature)");
+ versionMade = CENVEM(cen, pos);
+ version = CENVER(cen, pos);
+ flag = CENFLG(cen, pos);
+ method = CENHOW(cen, pos);
+ mtime = dosToJavaTime(CENTIM(cen, pos));
+ crc = CENCRC(cen, pos);
+ csize = CENSIZ(cen, pos);
+ size = CENLEN(cen, pos);
+ int nlen = CENNAM(cen, pos);
+ int elen = CENEXT(cen, pos);
+ int clen = CENCOM(cen, pos);
+ disk = CENDSK(cen, pos);
+ attrs = CENATT(cen, pos);
+ attrsEx = CENATX(cen, pos);
+ locoff = CENOFF(cen, pos);
+
+ pos += CENHDR;
+ name(Arrays.copyOfRange(cen, pos, pos + nlen));
+
+ pos += nlen;
+ if (elen > 0) {
+ extra = Arrays.copyOfRange(cen, pos, pos + elen);
+ pos += elen;
+ readExtra(zipfs);
+ }
+ if (clen > 0) {
+ comment = Arrays.copyOfRange(cen, pos, pos + clen);
+ }
+ return this;
+ }
+
+ int writeCEN(OutputStream os) throws IOException
+ {
+ int written = CENHDR;
+ int version0 = version();
+ long csize0 = csize;
+ long size0 = size;
+ long locoff0 = locoff;
+ int elen64 = 0; // extra for ZIP64
+ int elenNTFS = 0; // extra for NTFS (a/c/mtime)
+ int elenEXTT = 0; // extra for Extended Timestamp
+ boolean foundExtraTime = false; // if time stamp NTFS, EXTT present
+
+ // confirm size/length
+ int nlen = (name != null) ? name.length : 0;
+ int elen = (extra != null) ? extra.length : 0;
+ int eoff = 0;
+ int clen = (comment != null) ? comment.length : 0;
+ if (csize >= ZIP64_MINVAL) {
+ csize0 = ZIP64_MINVAL;
+ elen64 += 8; // csize(8)
+ }
+ if (size >= ZIP64_MINVAL) {
+ size0 = ZIP64_MINVAL; // size(8)
+ elen64 += 8;
+ }
+ if (locoff >= ZIP64_MINVAL) {
+ locoff0 = ZIP64_MINVAL;
+ elen64 += 8; // offset(8)
+ }
+ if (elen64 != 0) {
+ elen64 += 4; // header and data sz 4 bytes
+ }
+ while (eoff + 4 < elen) {
+ int tag = SH(extra, eoff);
+ int sz = SH(extra, eoff + 2);
+ if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
+ foundExtraTime = true;
+ }
+ eoff += (4 + sz);
+ }
+ if (!foundExtraTime) {
+ if (isWindows) { // use NTFS
+ elenNTFS = 36; // total 36 bytes
+ } else { // Extended Timestamp otherwise
+ elenEXTT = 9; // only mtime in cen
+ }
+ }
+ writeInt(os, CENSIG); // CEN header signature
+ if (elen64 != 0) {
+ writeShort(os, 45); // ver 4.5 for zip64
+ writeShort(os, 45);
+ } else {
+ writeShort(os, version0); // version made by
+ writeShort(os, version0); // version needed to extract
+ }
+ writeShort(os, flag); // general purpose bit flag
+ writeShort(os, method); // compression method
+ // last modification time
+ writeInt(os, (int)javaToDosTime(mtime));
+ writeInt(os, crc); // crc-32
+ writeInt(os, csize0); // compressed size
+ writeInt(os, size0); // uncompressed size
+ writeShort(os, name.length);
+ writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
+
+ if (comment != null) {
+ writeShort(os, Math.min(clen, 0xffff));
+ } else {
+ writeShort(os, 0);
+ }
+ writeShort(os, 0); // starting disk number
+ writeShort(os, 0); // internal file attributes (unused)
+ writeInt(os, 0); // external file attributes (unused)
+ writeInt(os, locoff0); // relative offset of local header
+ writeBytes(os, name);
+ if (elen64 != 0) {
+ writeShort(os, EXTID_ZIP64);// Zip64 extra
+ writeShort(os, elen64 - 4); // size of "this" extra block
+ if (size0 == ZIP64_MINVAL)
+ writeLong(os, size);
+ if (csize0 == ZIP64_MINVAL)
+ writeLong(os, csize);
+ if (locoff0 == ZIP64_MINVAL)
+ writeLong(os, locoff);
+ }
+ if (elenNTFS != 0) {
+ writeShort(os, EXTID_NTFS);
+ writeShort(os, elenNTFS - 4);
+ writeInt(os, 0); // reserved
+ writeShort(os, 0x0001); // NTFS attr tag
+ writeShort(os, 24);
+ writeLong(os, javaToWinTime(mtime));
+ writeLong(os, javaToWinTime(atime));
+ writeLong(os, javaToWinTime(ctime));
+ }
+ if (elenEXTT != 0) {
+ writeShort(os, EXTID_EXTT);
+ writeShort(os, elenEXTT - 4);
+ if (ctime == -1)
+ os.write(0x3); // mtime and atime
+ else
+ os.write(0x7); // mtime, atime and ctime
+ writeInt(os, javaToUnixTime(mtime));
+ }
+ if (extra != null) // whatever not recognized
+ writeBytes(os, extra);
+ if (comment != null) //TBD: 0, Math.min(commentBytes.length, 0xffff));
+ writeBytes(os, comment);
+ return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT;
+ }
+
+ ///////////////////// LOC //////////////////////
+ static Entry readLOC(ZipFileSystem zipfs, long pos)
+ throws IOException
+ {
+ return readLOC(zipfs, pos, new byte[1024]);
+ }
+
+ static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
+ throws IOException
+ {
+ return new Entry().loc(zipfs, pos, buf);
+ }
+
+ Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
+ throws IOException
+ {
+ assert (buf.length >= LOCHDR);
+ if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
+ throw new ZipException("loc: reading failed");
+ if (LOCSIG(buf) != LOCSIG)
+ throw new ZipException("loc: wrong sig ->"
+ + Long.toString(LOCSIG(buf), 16));
+ //startPos = pos;
+ version = LOCVER(buf);
+ flag = LOCFLG(buf);
+ method = LOCHOW(buf);
+ mtime = dosToJavaTime(LOCTIM(buf));
+ crc = LOCCRC(buf);
+ csize = LOCSIZ(buf);
+ size = LOCLEN(buf);
+ int nlen = LOCNAM(buf);
+ int elen = LOCEXT(buf);
+
+ name = new byte[nlen];
+ if (zipfs.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) {
+ throw new ZipException("loc: name reading failed");
+ }
+ if (elen > 0) {
+ extra = new byte[elen];
+ if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
+ != elen) {
+ throw new ZipException("loc: ext reading failed");
+ }
+ }
+ pos += (LOCHDR + nlen + elen);
+ if ((flag & FLAG_DATADESCR) != 0) {
+ // Data Descriptor
+ Entry e = zipfs.getEntry0(name); // get the size/csize from cen
+ if (e == null)
+ throw new ZipException("loc: name not found in cen");
+ size = e.size;
+ csize = e.csize;
+ pos += (method == METHOD_STORED ? size : csize);
+ if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
+ pos += 24;
+ else
+ pos += 16;
+ } else {
+ if (extra != null &&
+ (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
+ // zip64 ext: must include both size and csize
+ int off = 0;
+ while (off + 20 < elen) { // HeaderID+DataSize+Data
+ int sz = SH(extra, off + 2);
+ if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
+ size = LL(extra, off + 4);
+ csize = LL(extra, off + 12);
+ break;
+ }
+ off += (sz + 4);
+ }
+ }
+ pos += (method == METHOD_STORED ? size : csize);
+ }
+ return this;
+ }
+
+ int writeLOC(OutputStream os)
+ throws IOException
+ {
+ writeInt(os, LOCSIG); // LOC header signature
+ int version = version();
+ int nlen = (name != null) ? name.length : 0;
+ int elen = (extra != null) ? extra.length : 0;
+ boolean foundExtraTime = false; // if extra timestamp present
+ int eoff = 0;
+ int elen64 = 0;
+ int elenEXTT = 0;
+ int elenNTFS = 0;
+ if ((flag & FLAG_DATADESCR) != 0) {
+ writeShort(os, version()); // version needed to extract
+ writeShort(os, flag); // general purpose bit flag
+ writeShort(os, method); // compression method
+ // last modification time
+ writeInt(os, (int)javaToDosTime(mtime));
+ // store size, uncompressed size, and crc-32 in data descriptor
+ // immediately following compressed entry data
+ writeInt(os, 0);
+ writeInt(os, 0);
+ writeInt(os, 0);
+ } else {
+ if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+ elen64 = 20; //headid(2) + size(2) + size(8) + csize(8)
+ writeShort(os, 45); // ver 4.5 for zip64
+ } else {
+ writeShort(os, version()); // version needed to extract
+ }
+ writeShort(os, flag); // general purpose bit flag
+ writeShort(os, method); // compression method
+ // last modification time
+ writeInt(os, (int)javaToDosTime(mtime));
+ writeInt(os, crc); // crc-32
+ if (elen64 != 0) {
+ writeInt(os, ZIP64_MINVAL);
+ writeInt(os, ZIP64_MINVAL);
+ } else {
+ writeInt(os, csize); // compressed size
+ writeInt(os, size); // uncompressed size
+ }
+ }
+ while (eoff + 4 < elen) {
+ int tag = SH(extra, eoff);
+ int sz = SH(extra, eoff + 2);
+ if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
+ foundExtraTime = true;
+ }
+ eoff += (4 + sz);
+ }
+ if (!foundExtraTime) {
+ if (isWindows) {
+ elenNTFS = 36; // NTFS, total 36 bytes
+ } else { // on unix use "ext time"
+ elenEXTT = 9;
+ if (atime != -1)
+ elenEXTT += 4;
+ if (ctime != -1)
+ elenEXTT += 4;
+ }
+ }
+ writeShort(os, name.length);
+ writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
+ writeBytes(os, name);
+ if (elen64 != 0) {
+ writeShort(os, EXTID_ZIP64);
+ writeShort(os, 16);
+ writeLong(os, size);
+ writeLong(os, csize);
+ }
+ if (elenNTFS != 0) {
+ writeShort(os, EXTID_NTFS);
+ writeShort(os, elenNTFS - 4);
+ writeInt(os, 0); // reserved
+ writeShort(os, 0x0001); // NTFS attr tag
+ writeShort(os, 24);
+ writeLong(os, javaToWinTime(mtime));
+ writeLong(os, javaToWinTime(atime));
+ writeLong(os, javaToWinTime(ctime));
+ }
+ if (elenEXTT != 0) {
+ writeShort(os, EXTID_EXTT);
+ writeShort(os, elenEXTT - 4);// size for the folowing data block
+ int fbyte = 0x1;
+ if (atime != -1) // mtime and atime
+ fbyte |= 0x2;
+ if (ctime != -1) // mtime, atime and ctime
+ fbyte |= 0x4;
+ os.write(fbyte); // flags byte
+ writeInt(os, javaToUnixTime(mtime));
+ if (atime != -1)
+ writeInt(os, javaToUnixTime(atime));
+ if (ctime != -1)
+ writeInt(os, javaToUnixTime(ctime));
+ }
+ if (extra != null) {
+ writeBytes(os, extra);
+ }
+ return LOCHDR + name.length + elen + elen64 + elenNTFS + elenEXTT;
+ }
+
+ // Data Descriptior
+ int writeEXT(OutputStream os)
+ throws IOException
+ {
+ writeInt(os, EXTSIG); // EXT header signature
+ writeInt(os, crc); // crc-32
+ if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+ writeLong(os, csize);
+ writeLong(os, size);
+ return 24;
+ } else {
+ writeInt(os, csize); // compressed size
+ writeInt(os, size); // uncompressed size
+ return 16;
+ }
+ }
+
+ // read NTFS, UNIX and ZIP64 data from cen.extra
+ void readExtra(ZipFileSystem zipfs) throws IOException {
+ if (extra == null)
+ return;
+ int elen = extra.length;
+ int off = 0;
+ int newOff = 0;
+ while (off + 4 < elen) {
+ // extra spec: HeaderID+DataSize+Data
+ int pos = off;
+ int tag = SH(extra, pos);
+ int sz = SH(extra, pos + 2);
+ pos += 4;
+ if (pos + sz > elen) // invalid data
+ break;
+ switch (tag) {
+ case EXTID_ZIP64 :
+ if (size == ZIP64_MINVAL) {
+ if (pos + 8 > elen) // invalid zip64 extra
+ break; // fields, just skip
+ size = LL(extra, pos);
+ pos += 8;
+ }
+ if (csize == ZIP64_MINVAL) {
+ if (pos + 8 > elen)
+ break;
+ csize = LL(extra, pos);
+ pos += 8;
+ }
+ if (locoff == ZIP64_MINVAL) {
+ if (pos + 8 > elen)
+ break;
+ locoff = LL(extra, pos);
+ pos += 8;
+ }
+ break;
+ case EXTID_NTFS:
+ pos += 4; // reserved 4 bytes
+ if (SH(extra, pos) != 0x0001)
+ break;
+ if (SH(extra, pos + 2) != 24)
+ break;
+ // override the loc field, datatime here is
+ // more "accurate"
+ mtime = winToJavaTime(LL(extra, pos + 4));
+ atime = winToJavaTime(LL(extra, pos + 12));
+ ctime = winToJavaTime(LL(extra, pos + 20));
+ break;
+ case EXTID_EXTT:
+ // spec says the Extened timestamp in cen only has mtime
+ // need to read the loc to get the extra a/ctime
+ byte[] buf = new byte[LOCHDR];
+ if (zipfs.readFullyAt(buf, 0, buf.length , locoff)
+ != buf.length)
+ throw new ZipException("loc: reading failed");
+ if (LOCSIG(buf) != LOCSIG)
+ throw new ZipException("loc: wrong sig ->"
+ + Long.toString(LOCSIG(buf), 16));
+
+ int locElen = LOCEXT(buf);
+ if (locElen < 9) // EXTT is at lease 9 bytes
+ break;
+ int locNlen = LOCNAM(buf);
+ buf = new byte[locElen];
+ if (zipfs.readFullyAt(buf, 0, buf.length , locoff + LOCHDR + locNlen)
+ != buf.length)
+ throw new ZipException("loc extra: reading failed");
+ int locPos = 0;
+ while (locPos + 4 < buf.length) {
+ int locTag = SH(buf, locPos);
+ int locSZ = SH(buf, locPos + 2);
+ locPos += 4;
+ if (locTag != EXTID_EXTT) {
+ locPos += locSZ;
+ continue;
+ }
+ int flag = CH(buf, locPos++);
+ if ((flag & 0x1) != 0) {
+ mtime = unixToJavaTime(LG(buf, locPos));
+ locPos += 4;
+ }
+ if ((flag & 0x2) != 0) {
+ atime = unixToJavaTime(LG(buf, locPos));
+ locPos += 4;
+ }
+ if ((flag & 0x4) != 0) {
+ ctime = unixToJavaTime(LG(buf, locPos));
+ locPos += 4;
+ }
+ break;
+ }
+ break;
+ default: // unknown tag
+ System.arraycopy(extra, off, extra, newOff, sz + 4);
+ newOff += (sz + 4);
+ }
+ off += (sz + 4);
+ }
+ if (newOff != 0 && newOff != extra.length)
+ extra = Arrays.copyOf(extra, newOff);
+ else
+ extra = null;
+ }
+ }
+
+ private static class ExChannelCloser {
+ Path path;
+ SeekableByteChannel ch;
+ Set<InputStream> streams;
+ ExChannelCloser(Path path,
+ SeekableByteChannel ch,
+ Set<InputStream> streams)
+ {
+ this.path = path;
+ this.ch = ch;
+ this.streams = streams;
+ }
+ }
+
+ // ZIP directory has two issues:
+ // (1) ZIP spec does not require the ZIP file to include
+ // directory entry
+ // (2) all entries are not stored/organized in a "tree"
+ // structure.
+ // A possible solution is to build the node tree ourself as
+ // implemented below.
+ private IndexNode root;
+
+ private void addToTree(IndexNode inode, HashSet<IndexNode> dirs) {
+ if (dirs.contains(inode)) {
+ return;
+ }
+ IndexNode parent;
+ byte[] name = inode.name;
+ byte[] pname = getParent(name);
+ if (inodes.containsKey(LOOKUPKEY.as(pname))) {
+ parent = inodes.get(LOOKUPKEY);
+ } else { // pseudo directory entry
+ parent = new IndexNode(pname, -1);
+ inodes.put(parent, parent);
+ }
+ addToTree(parent, dirs);
+ inode.sibling = parent.child;
+ parent.child = inode;
+ if (name[name.length -1] == '/')
+ dirs.add(inode);
+ }
+
+ private void removeFromTree(IndexNode inode) {
+ IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
+ IndexNode child = parent.child;
+ if (child.equals(inode)) {
+ parent.child = child.sibling;
+ } else {
+ IndexNode last = child;
+ while ((child = child.sibling) != null) {
+ if (child.equals(inode)) {
+ last.sibling = child.sibling;
+ break;
+ } else {
+ last = child;
+ }
+ }
+ }
+ }
+
+ private void buildNodeTree() throws IOException {
+ beginWrite();
+ try {
+ HashSet<IndexNode> dirs = new HashSet<>();
+ IndexNode root = new IndexNode(ROOTPATH, -1);
+ inodes.put(root, root);
+ dirs.add(root);
+ for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) {
+ addToTree(node, dirs);
+ }
+ } finally {
+ endWrite();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.io.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.attribute.*;
+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;
+import java.util.zip.ZipError;
+import java.util.concurrent.ExecutorService;
+
+/*
+ *
+ * @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 "jar";
+ }
+
+ protected Path uriToPath(URI uri) {
+ String scheme = uri.getScheme();
+ if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
+ throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+ }
+ try {
+ // only support legacy JAR URL syntax jar:{uri}!/{entry} for now
+ String spec = uri.getRawSchemeSpecificPart();
+ int sep = spec.indexOf("!/");
+ if (sep != -1)
+ spec = spec.substring(0, sep);
+ return Paths.get(new URI(spec)).toAbsolutePath();
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
+ }
+
+ private boolean ensureFile(Path path) {
+ try {
+ BasicFileAttributes attrs =
+ Files.readAttributes(path, BasicFileAttributes.class);
+ if (!attrs.isRegularFile())
+ throw new UnsupportedOperationException();
+ return true;
+ } catch (IOException ioe) {
+ return false;
+ }
+ }
+
+ @Override
+ public FileSystem newFileSystem(URI uri, Map<String, ?> env)
+ throws IOException
+ {
+ Path path = uriToPath(uri);
+ synchronized(filesystems) {
+ Path realPath = null;
+ if (ensureFile(path)) {
+ realPath = path.toRealPath();
+ if (filesystems.containsKey(realPath))
+ throw new FileSystemAlreadyExistsException();
+ }
+ ZipFileSystem zipfs = null;
+ try {
+ zipfs = new ZipFileSystem(this, path, env);
+ } catch (ZipError ze) {
+ String pname = path.toString();
+ if (pname.endsWith(".zip") || pname.endsWith(".jar"))
+ throw ze;
+ // assume NOT a zip/jar file
+ throw new UnsupportedOperationException();
+ }
+ filesystems.put(realPath, zipfs);
+ return zipfs;
+ }
+ }
+
+ @Override
+ public FileSystem newFileSystem(Path path, Map<String, ?> env)
+ throws IOException
+ {
+ if (path.getFileSystem() != FileSystems.getDefault()) {
+ throw new UnsupportedOperationException();
+ }
+ ensureFile(path);
+ try {
+ return new ZipFileSystem(this, path, env);
+ } catch (ZipError ze) {
+ String pname = path.toString();
+ if (pname.endsWith(".zip") || pname.endsWith(".jar"))
+ throw ze;
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Override
+ public Path getPath(URI uri) {
+
+ String spec = uri.getSchemeSpecificPart();
+ int sep = spec.indexOf("!/");
+ if (sep == -1)
+ throw new IllegalArgumentException("URI: "
+ + uri
+ + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
+ return getFileSystem(uri).getPath(spec.substring(sep + 1));
+ }
+
+
+ @Override
+ public FileSystem getFileSystem(URI uri) {
+ synchronized (filesystems) {
+ ZipFileSystem zipfs = null;
+ try {
+ zipfs = filesystems.get(uriToPath(uri).toRealPath());
+ } catch (IOException x) {
+ // ignore the ioe from toRealPath(), return FSNFE
+ }
+ if (zipfs == null)
+ throw new FileSystemNotFoundException();
+ return zipfs;
+ }
+ }
+
+ // Checks that the given file is a UnixPath
+ static final ZipPath toZipPath(Path path) {
+ if (path == null)
+ throw new NullPointerException();
+ if (!(path instanceof ZipPath))
+ throw new ProviderMismatchException();
+ return (ZipPath)path;
+ }
+
+ @Override
+ public void checkAccess(Path path, AccessMode... modes) throws IOException {
+ toZipPath(path).checkAccess(modes);
+ }
+
+ @Override
+ public void copy(Path src, Path target, CopyOption... options)
+ throws IOException
+ {
+ toZipPath(src).copy(toZipPath(target), options);
+ }
+
+ @Override
+ public void createDirectory(Path path, FileAttribute<?>... attrs)
+ throws IOException
+ {
+ toZipPath(path).createDirectory(attrs);
+ }
+
+ @Override
+ public final void delete(Path path) throws IOException {
+ toZipPath(path).delete();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <V extends FileAttributeView> V
+ getFileAttributeView(Path path, Class<V> type, LinkOption... options)
+ {
+ return ZipFileAttributeView.get(toZipPath(path), type);
+ }
+
+ @Override
+ public FileStore getFileStore(Path path) throws IOException {
+ return toZipPath(path).getFileStore();
+ }
+
+ @Override
+ public boolean isHidden(Path path) {
+ return toZipPath(path).isHidden();
+ }
+
+ @Override
+ public boolean isSameFile(Path path, Path other) throws IOException {
+ return toZipPath(path).isSameFile(other);
+ }
+
+ @Override
+ public void move(Path src, Path target, CopyOption... options)
+ throws IOException
+ {
+ toZipPath(src).move(toZipPath(target), options);
+ }
+
+ @Override
+ public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
+ Set<? extends OpenOption> options,
+ ExecutorService exec,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SeekableByteChannel newByteChannel(Path path,
+ Set<? extends OpenOption> options,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ return toZipPath(path).newByteChannel(options, attrs);
+ }
+
+ @Override
+ public DirectoryStream<Path> newDirectoryStream(
+ Path path, Filter<? super Path> filter) throws IOException
+ {
+ return toZipPath(path).newDirectoryStream(filter);
+ }
+
+ @Override
+ public FileChannel newFileChannel(Path path,
+ Set<? extends OpenOption> options,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ return toZipPath(path).newFileChannel(options, attrs);
+ }
+
+ @Override
+ public InputStream newInputStream(Path path, OpenOption... options)
+ throws IOException
+ {
+ return toZipPath(path).newInputStream(options);
+ }
+
+ @Override
+ public OutputStream newOutputStream(Path path, OpenOption... options)
+ throws IOException
+ {
+ return toZipPath(path).newOutputStream(options);
+ }
+
+ @Override
+ public <A extends BasicFileAttributes> A
+ readAttributes(Path path, Class<A> type, LinkOption... options)
+ throws IOException
+ {
+ if (type == BasicFileAttributes.class || type == ZipFileAttributes.class)
+ return (A)toZipPath(path).getAttributes();
+ return null;
+ }
+
+ @Override
+ public Map<String, Object>
+ readAttributes(Path path, String attribute, LinkOption... options)
+ throws IOException
+ {
+ return toZipPath(path).readAttributes(attribute, options);
+ }
+
+ @Override
+ public Path readSymbolicLink(Path link) throws IOException {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void setAttribute(Path path, String attribute,
+ Object value, LinkOption... options)
+ throws IOException
+ {
+ toZipPath(path).setAttribute(attribute, value, options);
+ }
+
+ //////////////////////////////////////////////////////////////
+ void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException {
+ synchronized (filesystems) {
+ zfpath = zfpath.toRealPath();
+ if (filesystems.get(zfpath) == zfs)
+ filesystems.remove(zfpath);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipInfo.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+import static jdk.nio.zipfs.ZipConstants.*;
+import static jdk.nio.zipfs.ZipUtils.*;
+
+/**
+ * Print all loc and cen headers of the ZIP file
+ *
+ * @author Xueming Shen
+ */
+
+public class ZipInfo {
+
+ public static void main(String[] args) throws Throwable {
+ if (args.length < 1) {
+ print("Usage: java ZipInfo zfname");
+ } else {
+ Map<String, ?> env = Collections.emptyMap();
+ ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
+ .newFileSystem(Paths.get(args[0]), env));
+ byte[] cen = zfs.cen;
+ if (cen == null) {
+ print("zip file is empty%n");
+ return;
+ }
+ int pos = 0;
+ byte[] buf = new byte[1024];
+ int no = 1;
+ while (pos + CENHDR < cen.length) {
+ print("----------------#%d--------------------%n", no++);
+ printCEN(cen, pos);
+
+ // use size CENHDR as the extra bytes to read, just in case the
+ // loc.extra is bigger than the cen.extra, try to avoid to read
+ // twice
+ long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR;
+ if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
+ ZipFileSystem.zerror("read loc header failed");
+ if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) {
+ // have to read the second time;
+ len = LOCHDR + LOCNAM(buf) + LOCEXT(buf);
+ if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
+ ZipFileSystem.zerror("read loc header failed");
+ }
+ printLOC(buf);
+ pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos);
+ }
+ zfs.close();
+ }
+ }
+
+ static void print(String fmt, Object... objs) {
+ System.out.printf(fmt, objs);
+ }
+
+ static void printLOC(byte[] loc) {
+ print("%n");
+ print("[Local File Header]%n");
+ print(" Signature : %#010x%n", LOCSIG(loc));
+ if (LOCSIG(loc) != LOCSIG) {
+ print(" Wrong signature!");
+ return;
+ }
+ print(" Version : %#6x [%d.%d]%n",
+ LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10);
+ print(" Flag : %#6x%n", LOCFLG(loc));
+ print(" Method : %#6x%n", LOCHOW(loc));
+ print(" LastMTime : %#10x [%tc]%n",
+ LOCTIM(loc), dosToJavaTime(LOCTIM(loc)));
+ print(" CRC : %#10x%n", LOCCRC(loc));
+ print(" CSize : %#10x%n", LOCSIZ(loc));
+ print(" Size : %#10x%n", LOCLEN(loc));
+ print(" NameLength : %#6x [%s]%n",
+ LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc)));
+ print(" ExtraLength : %#6x%n", LOCEXT(loc));
+ if (LOCEXT(loc) != 0)
+ printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc));
+ }
+
+ static void printCEN(byte[] cen, int off) {
+ print("[Central Directory Header]%n");
+ print(" Signature : %#010x%n", CENSIG(cen, off));
+ if (CENSIG(cen, off) != CENSIG) {
+ print(" Wrong signature!");
+ return;
+ }
+ print(" VerMadeby : %#6x [%d, %d.%d]%n",
+ CENVEM(cen, off), (CENVEM(cen, off) >> 8),
+ (CENVEM(cen, off) & 0xff) / 10,
+ (CENVEM(cen, off) & 0xff) % 10);
+ print(" VerExtract : %#6x [%d.%d]%n",
+ CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10);
+ print(" Flag : %#6x%n", CENFLG(cen, off));
+ print(" Method : %#6x%n", CENHOW(cen, off));
+ print(" LastMTime : %#10x [%tc]%n",
+ CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off)));
+ print(" CRC : %#10x%n", CENCRC(cen, off));
+ print(" CSize : %#10x%n", CENSIZ(cen, off));
+ print(" Size : %#10x%n", CENLEN(cen, off));
+ print(" NameLen : %#6x [%s]%n",
+ CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off)));
+ print(" ExtraLen : %#6x%n", CENEXT(cen, off));
+ if (CENEXT(cen, off) != 0)
+ printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off));
+ print(" CommentLen : %#6x%n", CENCOM(cen, off));
+ print(" DiskStart : %#6x%n", CENDSK(cen, off));
+ print(" Attrs : %#6x%n", CENATT(cen, off));
+ print(" AttrsEx : %#10x%n", CENATX(cen, off));
+ print(" LocOff : %#10x%n", CENOFF(cen, off));
+
+ }
+
+ static long locoff(byte[] cen, int pos) {
+ long locoff = CENOFF(cen, pos);
+ if (locoff == ZIP64_MINVAL) { //ZIP64
+ int off = pos + CENHDR + CENNAM(cen, pos);
+ int end = off + CENEXT(cen, pos);
+ while (off + 4 < end) {
+ int tag = SH(cen, off);
+ int sz = SH(cen, off + 2);
+ if (tag != EXTID_ZIP64) {
+ off += 4 + sz;
+ continue;
+ }
+ off += 4;
+ if (CENLEN(cen, pos) == ZIP64_MINVAL)
+ off += 8;
+ if (CENSIZ(cen, pos) == ZIP64_MINVAL)
+ off += 8;
+ return LL(cen, off);
+ }
+ // should never be here
+ }
+ return locoff;
+ }
+
+ static void printExtra(byte[] extra, int off, int len) {
+ int end = off + len;
+ while (off + 4 <= end) {
+ int tag = SH(extra, off);
+ int sz = SH(extra, off + 2);
+ print(" [tag=0x%04x, sz=%d, data= ", tag, sz);
+ if (off + sz > end) {
+ print(" Error: Invalid extra data, beyond extra length");
+ break;
+ }
+ off += 4;
+ for (int i = 0; i < sz; i++)
+ print("%02x ", extra[off + i]);
+ print("]%n");
+ switch (tag) {
+ case EXTID_ZIP64 :
+ print(" ->ZIP64: ");
+ int pos = off;
+ while (pos + 8 <= off + sz) {
+ print(" *0x%x ", LL(extra, pos));
+ pos += 8;
+ }
+ print("%n");
+ break;
+ case EXTID_NTFS:
+ print(" ->PKWare NTFS%n");
+ // 4 bytes reserved
+ if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24)
+ print(" Error: Invalid NTFS sub-tag or subsz");
+ print(" mtime:%tc%n",
+ winToJavaTime(LL(extra, off + 8)));
+ print(" atime:%tc%n",
+ winToJavaTime(LL(extra, off + 16)));
+ print(" ctime:%tc%n",
+ winToJavaTime(LL(extra, off + 24)));
+ break;
+ case EXTID_EXTT:
+ print(" ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]);
+ pos = off + 1 ;
+ while (pos + 4 <= off + sz) {
+ print(" *%tc%n",
+ unixToJavaTime(LG(extra, pos)));
+ pos += 4;
+ }
+ break;
+ default:
+ print(" ->[tag=%x, size=%d]%n", tag, sz);
+ }
+ off += sz;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipPath.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,869 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.io.*;
+import java.net.URI;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.attribute.*;
+import java.util.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+
+/**
+ *
+ * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+class ZipPath implements 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 getFileName() {
+ 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(LinkOption... options) throws IOException {
+ ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath();
+ realPath.checkAccess();
+ return realPath;
+ }
+
+ 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() {
+ try {
+ return new URI("jar",
+ zfs.getZipFile().toUri() +
+ "!" +
+ zfs.getString(toAbsolutePath().path),
+ null);
+ } 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 new ZipPath(getFileSystem(), new byte[0], true);
+ 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.length > 0 && path[0] == '/');
+ }
+
+ @Override
+ public ZipPath resolve(Path other) {
+ 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 Path resolveSibling(Path other) {
+ if (other == null)
+ throw new NullPointerException();
+ Path parent = getParent();
+ return (parent == null) ? other : parent.resolve(other);
+ }
+
+ @Override
+ public boolean startsWith(Path other) {
+ final ZipPath o = checkPath(other);
+ if (o.isAbsolute() != this.isAbsolute() ||
+ o.path.length > this.path.length)
+ return false;
+ int olast = o.path.length;
+ for (int i = 0; i < olast; i++) {
+ if (o.path[i] != this.path[i])
+ return false;
+ }
+ olast--;
+ return o.path.length == this.path.length ||
+ o.path[olast] == '/' ||
+ this.path[olast + 1] == '/';
+ }
+
+ @Override
+ public boolean endsWith(Path other) {
+ final ZipPath o = checkPath(other);
+ int olast = o.path.length - 1;
+ if (olast > 0 && o.path[olast] == '/')
+ olast--;
+ int last = this.path.length - 1;
+ if (last > 0 && this.path[last] == '/')
+ last--;
+ if (olast == -1) // o.path.length == 0
+ return last == -1;
+ if ((o.isAbsolute() &&(!this.isAbsolute() || olast != last)) ||
+ (last < olast))
+ return false;
+ for (; olast >= 0; olast--, last--) {
+ if (o.path[olast] != this.path[last])
+ return false;
+ }
+ return o.path[olast + 1] == '/' ||
+ last == -1 || this.path[last] == '/';
+ }
+
+ @Override
+ public ZipPath resolve(String other) {
+ return resolve(getFileSystem().getPath(other));
+ }
+
+ @Override
+ public final Path resolveSibling(String other) {
+ return resolveSibling(getFileSystem().getPath(other));
+ }
+
+ @Override
+ public final boolean startsWith(String other) {
+ return startsWith(getFileSystem().getPath(other));
+ }
+
+ @Override
+ public final boolean endsWith(String other) {
+ return endsWith(getFileSystem().getPath(other));
+ }
+
+ @Override
+ public Path normalize() {
+ byte[] resolved = getResolved();
+ if (resolved == path) // no change
+ return this;
+ 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)'.') {
+ if (m == 0 && path[0] == '/') // absolute path
+ to[m++] = '/';
+ 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;
+ }
+
+ 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 final File toFile() {
+ throw new UnsupportedOperationException();
+ }
+
+ @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();
+ }
+ };
+ }
+
+ /////////////////////////////////////////////////////////////////////
+
+
+ void createDirectory(FileAttribute<?>... attrs)
+ throws IOException
+ {
+ zfs.createDirectory(getResolvedPath(), attrs);
+ }
+
+ 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());
+ }
+
+ DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
+ throws IOException
+ {
+ return new ZipDirectoryStream(this, filter);
+ }
+
+ void delete() throws IOException {
+ zfs.deleteFile(getResolvedPath(), true);
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ Map<String, Object> readAttributes(String attributes, LinkOption... options)
+ throws IOException
+
+ {
+ String view = null;
+ String attrs = null;
+ int colonPos = attributes.indexOf(':');
+ if (colonPos == -1) {
+ view = "basic";
+ attrs = attributes;
+ } else {
+ view = attributes.substring(0, colonPos++);
+ attrs = attributes.substring(colonPos);
+ }
+ ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
+ if (zfv == null) {
+ throw new UnsupportedOperationException("view not supported");
+ }
+ return zfv.readAttributes(attrs);
+ }
+
+ 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));
+ }
+
+ boolean isSameFile(Path other) throws IOException {
+ if (this.equals(other))
+ return true;
+ if (other == null ||
+ this.getFileSystem() != other.getFileSystem())
+ return false;
+ this.checkAccess();
+ ((ZipPath)other).checkAccess();
+ return Arrays.equals(this.getResolvedPath(),
+ ((ZipPath)other).getResolvedPath());
+ }
+
+ 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);
+ }
+
+ 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());
+ }
+
+ boolean exists() {
+ if (path.length == 1 && path[0] == '/')
+ return true;
+ try {
+ return zfs.exists(getResolvedPath());
+ } catch (IOException x) {}
+ return false;
+ }
+
+ OutputStream newOutputStream(OpenOption... options) throws IOException
+ {
+ if (options.length == 0)
+ return zfs.newOutputStream(getResolvedPath(),
+ CREATE_NEW, WRITE);
+ return zfs.newOutputStream(getResolvedPath(), options);
+ }
+
+ void move(ZipPath target, CopyOption... options)
+ throws IOException
+ {
+ if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
+ {
+ zfs.copyFile(true,
+ getResolvedPath(), target.getResolvedPath(),
+ options);
+ } else {
+ copyToTarget(target, options);
+ delete();
+ }
+ }
+
+ void copy(ZipPath target, CopyOption... options)
+ throws IOException
+ {
+ if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
+ zfs.copyFile(false,
+ getResolvedPath(), target.getResolvedPath(),
+ options);
+ else
+ copyToTarget(target, options);
+ }
+
+ private void copyToTarget(ZipPath 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 = true;
+ }
+ // 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 =
+ ZipFileAttributeView.get(target, BasicFileAttributeView.class);
+ try {
+ view.setTimes(zfas.lastModifiedTime(),
+ zfas.lastAccessTime(),
+ zfas.creationTime());
+ } catch (IOException x) {
+ // rollback?
+ try {
+ target.delete();
+ } catch (IOException ignore) { }
+ throw x;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipUtils.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009, 2014, 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.
+ */
+
+package jdk.nio.zipfs;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.regex.PatternSyntaxException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * @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 & 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 & 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 & 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;
+ }
+
+
+ // used to adjust values between Windows and java epoch
+ private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
+ public static final long winToJavaTime(long wtime) {
+ return TimeUnit.MILLISECONDS.convert(
+ wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
+ }
+
+ public static final long javaToWinTime(long time) {
+ return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
+ - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
+ }
+
+ public static final long unixToJavaTime(long utime) {
+ return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
+ }
+
+ public static final long javaToUnixTime(long time) {
+ return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
+ }
+
+ 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();
+ }
+}
--- a/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java Wed Apr 16 10:53:10 2014 -0700
@@ -27,13 +27,15 @@
import java.awt.AWTEvent;
-import java.util.Collections;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import sun.util.logging.PlatformLogger;
+import sun.misc.ThreadGroupUtils;
/**
* This class is to let AWT shutdown automatically when a user is done
@@ -215,7 +217,10 @@
synchronized (activationLock) {
synchronized (mainLock) {
if (!isReadyToShutdown() && blockerThread == null) {
- activateBlockerThread();
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ activateBlockerThread();
+ return null;
+ });
} else {
mainLock.notifyAll();
timeoutPassed = false;
@@ -331,9 +336,12 @@
/**
* Creates and starts a new blocker thread. Doesn't return until
* the new blocker thread starts.
+ *
+ * Must be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
*/
private void activateBlockerThread() {
- Thread thread = new Thread(this, "AWT-Shutdown");
+ Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, "AWT-Shutdown");
+ thread.setContextClassLoader(null);
thread.setDaemon(false);
blockerThread = thread;
thread.start();
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Apr 16 10:53:10 2014 -0700
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
--- a/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java Wed Apr 16 10:53:10 2014 -0700
@@ -85,7 +85,7 @@
// read it.
Map<Long, Object> cached_data = new HashMap<>(formats.length, 1.0f);
DataTransferer.getInstance()
- .getFlavorsForFormats(formats, SunClipboard.flavorMap)
+ .getFlavorsForFormats(formats, SunClipboard.getDefaultFlavorTable())
.entrySet()
.forEach(entry -> fetchOneFlavor(clipboard, entry.getKey(), entry.getValue(), cached_data));
flavors = DataTransferer.setToSortedDataFlavorArray(flavorsToData.keySet());
--- a/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Wed Apr 16 10:53:10 2014 -0700
@@ -63,9 +63,6 @@
public abstract class SunClipboard extends Clipboard
implements PropertyChangeListener {
- public static final FlavorTable flavorMap =
- (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
-
private AppContext contentsContext = null;
private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
@@ -167,7 +164,7 @@
long[] formats = getClipboardFormatsOpenClose();
return DataTransferer.getInstance().
- getFlavorsForFormatsAsArray(formats, flavorMap);
+ getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable());
}
/**
@@ -213,7 +210,7 @@
long[] formats = getClipboardFormats();
Long lFormat = DataTransferer.getInstance().
- getFlavorsForFormats(formats, flavorMap).get(flavor);
+ getFlavorsForFormats(formats, getDefaultFlavorTable()).get(flavor);
if (lFormat == null) {
throw new UnsupportedFlavorException(flavor);
@@ -344,7 +341,7 @@
private static Set formatArrayAsDataFlavorSet(long[] formats) {
return (formats == null) ? null :
DataTransferer.getInstance().
- getFlavorsForFormatsAsSet(formats, flavorMap);
+ getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable());
}
@@ -447,4 +444,8 @@
}
}
}
+
+ public static FlavorTable getDefaultFlavorTable() {
+ return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap();
+ }
}
--- a/jdk/src/share/classes/sun/font/CreatedFontTracker.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/font/CreatedFontTracker.java Wed Apr 16 10:53:10 2014 -0700
@@ -27,12 +27,15 @@
import java.io.File;
import java.io.OutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import sun.awt.AppContext;
+import sun.misc.ThreadGroupUtils;
public class CreatedFontTracker {
@@ -112,28 +115,18 @@
static void init() {
if (t == null) {
// Add a shutdown hook to remove the temp file.
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Object>() {
- public Object run() {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup tg =
- Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- t = new Thread(tg, new Runnable() {
- public void run() {
- runHooks();
- }
- });
- t.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(t);
- return null;
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ t = new Thread(rootTG, TempFileDeletionHook::runHooks);
+ t.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(t);
+ return null;
+ });
}
}
--- a/jdk/src/share/classes/sun/font/SunFontManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/font/SunFontManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -52,6 +52,7 @@
import sun.awt.AppContext;
import sun.awt.FontConfiguration;
import sun.awt.SunToolkit;
+import sun.misc.ThreadGroupUtils;
import sun.java2d.FontSupport;
import sun.util.logging.PlatformLogger;
@@ -2527,24 +2528,18 @@
});
}
};
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Object>() {
- public Object run() {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup tg =
- Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- fileCloser = new Thread(tg, fileCloserRunnable);
- fileCloser.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(fileCloser);
- return null;
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ fileCloser = new Thread(rootTG, fileCloserRunnable);
+ fileCloser.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(fileCloser);
+ return null;
+ });
}
}
}
--- a/jdk/src/share/classes/sun/java2d/Disposer.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/java2d/Disposer.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,10 +25,14 @@
package sun.java2d;
+import sun.misc.ThreadGroupUtils;
+
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.PhantomReference;
import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Hashtable;
@@ -77,27 +81,21 @@
}
}
disposerInstance = new Disposer();
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Object>() {
- public Object run() {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- Thread t =
- new Thread(tg, disposerInstance, "Java2D Disposer");
- t.setContextClassLoader(null);
- t.setDaemon(true);
- t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- return null;
- }
- }
- );
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ Thread t = new Thread(rootTG, disposerInstance, "Java2D Disposer");
+ t.setContextClassLoader(null);
+ t.setDaemon(true);
+ t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+ return null;
+ }
+ );
}
/**
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,6 +25,7 @@
package sun.java2d.opengl;
+import sun.misc.ThreadGroupUtils;
import sun.java2d.pipe.RenderBuffer;
import sun.java2d.pipe.RenderQueue;
import static sun.java2d.pipe.BufferedOpCodes.*;
@@ -47,14 +48,8 @@
* The thread must be a member of a thread group
* which will not get GCed before VM exit.
*/
- flusher = AccessController.doPrivileged(new PrivilegedAction<QueueFlusher>() {
- public QueueFlusher run() {
- ThreadGroup rootThreadGroup = Thread.currentThread().getThreadGroup();
- while (rootThreadGroup.getParent() != null) {
- rootThreadGroup = rootThreadGroup.getParent();
- }
- return new QueueFlusher(rootThreadGroup);
- }
+ flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) () -> {
+ return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup());
});
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/InnocuousThread.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013, 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 GNUNSAFE 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 WITHOUNSAFET
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICUNSAFELAR PUNSAFERPOSE. See the GNUNSAFE 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 GNUNSAFE 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 UNSAFESA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 UNSAFESA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.security.AccessControlContext;
+import java.security.ProtectionDomain;
+
+/**
+ * A thread that has no permissions, is not a member of any user-defined
+ * ThreadGroup and supports the ability to erase ThreadLocals.
+ *
+ * @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
+ */
+public final class InnocuousThread extends Thread {
+ private static final Unsafe UNSAFE;
+ private static final ThreadGroup THREADGROUP;
+ private static final AccessControlContext ACC;
+ private static final long THREADLOCALS;
+ private static final long INHERITABLETHREADLOCALS;
+ private static final long INHERITEDACCESSCONTROLCONTEXT;
+
+ public InnocuousThread(Runnable target) {
+ super(THREADGROUP, target, "anInnocuousThread");
+ UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
+ eraseThreadLocals();
+ }
+
+ @Override
+ public ClassLoader getContextClassLoader() {
+ // always report system class loader
+ return ClassLoader.getSystemClassLoader();
+ }
+
+ @Override
+ public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
+ // silently fail
+ }
+
+ @Override
+ public void setContextClassLoader(ClassLoader cl) {
+ throw new SecurityException("setContextClassLoader");
+ }
+
+ // ensure run method is run only once
+ private volatile boolean hasRun;
+
+ @Override
+ public void run() {
+ if (Thread.currentThread() == this && !hasRun) {
+ hasRun = true;
+ super.run();
+ }
+ }
+
+ /**
+ * Drops all thread locals (and inherited thread locals).
+ */
+ public void eraseThreadLocals() {
+ UNSAFE.putObject(this, THREADLOCALS, null);
+ UNSAFE.putObject(this, INHERITABLETHREADLOCALS, null);
+ }
+
+ // Use Unsafe to access Thread group and ThreadGroup parent fields
+ static {
+ try {
+ ACC = new AccessControlContext(new ProtectionDomain[] {
+ new ProtectionDomain(null, null)
+ });
+
+ // Find and use topmost ThreadGroup as parent of new group
+ UNSAFE = Unsafe.getUnsafe();
+ Class<?> tk = Thread.class;
+ Class<?> gk = ThreadGroup.class;
+
+ THREADLOCALS = UNSAFE.objectFieldOffset
+ (tk.getDeclaredField("threadLocals"));
+ INHERITABLETHREADLOCALS = UNSAFE.objectFieldOffset
+ (tk.getDeclaredField("inheritableThreadLocals"));
+ INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
+ (tk.getDeclaredField("inheritedAccessControlContext"));
+
+ long tg = UNSAFE.objectFieldOffset(tk.getDeclaredField("group"));
+ long gp = UNSAFE.objectFieldOffset(gk.getDeclaredField("parent"));
+ ThreadGroup group = (ThreadGroup)
+ UNSAFE.getObject(Thread.currentThread(), tg);
+
+ while (group != null) {
+ ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);
+ if (parent == null)
+ break;
+ group = parent;
+ }
+ THREADGROUP = new ThreadGroup(group, "InnocuousThreadGroup");
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/ThreadGroupUtils.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+package sun.misc;
+
+/**
+ * A utility class needed to access the root {@code ThreadGroup}
+ *
+ * The class should not depend on any others, because it' called from JNI_OnLoad of the AWT
+ * native library. Triggering class loading could could lead to a deadlock.
+ */
+public final class ThreadGroupUtils {
+
+ private ThreadGroupUtils() {
+ // Avoid instantiation
+ }
+
+ /**
+ * Returns a root thread group.
+ * Should be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
+ *
+ * @return a root {@code ThreadGroup}
+ */
+ public static ThreadGroup getRootThreadGroup() {
+ ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
+ ThreadGroup parentTG = currentTG.getParent();
+ while (parentTG != null) {
+ currentTG = parentTG;
+ parentTG = currentTG.getParent();
+ }
+ return currentTG;
+ }
+}
--- a/jdk/src/share/classes/sun/net/www/MimeTable.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/net/www/MimeTable.java Wed Apr 16 10:53:10 2014 -0700
@@ -225,39 +225,28 @@
public synchronized void load() {
Properties entries = new Properties();
File file = null;
- try {
- InputStream is;
- // First try to load the user-specific table, if it exists
- String userTablePath =
- System.getProperty("content.types.user.table");
- if (userTablePath != null) {
- file = new File(userTablePath);
- if (!file.exists()) {
- // No user-table, try to load the default built-in table.
- file = new File(System.getProperty("java.home") +
- File.separator +
- "lib" +
- File.separator +
- "content-types.properties");
- }
+ InputStream in;
+
+ // First try to load the user-specific table, if it exists
+ String userTablePath = System.getProperty("content.types.user.table");
+ if (userTablePath != null && (file = new File(userTablePath)).exists()) {
+ try {
+ in = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ System.err.println("Warning: " + file.getPath()
+ + " mime table not found.");
+ return;
}
- else {
- // No user table, try to load the default built-in table.
- file = new File(System.getProperty("java.home") +
- File.separator +
- "lib" +
- File.separator +
- "content-types.properties");
- }
+ } else {
+ in = MimeTable.class.getResourceAsStream("content-types.properties");
+ if (in == null)
+ throw new InternalError("default mime table not found");
+ }
- is = new BufferedInputStream(new FileInputStream(file));
- entries.load(is);
- is.close();
- }
- catch (IOException e) {
- System.err.println("Warning: default mime table not found: " +
- file.getPath());
- return;
+ try (BufferedInputStream bin = new BufferedInputStream(in)) {
+ entries.load(bin);
+ } catch (IOException e) {
+ System.err.println("Warning: " + e.getMessage());
}
parse(entries);
}
@@ -380,18 +369,6 @@
return MimeEntry.UNKNOWN;
}
- public synchronized boolean save(String filename) {
- if (filename == null) {
- filename = System.getProperty("user.home" +
- File.separator +
- "lib" +
- File.separator +
- "content-types.properties");
- }
-
- return saveAsProperties(new File(filename));
- }
-
public Properties getAsProperties() {
Properties properties = new Properties();
Enumeration<MimeEntry> e = elements();
--- a/jdk/src/share/classes/sun/nio/ch/Invoker.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Invoker.java Wed Apr 16 10:53:10 2014 -0700
@@ -130,6 +130,18 @@
// clear interrupt
Thread.interrupted();
+
+ // clear thread locals when in default thread pool
+ if (System.getSecurityManager() != null) {
+ Thread me = Thread.currentThread();
+ if (me instanceof sun.misc.InnocuousThread) {
+ GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+ ((sun.misc.InnocuousThread)me).eraseThreadLocals();
+ if (thisGroupAndInvokeCount != null) {
+ myGroupAndInvokeCount.set(thisGroupAndInvokeCount);
+ }
+ }
+ }
}
/**
--- a/jdk/src/share/classes/sun/nio/ch/ThreadPool.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/ThreadPool.java Wed Apr 16 10:53:10 2014 -0700
@@ -27,6 +27,7 @@
import java.util.concurrent.*;
import java.security.AccessController;
+import java.security.PrivilegedAction;
import sun.security.action.GetPropertyAction;
import sun.security.action.GetIntegerAction;
@@ -39,14 +40,6 @@
"java.nio.channels.DefaultThreadPool.threadFactory";
private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE =
"java.nio.channels.DefaultThreadPool.initialSize";
- private static final ThreadFactory defaultThreadFactory = new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setDaemon(true);
- return t;
- }
- };
private final ExecutorService executor;
@@ -79,7 +72,22 @@
}
static ThreadFactory defaultThreadFactory() {
- return defaultThreadFactory;
+ if (System.getSecurityManager() == null) {
+ return (Runnable r) -> {
+ Thread t = new Thread(r);
+ t.setDaemon(true);
+ return t;
+ };
+ } else {
+ return (Runnable r) -> {
+ PrivilegedAction<Thread> action = () -> {
+ Thread t = new sun.misc.InnocuousThread(r);
+ t.setDaemon(true);
+ return t;
+ };
+ return AccessController.doPrivileged(action);
+ };
+ }
}
private static class DefaultThreadPoolHolder {
@@ -100,7 +108,7 @@
// default to thread factory that creates daemon threads
ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory();
if (threadFactory == null)
- threadFactory = defaultThreadFactory;
+ threadFactory = defaultThreadFactory();
// create thread pool
ExecutorService executor = Executors.newCachedThreadPool(threadFactory);
return new ThreadPool(executor, false, initialSize);
--- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -179,8 +179,8 @@
md.update(p.getProperty(s).getBytes());
}
- md.update
- (InetAddress.getLocalHost().toString().getBytes());
+ // Include network adapter names (and a Mac address)
+ addNetworkAdapterInfo(md);
// The temporary dir
File f = new File(p.getProperty("java.io.tmpdir"));
@@ -221,6 +221,31 @@
return md.digest();
}
+ /*
+ * Include network adapter names and, if available, a Mac address
+ *
+ * See also java.util.concurrent.ThreadLocalRandom.initialSeed()
+ */
+ private static void addNetworkAdapterInfo(MessageDigest md) {
+
+ try {
+ Enumeration<NetworkInterface> ifcs =
+ NetworkInterface.getNetworkInterfaces();
+ while (ifcs.hasMoreElements()) {
+ NetworkInterface ifc = ifcs.nextElement();
+ md.update(ifc.toString().getBytes());
+ if (!ifc.isVirtual()) { // skip fake addresses
+ byte[] bs = ifc.getHardwareAddress();
+ if (bs != null) {
+ md.update(bs);
+ break;
+ }
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ }
+
/**
* Helper function to convert a long into a byte array (least significant
* byte first).
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Wed Apr 16 10:53:10 2014 -0700
@@ -75,7 +75,7 @@
private PublicKey prevPubKey;
private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
- EnumSet.of(CryptoPrimitive.SIGNATURE);
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
private final static DisabledAlgorithmConstraints
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
--- a/jdk/src/share/classes/sun/security/rsa/RSAPadding.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/rsa/RSAPadding.java Wed Apr 16 10:53:10 2014 -0700
@@ -25,11 +25,9 @@
package sun.security.rsa;
-import java.math.BigInteger;
import java.util.*;
import java.security.*;
-import java.security.interfaces.*;
import java.security.spec.*;
import javax.crypto.BadPaddingException;
@@ -41,21 +39,41 @@
/**
* RSA padding and unpadding.
*
- * Format of PKCS#1 v1.5 padding is:
+ * The various PKCS#1 versions can be found in the EMC/RSA Labs
+ * web site, which is currently:
+ *
+ * http://www.emc.com/emc-plus/rsa-labs/index.htm
+ *
+ * or in the IETF RFCs derived from the above PKCS#1 standards.
+ *
+ * RFC 2313: v1.5
+ * RFC 2437: v2.0
+ * RFC 3447: v2.1
+ *
+ * The format of PKCS#1 v1.5 padding is:
+ *
* 0x00 | BT | PS...PS | 0x00 | data...data
+ *
* where BT is the blocktype (1 or 2). The length of the entire string
* must be the same as the size of the modulus (i.e. 128 byte for a 1024 bit
* key). Per spec, the padding string must be at least 8 bytes long. That
* leaves up to (length of key in bytes) - 11 bytes for the data.
*
- * OAEP padding is a bit more complicated and has a number of options.
- * We support:
+ * OAEP padding was introduced in PKCS#1 v2.0 and is a bit more complicated
+ * and has a number of options. We support:
+ *
* . arbitrary hash functions ('Hash' in the specification), MessageDigest
* implementation must be available
* . MGF1 as the mask generation function
* . the empty string as the default value for label L and whatever
* specified in javax.crypto.spec.OAEPParameterSpec
*
+ * The algorithms (representations) are forwards-compatible: that is,
+ * the algorithm described in previous releases are in later releases.
+ * However, additional comments/checks/clarifications were added to the
+ * later versions based on real-world experience (e.g. stricter v1.5
+ * format checking.)
+ *
* Note: RSA keys should be at least 512 bits long
*
* @since 1.5
@@ -156,7 +174,8 @@
throw new InvalidAlgorithmParameterException
("Unsupported MGF algo: " + mgfName);
}
- mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters()).getDigestAlgorithm();
+ mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters())
+ .getDigestAlgorithm();
PSource pSrc = spec.getPSource();
String pSrcAlgo = pSrc.getAlgorithm();
if (!pSrcAlgo.equalsIgnoreCase("PSpecified")) {
@@ -198,7 +217,7 @@
*/
private static byte[] getInitialHash(MessageDigest md,
byte[] digestInput) {
- byte[] result = null;
+ byte[] result;
if ((digestInput == null) || (digestInput.length == 0)) {
String digestName = md.getAlgorithm();
result = emptyHashes.get(digestName);
@@ -213,8 +232,8 @@
}
/**
- * Return the maximum size of the plaintext data that can be processed using
- * this object.
+ * Return the maximum size of the plaintext data that can be processed
+ * using this object.
*/
public int getMaxDataSize() {
return maxDataSize;
@@ -262,7 +281,7 @@
*/
public byte[] unpad(byte[] padded) throws BadPaddingException {
if (padded.length != paddedSize) {
- throw new BadPaddingException("Padded length must be " + paddedSize);
+ throw new BadPaddingException("Decryption error");
}
switch (type) {
case PAD_NONE:
@@ -282,7 +301,8 @@
*/
private byte[] padV15(byte[] data) throws BadPaddingException {
byte[] padded = new byte[paddedSize];
- System.arraycopy(data, 0, padded, paddedSize - data.length, data.length);
+ System.arraycopy(data, 0, padded, paddedSize - data.length,
+ data.length);
int psSize = paddedSize - 3 - data.length;
int k = 0;
padded[k++] = 0;
@@ -317,55 +337,53 @@
}
/**
- * PKCS#1 v1.5 unpadding (blocktype 1 and 2).
+ * PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)).
*
* Note that we want to make it a constant-time operation
*/
private byte[] unpadV15(byte[] padded) throws BadPaddingException {
int k = 0;
- BadPaddingException bpe = null;
+ boolean bp = false;
if (padded[k++] != 0) {
- bpe = new BadPaddingException("Data must start with zero");
+ bp = true;
}
- if (padded[k++] != type && bpe == null) {
- bpe = new BadPaddingException("Blocktype mismatch: " + padded[1]);
+ if (padded[k++] != type) {
+ bp = true;
}
int p = 0;
while (k < padded.length) {
int b = padded[k++] & 0xff;
- if (b == 0 && p == 0) {
+ if ((b == 0) && (p == 0)) {
p = k;
}
- if (k == padded.length && p == 0 && bpe == null) {
- bpe = new BadPaddingException("Padding string not terminated");
+ if ((k == padded.length) && (p == 0)) {
+ bp = true;
}
if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) &&
- p == 0 && bpe == null) {
- bpe = new BadPaddingException("Padding byte not 0xff: " + b);
+ (p == 0)) {
+ bp = true;
}
}
int n = padded.length - p;
- if (n > maxDataSize && bpe == null) {
- bpe = new BadPaddingException("Padding string too short");
+ if (n > maxDataSize) {
+ bp = true;
}
// copy useless padding array for a constant-time method
- //
- // Is it necessary?
byte[] padding = new byte[p];
System.arraycopy(padded, 0, padding, 0, p);
byte[] data = new byte[n];
System.arraycopy(padded, p, data, 0, n);
- if (bpe == null) {
- bpe = new BadPaddingException("Unused exception");
- } else {
+ BadPaddingException bpe = new BadPaddingException("Decryption error");
+
+ if (bp) {
throw bpe;
+ } else {
+ return data;
}
-
- return data;
}
/**
@@ -424,10 +442,11 @@
*/
private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
byte[] EM = padded;
+ boolean bp = false;
int hLen = lHash.length;
if (EM[0] != 0) {
- throw new BadPaddingException("Data must start with zero");
+ bp = true;
}
int seedStart = 1;
@@ -442,29 +461,48 @@
// verify lHash == lHash'
for (int i = 0; i < hLen; i++) {
if (lHash[i] != EM[dbStart + i]) {
- throw new BadPaddingException("lHash mismatch");
+ bp = true;
+ }
+ }
+
+ int padStart = dbStart + hLen;
+ int onePos = -1;
+
+ for (int i = padStart; i < EM.length; i++) {
+ int value = EM[i];
+ if (onePos == -1) {
+ if (value == 0x00) {
+ // continue;
+ } else if (value == 0x01) {
+ onePos = i;
+ } else { // Anything other than {0,1} is bad.
+ bp = true;
+ }
}
}
- // skip over padding (0x00 bytes)
- int i = dbStart + hLen;
- while (EM[i] == 0) {
- i++;
- if (i >= EM.length) {
- throw new BadPaddingException("Padding string not terminated");
- }
+ // We either ran off the rails or found something other than 0/1.
+ if (onePos == -1) {
+ bp = true;
+ onePos = EM.length - 1; // Don't inadvertently return any data.
}
- if (EM[i++] != 1) {
- throw new BadPaddingException
- ("Padding string not terminated by 0x01 byte");
- }
+ int mStart = onePos + 1;
+
+ // copy useless padding array for a constant-time method
+ byte [] tmp = new byte[mStart - padStart];
+ System.arraycopy(EM, padStart, tmp, 0, tmp.length);
- int mLen = EM.length - i;
- byte[] m = new byte[mLen];
- System.arraycopy(EM, i, m, 0, mLen);
+ byte [] m = new byte[EM.length - mStart];
+ System.arraycopy(EM, mStart, m, 0, m.length);
+
+ BadPaddingException bpe = new BadPaddingException("Decryption error");
- return m;
+ if (bp) {
+ throw bpe;
+ } else {
+ return m;
+ }
}
/**
@@ -499,5 +537,4 @@
}
}
}
-
}
--- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Wed Apr 16 10:53:10 2014 -0700
@@ -68,7 +68,7 @@
// performance optimization
private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
- EnumSet.of(CryptoPrimitive.SIGNATURE);
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
// supported pairs of signature and hash algorithm
private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Wed Apr 16 10:53:10 2014 -0700
@@ -90,9 +90,6 @@
private static final String META_INF = "META-INF/";
- // prefix for new signature-related files in META-INF directory
- private static final String SIG_PREFIX = META_INF + "SIG-";
-
private static final Class<?>[] PARAM_STRING = { String.class };
private static final String NONE = "NONE";
@@ -1522,22 +1519,7 @@
* . META-INF/*.EC
*/
private boolean signatureRelated(String name) {
- String ucName = name.toUpperCase(Locale.ENGLISH);
- if (ucName.equals(JarFile.MANIFEST_NAME) ||
- ucName.equals(META_INF) ||
- (ucName.startsWith(SIG_PREFIX) &&
- ucName.indexOf("/") == ucName.lastIndexOf("/"))) {
- return true;
- }
-
- if (ucName.startsWith(META_INF) &&
- SignatureFileVerifier.isBlockOrSF(ucName)) {
- // .SF/.DSA/.RSA/.EC files in META-INF subdirs
- // are not considered signature-related
- return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
- }
-
- return false;
+ return SignatureFileVerifier.isSigningRelated(name);
}
Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Wed Apr 16 10:53:10 2014 -0700
@@ -152,6 +152,52 @@
return false;
}
+ /**
+ * Yet another utility method used by JarVerifier and JarSigner
+ * to determine what files are signature related, which includes
+ * the MANIFEST, SF files, known signature block files, and other
+ * unknown signature related files (those starting with SIG- with
+ * an optional [A-Z0-9]{1,3} extension right inside META-INF).
+ *
+ * @param s file name
+ * @return true if the input file name is signature related
+ */
+ public static boolean isSigningRelated(String name) {
+ name = name.toUpperCase(Locale.ENGLISH);
+ if (!name.startsWith("META-INF/")) {
+ return false;
+ }
+ name = name.substring(9);
+ if (name.indexOf('/') != -1) {
+ return false;
+ }
+ if (isBlockOrSF(name) || name.equals("MANIFEST.MF")) {
+ return true;
+ } else if (name.startsWith("SIG-")) {
+ // check filename extension
+ // see http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures
+ // for what filename extensions are legal
+ int extIndex = name.lastIndexOf('.');
+ if (extIndex != -1) {
+ String ext = name.substring(extIndex + 1);
+ // validate length first
+ if (ext.length() > 3 || ext.length() < 1) {
+ return false;
+ }
+ // then check chars, must be in [a-zA-Z0-9] per the jar spec
+ for (int index = 0; index < ext.length(); index++) {
+ char cc = ext.charAt(index);
+ // chars are promoted to uppercase so skip lowercase checks
+ if ((cc < 'A' || cc > 'Z') && (cc < '0' || cc > '9')) {
+ return false;
+ }
+ }
+ }
+ return true; // no extension is OK
+ }
+ return false;
+ }
+
/** get digest from cache */
private MessageDigest getDigest(String algorithm)
--- a/jdk/src/share/demo/nio/zipfs/Demo.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,709 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.spi.*;
-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 Demo action ZipfileName [...]
- *
- * @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
-
- copyin_attrs, // <java Demo copyin_attrs zipfile src dst>
- // copy an external src file into zipfile
- // as entry dst, with attributes (timestamp)
-
- copyout, // <java Demo copyout zipfile src dst>
- // copy zipfile entry src" out to file dst
-
- copyout_attrs, // <java Demo copyout_attrs zipfile src 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
-
- setatime, // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
- setctime, // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" 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
-
- prof,
- }
-
- public static void main(String[] args) throws Throwable {
- FileSystemProvider provider = getZipFSProvider();
- if (provider == null) {
- System.err.println("ZIP filesystem provider is not installed");
- System.exit(1);
- }
-
- Action action = Action.valueOf(args[0]);
- Map<String, Object> env = env = new HashMap<>();
- if (action == Action.create)
- env.put("create", "true");
- try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
- Path path, src, dst;
- switch (action) {
- case rename:
- src = fs.getPath(args[2]);
- dst = fs.getPath(args[3]);
- Files.move(src, dst);
- break;
- case moveout:
- src = fs.getPath(args[2]);
- dst = Paths.get(args[3]);
- Files.move(src, dst);
- break;
- case movein:
- src = Paths.get(args[2]);
- dst = fs.getPath(args[3]);
- Files.move(src, dst);
- break;
- case copy:
- src = fs.getPath(args[2]);
- dst = fs.getPath(args[3]);
- Files.copy(src, dst);
- break;
- case copyout:
- src = fs.getPath(args[2]);
- dst = Paths.get(args[3]);
- Files.copy(src, dst);
- break;
- case copyin:
- src = Paths.get(args[2]);
- dst = fs.getPath(args[3]);
- Files.copy(src, dst);
- break;
- case copyin_attrs:
- src = Paths.get(args[2]);
- dst = fs.getPath(args[3]);
- Files.copy(src, dst, COPY_ATTRIBUTES);
- break;
- case copyout_attrs:
- src = fs.getPath(args[2]);
- dst = Paths.get(args[3]);
- Files.copy(src, dst, COPY_ATTRIBUTES);
- break;
- case zzmove:
- try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
- z2zmove(fs, fs2, args[3]);
- }
- break;
- case zzcopy:
- try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
- z2zcopy(fs, fs2, args[3]);
- }
- break;
- case attrs:
- for (int i = 2; i < args.length; i++) {
- path = fs.getPath(args[i]);
- System.out.println(path);
- System.out.println(
- Files.readAttributes(path, BasicFileAttributes.class).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]);
- Files.setAttribute(path, "lastModifiedTime",
- FileTime.fromMillis(newDatetime.getTime()));
- System.out.println(
- Files.readAttributes(path, BasicFileAttributes.class).toString());
- }
- break;
- case setctime:
- df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
- newDatetime = df.parse(args[2]);
- for (int i = 3; i < args.length; i++) {
- path = fs.getPath(args[i]);
- Files.setAttribute(path, "creationTime",
- FileTime.fromMillis(newDatetime.getTime()));
- System.out.println(
- Files.readAttributes(path, BasicFileAttributes.class).toString());
- }
- break;
- case setatime:
- df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
- newDatetime = df.parse(args[2]);
- for (int i = 3; i < args.length; i++) {
- path = fs.getPath(args[i]);
- Files.setAttribute(path, "lastAccessTime",
- FileTime.fromMillis(newDatetime.getTime()));
- System.out.println(
- Files.readAttributes(path, BasicFileAttributes.class).toString());
- }
- break;
- case attrsspace:
- path = fs.getPath("/");
- FileStore fstore = Files.getFileStore(path);
- System.out.printf("filestore[%s]%n", fstore.name());
- System.out.printf(" totalSpace: %d%n",
- (Long)fstore.getAttribute("totalSpace"));
- System.out.printf(" usableSpace: %d%n",
- (Long)fstore.getAttribute("usableSpace"));
- System.out.printf(" unallocSpace: %d%n",
- (Long)fstore.getAttribute("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++)
- Files.delete(fs.getPath(args[i]));
- 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]:"";
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(path,
- new DirectoryStream.Filter<Path>() {
- @Override
- public boolean accept(Path path) {
- return path.toString().contains(fStr);
- }
- }))
- {
- for (Path p : ds)
- System.out.println(p);
- }
- break;
- case mkdir:
- Files.createDirectory(fs.getPath(args[2]));
- 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.printf("%n%s%n", path);
- System.out.println("-------(1)---------");
- System.out.println(
- Files.readAttributes(path, BasicFileAttributes.class).toString());
- System.out.println("-------(2)---------");
- Map<String, Object> map = Files.readAttributes(path, "zip:*");
- for (Map.Entry<String, Object> e : map.entrySet()) {
- System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
- }
- System.out.println("-------(3)---------");
- map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory");
- for (Map.Entry<String, ?> e : map.entrySet()) {
- System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
- }
- }
- break;
- case prof:
- list(fs.getPath("/"), false);
- while (true) {
- Thread.sleep(10000);
- //list(fs.getPath("/"), true);
- System.out.println("sleeping...");
- }
- }
- } catch (Exception x) {
- x.printStackTrace();
- }
- }
-
- private static FileSystemProvider getZipFSProvider() {
- for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
- if ("jar".equals(provider.getScheme()))
- return provider;
- }
- return null;
- }
-
- @SuppressWarnings("unused")
- /**
- * Not used in demo, but included for demonstrational purposes.
- */
- private static byte[] getBytes(String name) {
- return name.getBytes();
- }
-
- @SuppressWarnings("unused")
- /**
- * Not used in demo, but included for demonstrational purposes.
- */
- 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.getFileName().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 (Files.isDirectory(src)) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
- for (Path child : ds)
- update(fs, child.toString());
- }
- } else {
- Path dst = fs.getPath(path);
- Path parent = dst.getParent();
- if (parent != null && Files.notExists(parent))
- mkdirs(parent);
- Files.copy(src, dst, REPLACE_EXISTING);
- }
- }
-
- private static void extract(FileSystem fs, String path) throws Throwable{
- Path src = fs.getPath(path);
- if (Files.isDirectory(src)) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
- for (Path child : ds)
- extract(fs, child.toString());
- }
- } else {
- if (path.startsWith("/"))
- path = path.substring(1);
- Path dst = FileSystems.getDefault().getPath(path);
- Path parent = dst.getParent();
- if (Files.notExists(parent))
- mkdirs(parent);
- Files.copy(src, 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 (Files.isDirectory(srcPath)) {
- if (!Files.exists(dstPath)) {
- try {
- mkdirs(dstPath);
- } catch (FileAlreadyExistsException x) {}
- }
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
- for (Path child : ds) {
- z2zcopy(src, dst,
- path + (path.endsWith("/")?"":"/") + child.getFileName());
- }
- }
- } else {
- //System.out.println("copying..." + path);
- Files.copy(srcPath, 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 && Files.notExists(parent))
- mkdirs(parent);
- Files.move(file, 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 (Files.notExists(dst))
- mkdirs(dst);
- } catch (IOException x) {
- x.printStackTrace();
- }
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(Path dir,
- IOException ioe)
- throws IOException
- {
- try {
- Files.delete(dir);
- } 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 (Files.notExists(parent))
- mkdirs(parent);
- }
- Files.createDirectory(path);
- }
-
- @SuppressWarnings("unused")
- /**
- * Not used in demo, but included for demonstrational purposes.
- */
- private static void rmdirs(Path path) throws IOException {
- while (path != null && path.getNameCount() != 0) {
- Files.delete(path);
- path = path.getParent();
- }
- }
-
- private static void list(Path path, boolean verbose ) throws IOException {
- if (!"/".equals(path.toString())) {
- System.out.printf(" %s%n", path.toString());
- if (verbose)
- System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString());
- }
- if (Files.notExists(path))
- return;
- if (Files.isDirectory(path)) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
- for (Path child : ds)
- list(child, verbose);
- }
- }
- }
-
- @SuppressWarnings("unused")
- /**
- * Checks that the content of two paths are equal.
- * Not used in demo, but included for demonstrational purposes.
- */
- private static void checkEqual(Path src, Path dst) throws IOException
- {
- //System.out.printf("checking <%s> vs <%s>...%n",
- // src.toString(), dst.toString());
-
- //streams
- byte[] bufSrc = new byte[8192];
- byte[] bufDst = new byte[8192];
- try (InputStream isSrc = Files.newInputStream(src);
- InputStream isDst = Files.newInputStream(dst))
- {
- 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--;
- }
- }
- }
-
- // channels
-
- try (SeekableByteChannel chSrc = Files.newByteChannel(src);
- SeekableByteChannel chDst = Files.newByteChannel(dst))
- {
- 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);
-
- 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();
- }
- }
-
- 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);
-
- try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read);
- FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite))
- {
- ByteBuffer bb = ByteBuffer.allocate(8192);
- while (srcFc.read(bb) >= 0) {
- bb.flip();
- dstFc.write(bb);
- bb.clear();
- }
- }
- }
-
- 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);
-
- try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
- SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
- {
- ByteBuffer bb = ByteBuffer.allocate(8192);
- while (srcCh.read(bb) >= 0) {
- bb.flip();
- dstCh.write(bb);
- bb.clear();
- }
- }
- }
-
- private static void streamCopy(Path src, Path dst) throws IOException
- {
- byte[] buf = new byte[8192];
- try (InputStream isSrc = Files.newInputStream(src);
- OutputStream osDst = Files.newOutputStream(dst))
- {
- int n = 0;
- while ((n = isSrc.read(buf)) != -1) {
- osDst.write(buf, 0, n);
- }
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/README.txt Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-ZipFileSystem is a file system provider that treats the contents of a zip or
-JAR file as a java.nio.file.FileSystem.
-
-The factory methods defined by the java.nio.file.FileSystems class can be
-used to create a FileSystem, eg:
-
- // use file type detection
- Path jarfile = Paths.get("foo.jar");
- FileSystem fs = FileSystems.newFileSystem(jarfile, null);
-
--or
-
- // locate file system by the legacy JAR URL syntax
- Map<String,?> env = Collections.emptyMap();
- URI uri = URI.create("jar:file:/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();
-
-See Demo.java for more interesting usages.
-
-
--- a/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-com.sun.nio.zipfs.ZipFileSystemProvider
-
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-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
- }
- }
-
- @Override
- public Path getPath(URI uri) {
- FileSystem fs = getFileSystem(uri);
- String path = uri.getFragment();
- if (path == null) {
- String uristr = uri.toString();
- int off = uristr.indexOf("!/");
- if (off != -1)
- path = uristr.substring(off + 2);
- }
- if (path != null)
- return fs.getPath(path);
- throw new IllegalArgumentException("URI: "
- + uri
- + " does not contain path fragment ex. jar:///c:/foo.zip!/BAR");
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-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;
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-
-/**
- *
- * @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;
- static final int METHOD_AES = 99;
-
- /*
- * 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
- static final int EXTID_EFS = 0x0017; // Strong Encryption
- static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp
-
- /*
- * fields access methods
- */
- ///////////////////////////////////////////////////////
- static final int CH(byte[] b, int n) {
- return Byte.toUnsignedInt(b[n]);
- }
-
- static final int SH(byte[] b, int n) {
- return Byte.toUnsignedInt(b[n]) | (Byte.toUnsignedInt(b[n + 1]) << 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
-
- // central directory header (CEN) fields
- static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
- static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
- static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
- static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
- static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
- static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
- static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
- static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
- static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
- static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
- static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
- static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
- static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
- static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
- static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
- static final long CENOFF(byte[] 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;
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-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;
-
-/**
- *
- * @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;
- }
-
-
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.attribute.*;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/*
- * @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);
- if (AttrID.valueOf(attribute) == AttrID.lastAccessTime)
- setTimes (null, (FileTime)value, null);
- if (AttrID.valueOf(attribute) == AttrID.creationTime)
- setTimes (null, null, (FileTime)value);
- return;
- } catch (IllegalArgumentException x) {}
- throw new UnsupportedOperationException("'" + attribute +
- "' is unknown or read-only attribute");
- }
-
- Map<String, Object> readAttributes(String attributes)
- throws IOException
- {
- ZipFileAttributes zfas = readAttributes();
- LinkedHashMap<String, Object> map = new LinkedHashMap<>();
- if ("*".equals(attributes)) {
- for (AttrID id : AttrID.values()) {
- try {
- map.put(id.name(), attribute(id, zfas));
- } catch (IllegalArgumentException x) {}
- }
- } else {
- String[] as = attributes.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;
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-
-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(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(e.atime);
- return null;
- }
-
- @Override
- public FileTime lastModifiedTime() {
- return FileTime.fromMillis(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 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(1024);
- Formatter fm = new Formatter(sb);
- if (creationTime() != null)
- fm.format(" creationTime : %tc%n", creationTime().toMillis());
- else
- fm.format(" creationTime : null%n");
-
- 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();
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileAttributeView;
-import java.nio.file.attribute.FileStoreAttributeView;
-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 = 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();
- return (V)null;
- }
-
- @Override
- public long getTotalSpace() throws IOException {
- return new ZipFileStoreAttributes(this).totalSpace();
- }
-
- @Override
- public long getUsableSpace() throws IOException {
- return new ZipFileStoreAttributes(this).usableSpace();
- }
-
- @Override
- public long getUnallocatedSpace() throws IOException {
- return new ZipFileStoreAttributes(this).unallocatedSpace();
- }
-
- @Override
- public Object getAttribute(String attribute) throws IOException {
- if (attribute.equals("totalSpace"))
- return getTotalSpace();
- if (attribute.equals("usableSpace"))
- return getUsableSpace();
- if (attribute.equals("unallocatedSpace"))
- return getUnallocatedSpace();
- throw new UnsupportedOperationException("does not support the given attribute");
- }
-
- private static class ZipFileStoreAttributes {
- final FileStore fstore;
- final long size;
-
- public ZipFileStoreAttributes(ZipFileStore fileStore)
- throws IOException
- {
- Path path = FileSystems.getDefault().getPath(fileStore.name());
- this.size = Files.size(path);
- this.fstore = Files.getFileStore(path);
- }
-
- public long totalSpace() {
- return size;
- }
-
- public long usableSpace() throws IOException {
- if (!fstore.isReadOnly())
- return fstore.getUsableSpace();
- return 0;
- }
-
- public long unallocatedSpace() throws IOException {
- if (!fstore.isReadOnly())
- return fstore.getUnallocatedSpace();
- return 0;
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2398 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.*;
-import java.util.*;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-import java.util.zip.Inflater;
-import java.util.zip.Deflater;
-import java.util.zip.InflaterInputStream;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.ZipException;
-import java.util.zip.ZipError;
-import static java.lang.Boolean.*;
-import static com.sun.nio.zipfs.ZipConstants.*;
-import static com.sun.nio.zipfs.ZipUtils.*;
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-
-/**
- * A FileSystem built on a zip file
- *
- * @author Xueming Shen
- */
-
-public class ZipFileSystem extends FileSystem {
-
- private final ZipFileSystemProvider provider;
- private final ZipPath defaultdir;
- private boolean readOnly = false;
- private final Path zfpath;
- private final ZipCoder zc;
-
- // configurable by env map
- private final String defaultDir; // default dir for the file system
- private final String nameEncoding; // default encoding for name/comment
- private final boolean useTempFile; // use a temp file for newOS, default
- // is to use BAOS for better performance
- private final boolean createNew; // create a new zip if not exists
- private static final boolean isWindows =
- System.getProperty("os.name").startsWith("Windows");
-
- ZipFileSystem(ZipFileSystemProvider provider,
- Path zfpath,
- Map<String, ?> env)
- throws IOException
- {
- // configurable env setup
- this.createNew = "true".equals(env.get("create"));
- this.nameEncoding = env.containsKey("encoding") ?
- (String)env.get("encoding") : "UTF-8";
- this.useTempFile = TRUE.equals(env.get("useTempFile"));
- this.defaultDir = env.containsKey("default.dir") ?
- (String)env.get("default.dir") : "/";
- if (this.defaultDir.charAt(0) != '/')
- throw new IllegalArgumentException("default dir should be absolute");
-
- this.provider = provider;
- this.zfpath = zfpath;
- if (Files.notExists(zfpath)) {
- if (createNew) {
- try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) {
- new END().write(os, 0);
- }
- } else {
- throw new FileSystemNotFoundException(zfpath.toString());
- }
- }
- // sm and existence check
- zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
- if (!Files.isWritable(zfpath))
- this.readOnly = true;
- this.zc = ZipCoder.get(nameEncoding);
- this.defaultdir = new ZipPath(this, getBytes(defaultDir));
- this.ch = Files.newByteChannel(zfpath, READ);
- this.cen = initCEN();
- }
-
- @Override
- public FileSystemProvider provider() {
- return provider;
- }
-
- @Override
- public String getSeparator() {
- return "/";
- }
-
- @Override
- public boolean isOpen() {
- return isOpen;
- }
-
- @Override
- public boolean isReadOnly() {
- return readOnly;
- }
-
- private void checkWritable() throws IOException {
- if (readOnly)
- throw new ReadOnlyFileSystemException();
- }
-
- @Override
- public Iterable<Path> getRootDirectories() {
- ArrayList<Path> pathArr = new ArrayList<>();
- pathArr.add(new ZipPath(this, new byte[]{'/'}));
- return pathArr;
- }
-
- ZipPath getDefaultDir() { // package private
- return defaultdir;
- }
-
- @Override
- public ZipPath getPath(String first, String... more) {
- String path;
- if (more.length == 0) {
- path = first;
- } else {
- StringBuilder sb = new StringBuilder();
- sb.append(first);
- for (String segment: more) {
- if (segment.length() > 0) {
- if (sb.length() > 0)
- sb.append('/');
- sb.append(segment);
- }
- }
- path = sb.toString();
- }
- return new ZipPath(this, getBytes(path));
- }
-
- @Override
- public UserPrincipalLookupService getUserPrincipalLookupService() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public WatchService newWatchService() {
- throw new UnsupportedOperationException();
- }
-
- FileStore getFileStore(ZipPath path) {
- return new ZipFileStore(path);
- }
-
- @Override
- public Iterable<FileStore> getFileStores() {
- ArrayList<FileStore> list = new ArrayList<>(1);
- list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'})));
- return list;
- }
-
- private static final Set<String> supportedFileAttributeViews =
- Collections.unmodifiableSet(
- new HashSet<String>(Arrays.asList("basic", "zip")));
-
- @Override
- public Set<String> supportedFileAttributeViews() {
- return supportedFileAttributeViews;
- }
-
- @Override
- public String toString() {
- return zfpath.toString();
- }
-
- Path getZipFile() {
- return zfpath;
- }
-
- private static final String GLOB_SYNTAX = "glob";
- private static final String REGEX_SYNTAX = "regex";
-
- @Override
- public PathMatcher getPathMatcher(String syntaxAndInput) {
- int pos = syntaxAndInput.indexOf(':');
- if (pos <= 0 || pos == syntaxAndInput.length()) {
- throw new IllegalArgumentException();
- }
- String syntax = syntaxAndInput.substring(0, pos);
- String input = syntaxAndInput.substring(pos + 1);
- String expr;
- if (syntax.equals(GLOB_SYNTAX)) {
- expr = toRegexPattern(input);
- } else {
- if (syntax.equals(REGEX_SYNTAX)) {
- expr = input;
- } else {
- throw new UnsupportedOperationException("Syntax '" + syntax +
- "' not recognized");
- }
- }
- // return matcher
- final Pattern pattern = Pattern.compile(expr);
- return new PathMatcher() {
- @Override
- public boolean matches(Path path) {
- return pattern.matcher(path.toString()).matches();
- }
- };
- }
-
- @Override
- public void close() throws IOException {
- beginWrite();
- try {
- if (!isOpen)
- return;
- isOpen = false; // set closed
- } finally {
- endWrite();
- }
- if (!streams.isEmpty()) { // unlock and close all remaining streams
- Set<InputStream> copy = new HashSet<>(streams);
- for (InputStream is: copy)
- is.close();
- }
- beginWrite(); // lock and sync
- try {
- sync();
- ch.close(); // close the ch just in case no update
- } finally { // and sync dose not close the ch
- endWrite();
- }
-
- synchronized (inflaters) {
- for (Inflater inf : inflaters)
- inf.end();
- }
- synchronized (deflaters) {
- for (Deflater def : deflaters)
- def.end();
- }
-
- IOException ioe = null;
- synchronized (tmppaths) {
- for (Path p: tmppaths) {
- try {
- Files.deleteIfExists(p);
- } catch (IOException x) {
- if (ioe == null)
- ioe = x;
- else
- ioe.addSuppressed(x);
- }
- }
- }
- provider.removeFileSystem(zfpath, this);
- if (ioe != null)
- throw ioe;
- }
-
- ZipFileAttributes getFileAttributes(byte[] path)
- throws IOException
- {
- Entry e;
- beginRead();
- try {
- ensureOpen();
- e = getEntry0(path);
- if (e == null) {
- IndexNode inode = getInode(path);
- if (inode == null)
- return null;
- e = new Entry(inode.name); // pseudo directory
- e.method = METHOD_STORED; // STORED for dir
- e.mtime = e.atime = e.ctime = -1;// -1 for all times
- }
- } finally {
- endRead();
- }
- return new ZipFileAttributes(e);
- }
-
- void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
- throws IOException
- {
- checkWritable();
- beginWrite();
- try {
- ensureOpen();
- Entry e = getEntry0(path); // ensureOpen checked
- if (e == null)
- throw new NoSuchFileException(getString(path));
- if (e.type == Entry.CEN)
- e.type = Entry.COPY; // copy e
- if (mtime != null)
- e.mtime = mtime.toMillis();
- if (atime != null)
- e.atime = atime.toMillis();
- if (ctime != null)
- e.ctime = ctime.toMillis();
- update(e);
- } finally {
- endWrite();
- }
- }
-
- boolean exists(byte[] path)
- throws IOException
- {
- beginRead();
- try {
- ensureOpen();
- return getInode(path) != null;
- } finally {
- endRead();
- }
- }
-
- boolean isDirectory(byte[] path)
- throws IOException
- {
- beginRead();
- try {
- IndexNode n = getInode(path);
- return n != null && n.isDir();
- } finally {
- endRead();
- }
- }
-
- private ZipPath toZipPath(byte[] path) {
- // make it absolute
- byte[] p = new byte[path.length + 1];
- p[0] = '/';
- System.arraycopy(path, 0, p, 1, path.length);
- return new ZipPath(this, p);
- }
-
- // returns the list of child paths of "path"
- Iterator<Path> iteratorOf(byte[] path,
- DirectoryStream.Filter<? super Path> filter)
- throws IOException
- {
- beginWrite(); // iteration of inodes needs exclusive lock
- try {
- ensureOpen();
- IndexNode inode = getInode(path);
- if (inode == null)
- throw new NotDirectoryException(getString(path));
- List<Path> list = new ArrayList<>();
- IndexNode child = inode.child;
- while (child != null) {
- ZipPath zp = toZipPath(child.name);
- if (filter == null || filter.accept(zp))
- list.add(zp);
- child = child.sibling;
- }
- return list.iterator();
- } finally {
- endWrite();
- }
- }
-
- void createDirectory(byte[] dir, FileAttribute<?>... attrs)
- throws IOException
- {
- checkWritable();
- dir = toDirectoryPath(dir);
- beginWrite();
- try {
- ensureOpen();
- if (dir.length == 0 || exists(dir)) // root dir, or exiting dir
- throw new FileAlreadyExistsException(getString(dir));
- checkParents(dir);
- Entry e = new Entry(dir, Entry.NEW);
- e.method = METHOD_STORED; // STORED for dir
- update(e);
- } finally {
- endWrite();
- }
- }
-
- void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options)
- throws IOException
- {
- checkWritable();
- if (Arrays.equals(src, dst))
- return; // do nothing, src and dst are the same
-
- beginWrite();
- try {
- ensureOpen();
- Entry eSrc = getEntry0(src); // ensureOpen checked
- if (eSrc == null)
- throw new NoSuchFileException(getString(src));
- if (eSrc.isDir()) { // spec says to create dst dir
- createDirectory(dst);
- return;
- }
- boolean hasReplace = false;
- boolean hasCopyAttrs = false;
- for (CopyOption opt : options) {
- if (opt == REPLACE_EXISTING)
- hasReplace = true;
- else if (opt == COPY_ATTRIBUTES)
- hasCopyAttrs = true;
- }
- Entry eDst = getEntry0(dst);
- if (eDst != null) {
- if (!hasReplace)
- throw new FileAlreadyExistsException(getString(dst));
- } else {
- checkParents(dst);
- }
- Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
- u.name(dst); // change name
- if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
- {
- u.type = eSrc.type; // make it the same type
- if (deletesrc) { // if it's a "rename", take the data
- u.bytes = eSrc.bytes;
- u.file = eSrc.file;
- } else { // if it's not "rename", copy the data
- if (eSrc.bytes != null)
- u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
- else if (eSrc.file != null) {
- u.file = getTempPathForEntry(null);
- Files.copy(eSrc.file, u.file, REPLACE_EXISTING);
- }
- }
- }
- if (!hasCopyAttrs)
- u.mtime = u.atime= u.ctime = System.currentTimeMillis();
- update(u);
- if (deletesrc)
- updateDelete(eSrc);
- } finally {
- endWrite();
- }
- }
-
- // Returns an output stream for writing the contents into the specified
- // entry.
- OutputStream newOutputStream(byte[] path, OpenOption... options)
- throws IOException
- {
- checkWritable();
- boolean hasCreateNew = false;
- boolean hasCreate = false;
- boolean hasAppend = false;
- for (OpenOption opt: options) {
- if (opt == READ)
- throw new IllegalArgumentException("READ not allowed");
- if (opt == CREATE_NEW)
- hasCreateNew = true;
- if (opt == CREATE)
- hasCreate = true;
- if (opt == APPEND)
- hasAppend = true;
- }
- beginRead(); // only need a readlock, the "update()" will
- try { // try to obtain a writelock when the os is
- ensureOpen(); // being closed.
- Entry e = getEntry0(path);
- if (e != null) {
- if (e.isDir() || hasCreateNew)
- throw new FileAlreadyExistsException(getString(path));
- if (hasAppend) {
- InputStream is = getInputStream(e);
- OutputStream os = getOutputStream(new Entry(e, Entry.NEW));
- copyStream(is, os);
- is.close();
- return os;
- }
- return getOutputStream(new Entry(e, Entry.NEW));
- } else {
- if (!hasCreate && !hasCreateNew)
- throw new NoSuchFileException(getString(path));
- checkParents(path);
- return getOutputStream(new Entry(path, Entry.NEW));
- }
- } finally {
- endRead();
- }
- }
-
- // Returns an input stream for reading the contents of the specified
- // file entry.
- InputStream newInputStream(byte[] path) throws IOException {
- beginRead();
- try {
- ensureOpen();
- Entry e = getEntry0(path);
- if (e == null)
- throw new NoSuchFileException(getString(path));
- if (e.isDir())
- throw new FileSystemException(getString(path), "is a directory", null);
- return getInputStream(e);
- } finally {
- endRead();
- }
- }
-
- private void checkOptions(Set<? extends OpenOption> options) {
- // check for options of null type and option is an intance of StandardOpenOption
- for (OpenOption option : options) {
- if (option == null)
- throw new NullPointerException();
- if (!(option instanceof StandardOpenOption))
- throw new IllegalArgumentException();
- }
- }
-
- // Returns a Writable/ReadByteChannel for now. Might consdier to use
- // newFileChannel() instead, which dump the entry data into a regular
- // file on the default file system and create a FileChannel on top of
- // it.
- SeekableByteChannel newByteChannel(byte[] path,
- Set<? extends OpenOption> options,
- FileAttribute<?>... attrs)
- throws IOException
- {
- checkOptions(options);
- if (options.contains(StandardOpenOption.WRITE) ||
- options.contains(StandardOpenOption.APPEND)) {
- checkWritable();
- beginRead();
- try {
- final WritableByteChannel wbc = Channels.newChannel(
- newOutputStream(path, options.toArray(new OpenOption[0])));
- long leftover = 0;
- if (options.contains(StandardOpenOption.APPEND)) {
- Entry e = getEntry0(path);
- if (e != null && e.size >= 0)
- leftover = e.size;
- }
- final long offset = leftover;
- return new SeekableByteChannel() {
- long written = offset;
- public boolean isOpen() {
- return wbc.isOpen();
- }
-
- public long position() throws IOException {
- return written;
- }
-
- public SeekableByteChannel position(long pos)
- throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
- public int read(ByteBuffer dst) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public SeekableByteChannel truncate(long size)
- throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
- public int write(ByteBuffer src) throws IOException {
- int n = wbc.write(src);
- written += n;
- return n;
- }
-
- public long size() throws IOException {
- return written;
- }
-
- public void close() throws IOException {
- wbc.close();
- }
- };
- } finally {
- endRead();
- }
- } else {
- beginRead();
- try {
- ensureOpen();
- Entry e = getEntry0(path);
- if (e == null || e.isDir())
- throw new NoSuchFileException(getString(path));
- final ReadableByteChannel rbc =
- Channels.newChannel(getInputStream(e));
- final long size = e.size;
- return new SeekableByteChannel() {
- long read = 0;
- public boolean isOpen() {
- return rbc.isOpen();
- }
-
- public long position() throws IOException {
- return read;
- }
-
- public SeekableByteChannel position(long pos)
- throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
- public int read(ByteBuffer dst) throws IOException {
- int n = rbc.read(dst);
- if (n > 0) {
- read += n;
- }
- return n;
- }
-
- public SeekableByteChannel truncate(long size)
- throws IOException
- {
- throw new NonWritableChannelException();
- }
-
- public int write (ByteBuffer src) throws IOException {
- throw new NonWritableChannelException();
- }
-
- public long size() throws IOException {
- return size;
- }
-
- public void close() throws IOException {
- rbc.close();
- }
- };
- } finally {
- endRead();
- }
- }
- }
-
- // Returns a FileChannel of the specified entry.
- //
- // This implementation creates a temporary file on the default file system,
- // copy the entry data into it if the entry exists, and then create a
- // FileChannel on top of it.
- FileChannel newFileChannel(byte[] path,
- Set<? extends OpenOption> options,
- FileAttribute<?>... attrs)
- throws IOException
- {
- checkOptions(options);
- final boolean forWrite = (options.contains(StandardOpenOption.WRITE) ||
- options.contains(StandardOpenOption.APPEND));
- beginRead();
- try {
- ensureOpen();
- Entry e = getEntry0(path);
- if (forWrite) {
- checkWritable();
- if (e == null) {
- if (!options.contains(StandardOpenOption.CREATE_NEW))
- throw new NoSuchFileException(getString(path));
- } else {
- if (options.contains(StandardOpenOption.CREATE_NEW))
- throw new FileAlreadyExistsException(getString(path));
- if (e.isDir())
- throw new FileAlreadyExistsException("directory <"
- + getString(path) + "> exists");
- }
- options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile
- } else if (e == null || e.isDir()) {
- throw new NoSuchFileException(getString(path));
- }
-
- final boolean isFCH = (e != null && e.type == Entry.FILECH);
- final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path);
- final FileChannel fch = tmpfile.getFileSystem()
- .provider()
- .newFileChannel(tmpfile, options, attrs);
- final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
- if (forWrite) {
- u.flag = FLAG_DATADESCR;
- u.method = METHOD_DEFLATED;
- }
- // is there a better way to hook into the FileChannel's close method?
- return new FileChannel() {
- public int write(ByteBuffer src) throws IOException {
- return fch.write(src);
- }
- public long write(ByteBuffer[] srcs, int offset, int length)
- throws IOException
- {
- return fch.write(srcs, offset, length);
- }
- public long position() throws IOException {
- return fch.position();
- }
- public FileChannel position(long newPosition)
- throws IOException
- {
- fch.position(newPosition);
- return this;
- }
- public long size() throws IOException {
- return fch.size();
- }
- public FileChannel truncate(long size)
- throws IOException
- {
- fch.truncate(size);
- return this;
- }
- public void force(boolean metaData)
- throws IOException
- {
- fch.force(metaData);
- }
- public long transferTo(long position, long count,
- WritableByteChannel target)
- throws IOException
- {
- return fch.transferTo(position, count, target);
- }
- public long transferFrom(ReadableByteChannel src,
- long position, long count)
- throws IOException
- {
- return fch.transferFrom(src, position, count);
- }
- public int read(ByteBuffer dst) throws IOException {
- return fch.read(dst);
- }
- public int read(ByteBuffer dst, long position)
- throws IOException
- {
- return fch.read(dst, position);
- }
- public long read(ByteBuffer[] dsts, int offset, int length)
- throws IOException
- {
- return fch.read(dsts, offset, length);
- }
- public int write(ByteBuffer src, long position)
- throws IOException
- {
- return fch.write(src, position);
- }
- public MappedByteBuffer map(MapMode mode,
- long position, long size)
- throws IOException
- {
- throw new UnsupportedOperationException();
- }
- public FileLock lock(long position, long size, boolean shared)
- throws IOException
- {
- return fch.lock(position, size, shared);
- }
- public FileLock tryLock(long position, long size, boolean shared)
- throws IOException
- {
- return fch.tryLock(position, size, shared);
- }
- protected void implCloseChannel() throws IOException {
- fch.close();
- if (forWrite) {
- u.mtime = System.currentTimeMillis();
- u.size = Files.size(u.file);
-
- update(u);
- } else {
- if (!isFCH) // if this is a new fch for reading
- removeTempPathForEntry(tmpfile);
- }
- }
- };
- } finally {
- endRead();
- }
- }
-
- // the outstanding input streams that need to be closed
- private Set<InputStream> streams =
- Collections.synchronizedSet(new HashSet<InputStream>());
-
- // the ex-channel and ex-path that need to close when their outstanding
- // input streams are all closed by the obtainers.
- private Set<ExChannelCloser> exChClosers = new HashSet<>();
-
- private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
- private Path getTempPathForEntry(byte[] path) throws IOException {
- Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
- if (path != null) {
- Entry e = getEntry0(path);
- if (e != null) {
- try (InputStream is = newInputStream(path)) {
- Files.copy(is, tmpPath, REPLACE_EXISTING);
- }
- }
- }
- return tmpPath;
- }
-
- private void removeTempPathForEntry(Path path) throws IOException {
- Files.delete(path);
- tmppaths.remove(path);
- }
-
- // check if all parents really exit. ZIP spec does not require
- // the existence of any "parent directory".
- private void checkParents(byte[] path) throws IOException {
- beginRead();
- try {
- while ((path = getParent(path)) != null && path.length != 0) {
- if (!inodes.containsKey(IndexNode.keyOf(path))) {
- throw new NoSuchFileException(getString(path));
- }
- }
- } finally {
- endRead();
- }
- }
-
- private static byte[] ROOTPATH = new byte[0];
- private static byte[] getParent(byte[] path) {
- int off = path.length - 1;
- if (off > 0 && path[off] == '/') // isDirectory
- off--;
- while (off > 0 && path[off] != '/') { off--; }
- if (off <= 0)
- return ROOTPATH;
- return Arrays.copyOf(path, off + 1);
- }
-
- private final void beginWrite() {
- rwlock.writeLock().lock();
- }
-
- private final void endWrite() {
- rwlock.writeLock().unlock();
- }
-
- private final void beginRead() {
- rwlock.readLock().lock();
- }
-
- private final void endRead() {
- rwlock.readLock().unlock();
- }
-
- ///////////////////////////////////////////////////////////////////
-
- private volatile boolean isOpen = true;
- private final SeekableByteChannel ch; // channel to the zipfile
- final byte[] cen; // CEN & ENDHDR
- private END end;
- private long locpos; // position of first LOC header (usually 0)
-
- private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
-
- // name -> pos (in cen), IndexNode itself can be used as a "key"
- private LinkedHashMap<IndexNode, IndexNode> inodes;
-
- final byte[] getBytes(String name) {
- return zc.getBytes(name);
- }
-
- final String getString(byte[] name) {
- return zc.toString(name);
- }
-
- protected void finalize() throws IOException {
- close();
- }
-
- private long getDataPos(Entry e) throws IOException {
- if (e.locoff == -1) {
- Entry e2 = getEntry0(e.name);
- if (e2 == null)
- throw new ZipException("invalid loc for entry <" + e.name + ">");
- e.locoff = e2.locoff;
- }
- byte[] buf = new byte[LOCHDR];
- if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length)
- throw new ZipException("invalid loc for entry <" + e.name + ">");
- return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf);
- }
-
- // Reads len bytes of data from the specified offset into buf.
- // Returns the total number of bytes read.
- // Each/every byte read from here (except the cen, which is mapped).
- final long readFullyAt(byte[] buf, int off, long len, long pos)
- throws IOException
- {
- ByteBuffer bb = ByteBuffer.wrap(buf);
- bb.position(off);
- bb.limit((int)(off + len));
- return readFullyAt(bb, pos);
- }
-
- private final long readFullyAt(ByteBuffer bb, long pos)
- throws IOException
- {
- synchronized(ch) {
- return ch.position(pos).read(bb);
- }
- }
-
- // Searches for end of central directory (END) header. The contents of
- // the END header will be read and placed in endbuf. Returns the file
- // position of the END header, otherwise returns -1 if the END header
- // was not found or an error occurred.
- private END findEND() throws IOException
- {
- byte[] buf = new byte[READBLOCKSZ];
- long ziplen = ch.size();
- long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
- long minPos = minHDR - (buf.length - ENDHDR);
-
- for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR))
- {
- int off = 0;
- if (pos < 0) {
- // Pretend there are some NUL bytes before start of file
- off = (int)-pos;
- Arrays.fill(buf, 0, off, (byte)0);
- }
- int len = buf.length - off;
- if (readFullyAt(buf, off, len, pos + off) != len)
- zerror("zip END header not found");
-
- // Now scan the block backwards for END header signature
- for (int i = buf.length - ENDHDR; i >= 0; i--) {
- if (buf[i+0] == (byte)'P' &&
- buf[i+1] == (byte)'K' &&
- buf[i+2] == (byte)'\005' &&
- buf[i+3] == (byte)'\006' &&
- (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) {
- // Found END header
- buf = Arrays.copyOfRange(buf, i, i + ENDHDR);
- END end = new END();
- end.endsub = ENDSUB(buf);
- end.centot = ENDTOT(buf);
- end.cenlen = ENDSIZ(buf);
- end.cenoff = ENDOFF(buf);
- end.comlen = ENDCOM(buf);
- end.endpos = pos + i;
- if (end.cenlen == ZIP64_MINVAL ||
- end.cenoff == ZIP64_MINVAL ||
- end.centot == ZIP64_MINVAL32)
- {
- // need to find the zip64 end;
- byte[] loc64 = new byte[ZIP64_LOCHDR];
- if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
- != loc64.length) {
- return end;
- }
- long end64pos = ZIP64_LOCOFF(loc64);
- byte[] end64buf = new byte[ZIP64_ENDHDR];
- if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
- != end64buf.length) {
- return end;
- }
- // end64 found, re-calcualte everything.
- end.cenlen = ZIP64_ENDSIZ(end64buf);
- end.cenoff = ZIP64_ENDOFF(end64buf);
- end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
- end.endpos = end64pos;
- }
- return end;
- }
- }
- }
- zerror("zip END header not found");
- return null; //make compiler happy
- }
-
- // Reads zip file central directory. Returns the file position of first
- // CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
- // then the error was a zip format error and zip->msg has the error text.
- // Always pass in -1 for knownTotal; it's used for a recursive call.
- private byte[] initCEN() throws IOException {
- end = findEND();
- if (end.endpos == 0) {
- inodes = new LinkedHashMap<>(10);
- locpos = 0;
- buildNodeTree();
- return null; // only END header present
- }
- if (end.cenlen > end.endpos)
- zerror("invalid END header (bad central directory size)");
- long cenpos = end.endpos - end.cenlen; // position of CEN table
-
- // Get position of first local file (LOC) header, taking into
- // account that there may be a stub prefixed to the zip file.
- locpos = cenpos - end.cenoff;
- if (locpos < 0)
- zerror("invalid END header (bad central directory offset)");
-
- // read in the CEN and END
- byte[] cen = new byte[(int)(end.cenlen + ENDHDR)];
- if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
- zerror("read CEN tables failed");
- }
- // Iterate through the entries in the central directory
- inodes = new LinkedHashMap<>(end.centot + 1);
- int pos = 0;
- int limit = cen.length - ENDHDR;
- while (pos < limit) {
- if (CENSIG(cen, pos) != CENSIG)
- zerror("invalid CEN header (bad signature)");
- int method = CENHOW(cen, pos);
- int nlen = CENNAM(cen, pos);
- int elen = CENEXT(cen, pos);
- int clen = CENCOM(cen, pos);
- if ((CENFLG(cen, pos) & 1) != 0)
- zerror("invalid CEN header (encrypted entry)");
- if (method != METHOD_STORED && method != METHOD_DEFLATED)
- zerror("invalid CEN header (unsupported compression method: " + method + ")");
- if (pos + CENHDR + nlen > limit)
- zerror("invalid CEN header (bad header size)");
- byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen);
- IndexNode inode = new IndexNode(name, pos);
- inodes.put(inode, inode);
- // skip ext and comment
- pos += (CENHDR + nlen + elen + clen);
- }
- if (pos + ENDHDR != cen.length) {
- zerror("invalid CEN header (bad header size)");
- }
- buildNodeTree();
- return cen;
- }
-
- private void ensureOpen() throws IOException {
- if (!isOpen)
- throw new ClosedFileSystemException();
- }
-
- // Creates a new empty temporary file in the same directory as the
- // specified file. A variant of Files.createTempFile.
- private Path createTempFileInSameDirectoryAs(Path path)
- throws IOException
- {
- Path parent = path.toAbsolutePath().getParent();
- Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
- Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
- tmppaths.add(tmpPath);
- return tmpPath;
- }
-
- ////////////////////update & sync //////////////////////////////////////
-
- private boolean hasUpdate = false;
-
- // shared key. consumer guarantees the "writeLock" before use it.
- private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
-
- private void updateDelete(IndexNode inode) {
- beginWrite();
- try {
- removeFromTree(inode);
- inodes.remove(inode);
- hasUpdate = true;
- } finally {
- endWrite();
- }
- }
-
- private void update(Entry e) {
- beginWrite();
- try {
- IndexNode old = inodes.put(e, e);
- if (old != null) {
- removeFromTree(old);
- }
- if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
- IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
- e.sibling = parent.child;
- parent.child = e;
- }
- hasUpdate = true;
- } finally {
- endWrite();
- }
- }
-
- // copy over the whole LOC entry (header if necessary, data and ext) from
- // old zip to the new one.
- private long copyLOCEntry(Entry e, boolean updateHeader,
- OutputStream os,
- long written, byte[] buf)
- throws IOException
- {
- long locoff = e.locoff; // where to read
- e.locoff = written; // update the e.locoff with new value
-
- // calculate the size need to write out
- long size = 0;
- // if there is A ext
- if ((e.flag & FLAG_DATADESCR) != 0) {
- if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL)
- size = 24;
- else
- size = 16;
- }
- // read loc, use the original loc.elen/nlen
- if (readFullyAt(buf, 0, LOCHDR , locoff) != LOCHDR)
- throw new ZipException("loc: reading failed");
- if (updateHeader) {
- locoff += LOCHDR + LOCNAM(buf) + LOCEXT(buf); // skip header
- size += e.csize;
- written = e.writeLOC(os) + size;
- } else {
- os.write(buf, 0, LOCHDR); // write out the loc header
- locoff += LOCHDR;
- // use e.csize, LOCSIZ(buf) is zero if FLAG_DATADESCR is on
- // size += LOCNAM(buf) + LOCEXT(buf) + LOCSIZ(buf);
- size += LOCNAM(buf) + LOCEXT(buf) + e.csize;
- written = LOCHDR + size;
- }
- int n;
- while (size > 0 &&
- (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
- {
- if (size < n)
- n = (int)size;
- os.write(buf, 0, n);
- size -= n;
- locoff += n;
- }
- return written;
- }
-
- // sync the zip file system, if there is any udpate
- private void sync() throws IOException {
- //System.out.printf("->sync(%s) starting....!%n", toString());
- // check ex-closer
- if (!exChClosers.isEmpty()) {
- for (ExChannelCloser ecc : exChClosers) {
- if (ecc.streams.isEmpty()) {
- ecc.ch.close();
- Files.delete(ecc.path);
- exChClosers.remove(ecc);
- }
- }
- }
- if (!hasUpdate)
- return;
- Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
- try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
- {
- ArrayList<Entry> elist = new ArrayList<>(inodes.size());
- long written = 0;
- byte[] buf = new byte[8192];
- Entry e = null;
-
- // write loc
- for (IndexNode inode : inodes.values()) {
- if (inode instanceof Entry) { // an updated inode
- e = (Entry)inode;
- try {
- if (e.type == Entry.COPY) {
- // entry copy: the only thing changed is the "name"
- // and "nlen" in LOC header, so we udpate/rewrite the
- // LOC in new file and simply copy the rest (data and
- // ext) without enflating/deflating from the old zip
- // file LOC entry.
- written += copyLOCEntry(e, true, os, written, buf);
- } else { // NEW, FILECH or CEN
- e.locoff = written;
- written += e.writeLOC(os); // write loc header
- if (e.bytes != null) { // in-memory, deflated
- os.write(e.bytes); // already
- written += e.bytes.length;
- } else if (e.file != null) { // tmp file
- try (InputStream is = Files.newInputStream(e.file)) {
- int n;
- if (e.type == Entry.NEW) { // deflated already
- while ((n = is.read(buf)) != -1) {
- os.write(buf, 0, n);
- written += n;
- }
- } else if (e.type == Entry.FILECH) {
- // the data are not deflated, use ZEOS
- try (OutputStream os2 = new EntryOutputStream(e, os)) {
- while ((n = is.read(buf)) != -1) {
- os2.write(buf, 0, n);
- }
- }
- written += e.csize;
- if ((e.flag & FLAG_DATADESCR) != 0)
- written += e.writeEXT(os);
- }
- }
- Files.delete(e.file);
- tmppaths.remove(e.file);
- } else {
- // dir, 0-length data
- }
- }
- elist.add(e);
- } catch (IOException x) {
- x.printStackTrace(); // skip any in-accurate entry
- }
- } else { // unchanged inode
- if (inode.pos == -1) {
- continue; // pseudo directory node
- }
- e = Entry.readCEN(this, inode.pos);
- try {
- written += copyLOCEntry(e, false, os, written, buf);
- elist.add(e);
- } catch (IOException x) {
- x.printStackTrace(); // skip any wrong entry
- }
- }
- }
-
- // now write back the cen and end table
- end.cenoff = written;
- for (Entry entry : elist) {
- written += entry.writeCEN(os);
- }
- end.centot = elist.size();
- end.cenlen = written - end.cenoff;
- end.write(os, written);
- }
- if (!streams.isEmpty()) {
- //
- // TBD: ExChannelCloser should not be necessary if we only
- // sync when being closed, all streams should have been
- // closed already. Keep the logic here for now.
- //
- // There are outstanding input streams open on existing "ch",
- // so, don't close the "cha" and delete the "file for now, let
- // the "ex-channel-closer" to handle them
- ExChannelCloser ecc = new ExChannelCloser(
- createTempFileInSameDirectoryAs(zfpath),
- ch,
- streams);
- Files.move(zfpath, ecc.path, REPLACE_EXISTING);
- exChClosers.add(ecc);
- streams = Collections.synchronizedSet(new HashSet<InputStream>());
- } else {
- ch.close();
- Files.delete(zfpath);
- }
-
- Files.move(tmpFile, zfpath, REPLACE_EXISTING);
- hasUpdate = false; // clear
- /*
- if (isOpen) {
- ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen"
- cen = initCEN();
- }
- */
- //System.out.printf("->sync(%s) done!%n", toString());
- }
-
- private IndexNode getInode(byte[] path) {
- if (path == null)
- throw new NullPointerException("path");
- IndexNode key = IndexNode.keyOf(path);
- IndexNode inode = inodes.get(key);
- if (inode == null &&
- (path.length == 0 || path[path.length -1] != '/')) {
- // if does not ends with a slash
- path = Arrays.copyOf(path, path.length + 1);
- path[path.length - 1] = '/';
- inode = inodes.get(key.as(path));
- }
- return inode;
- }
-
- private Entry getEntry0(byte[] path) throws IOException {
- IndexNode inode = getInode(path);
- if (inode instanceof Entry)
- return (Entry)inode;
- if (inode == null || inode.pos == -1)
- return null;
- return Entry.readCEN(this, inode.pos);
- }
-
- public void deleteFile(byte[] path, boolean failIfNotExists)
- throws IOException
- {
- checkWritable();
-
- IndexNode inode = getInode(path);
- if (inode == null) {
- if (path != null && path.length == 0)
- throw new ZipException("root directory </> can't not be delete");
- if (failIfNotExists)
- throw new NoSuchFileException(getString(path));
- } else {
- if (inode.isDir() && inode.child != null)
- throw new DirectoryNotEmptyException(getString(path));
- updateDelete(inode);
- }
- }
-
- private static void copyStream(InputStream is, OutputStream os)
- throws IOException
- {
- byte[] copyBuf = new byte[8192];
- int n;
- while ((n = is.read(copyBuf)) != -1) {
- os.write(copyBuf, 0, n);
- }
- }
-
- // Returns an out stream for either
- // (1) writing the contents of a new entry, if the entry exits, or
- // (2) updating/replacing the contents of the specified existing entry.
- private OutputStream getOutputStream(Entry e) throws IOException {
-
- if (e.mtime == -1)
- e.mtime = System.currentTimeMillis();
- if (e.method == -1)
- e.method = METHOD_DEFLATED; // TBD: use default method
- // store size, compressed size, and crc-32 in LOC header
- e.flag = 0;
- if (zc.isUTF8())
- e.flag |= FLAG_EFS;
- OutputStream os;
- if (useTempFile) {
- e.file = getTempPathForEntry(null);
- os = Files.newOutputStream(e.file, WRITE);
- } else {
- os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
- }
- return new EntryOutputStream(e, os);
- }
-
- private InputStream getInputStream(Entry e)
- throws IOException
- {
- InputStream eis = null;
-
- if (e.type == Entry.NEW) {
- if (e.bytes != null)
- eis = new ByteArrayInputStream(e.bytes);
- else if (e.file != null)
- eis = Files.newInputStream(e.file);
- else
- throw new ZipException("update entry data is missing");
- } else if (e.type == Entry.FILECH) {
- // FILECH result is un-compressed.
- eis = Files.newInputStream(e.file);
- // TBD: wrap to hook close()
- // streams.add(eis);
- return eis;
- } else { // untouced CEN or COPY
- eis = new EntryInputStream(e, ch);
- }
- if (e.method == METHOD_DEFLATED) {
- // MORE: Compute good size for inflater stream:
- long bufSize = e.size + 2; // Inflater likes a bit of slack
- if (bufSize > 65536)
- bufSize = 8192;
- final long size = e.size;
- eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) {
-
- private boolean isClosed = false;
- public void close() throws IOException {
- if (!isClosed) {
- releaseInflater(inf);
- this.in.close();
- isClosed = true;
- streams.remove(this);
- }
- }
- // Override fill() method to provide an extra "dummy" byte
- // at the end of the input stream. This is required when
- // using the "nowrap" Inflater option. (it appears the new
- // zlib in 7 does not need it, but keep it for now)
- protected void fill() throws IOException {
- if (eof) {
- throw new EOFException(
- "Unexpected end of ZLIB input stream");
- }
- len = this.in.read(buf, 0, buf.length);
- if (len == -1) {
- buf[0] = 0;
- len = 1;
- eof = true;
- }
- inf.setInput(buf, 0, len);
- }
- private boolean eof;
-
- public int available() throws IOException {
- if (isClosed)
- return 0;
- long avail = size - inf.getBytesWritten();
- return avail > (long) Integer.MAX_VALUE ?
- Integer.MAX_VALUE : (int) avail;
- }
- };
- } else if (e.method == METHOD_STORED) {
- // TBD: wrap/ it does not seem necessary
- } else {
- throw new ZipException("invalid compression method");
- }
- streams.add(eis);
- return eis;
- }
-
- // Inner class implementing the input stream used to read
- // a (possibly compressed) zip file entry.
- private class EntryInputStream extends InputStream {
- private final SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might
- // point to a new channel after sync()
- private long pos; // current position within entry data
- protected long rem; // number of remaining bytes within entry
- protected final long size; // uncompressed size of this entry
-
- EntryInputStream(Entry e, SeekableByteChannel zfch)
- throws IOException
- {
- this.zfch = zfch;
- rem = e.csize;
- size = e.size;
- pos = getDataPos(e);
- }
- public int read(byte b[], int off, int len) throws IOException {
- ensureOpen();
- if (rem == 0) {
- return -1;
- }
- if (len <= 0) {
- return 0;
- }
- if (len > rem) {
- len = (int) rem;
- }
- // readFullyAt()
- long n = 0;
- ByteBuffer bb = ByteBuffer.wrap(b);
- bb.position(off);
- bb.limit(off + len);
- synchronized(zfch) {
- n = zfch.position(pos).read(bb);
- }
- if (n > 0) {
- pos += n;
- rem -= n;
- }
- if (rem == 0) {
- close();
- }
- return (int)n;
- }
- public int read() throws IOException {
- byte[] b = new byte[1];
- if (read(b, 0, 1) == 1) {
- return b[0] & 0xff;
- } else {
- return -1;
- }
- }
- public long skip(long n) throws IOException {
- ensureOpen();
- if (n > rem)
- n = rem;
- pos += n;
- rem -= n;
- if (rem == 0) {
- close();
- }
- return n;
- }
- public int available() {
- return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
- }
- public long size() {
- return size;
- }
- public void close() {
- rem = 0;
- streams.remove(this);
- }
- }
-
- class EntryOutputStream extends DeflaterOutputStream
- {
- private CRC32 crc;
- private Entry e;
- private long written;
-
- EntryOutputStream(Entry e, OutputStream os)
- throws IOException
- {
- super(os, getDeflater());
- if (e == null)
- throw new NullPointerException("Zip entry is null");
- this.e = e;
- crc = new CRC32();
- }
-
- @Override
- public void write(byte b[], int off, int len) throws IOException {
- if (e.type != Entry.FILECH) // only from sync
- ensureOpen();
- if (off < 0 || len < 0 || off > b.length - len) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- switch (e.method) {
- case METHOD_DEFLATED:
- super.write(b, off, len);
- break;
- case METHOD_STORED:
- written += len;
- out.write(b, off, len);
- break;
- default:
- throw new ZipException("invalid compression method");
- }
- crc.update(b, off, len);
- }
-
- @Override
- public void close() throws IOException {
- // TBD ensureOpen();
- switch (e.method) {
- case METHOD_DEFLATED:
- finish();
- e.size = def.getBytesRead();
- e.csize = def.getBytesWritten();
- e.crc = crc.getValue();
- break;
- case METHOD_STORED:
- // we already know that both e.size and e.csize are the same
- e.size = e.csize = written;
- e.crc = crc.getValue();
- break;
- default:
- throw new ZipException("invalid compression method");
- }
- //crc.reset();
- if (out instanceof ByteArrayOutputStream)
- e.bytes = ((ByteArrayOutputStream)out).toByteArray();
-
- if (e.type == Entry.FILECH) {
- releaseDeflater(def);
- return;
- }
- super.close();
- releaseDeflater(def);
- update(e);
- }
- }
-
- static void zerror(String msg) {
- throw new ZipError(msg);
- }
-
- // Maxmum number of de/inflater we cache
- private final int MAX_FLATER = 20;
- // List of available Inflater objects for decompression
- private final List<Inflater> inflaters = new ArrayList<>();
-
- // Gets an inflater from the list of available inflaters or allocates
- // a new one.
- private Inflater getInflater() {
- synchronized (inflaters) {
- int size = inflaters.size();
- if (size > 0) {
- Inflater inf = inflaters.remove(size - 1);
- return inf;
- } else {
- return new Inflater(true);
- }
- }
- }
-
- // Releases the specified inflater to the list of available inflaters.
- private void releaseInflater(Inflater inf) {
- synchronized (inflaters) {
- if (inflaters.size() < MAX_FLATER) {
- inf.reset();
- inflaters.add(inf);
- } else {
- inf.end();
- }
- }
- }
-
- // List of available Deflater objects for compression
- private final List<Deflater> deflaters = new ArrayList<>();
-
- // Gets an deflater from the list of available deflaters or allocates
- // a new one.
- private Deflater getDeflater() {
- synchronized (deflaters) {
- int size = deflaters.size();
- if (size > 0) {
- Deflater def = deflaters.remove(size - 1);
- return def;
- } else {
- return new Deflater(Deflater.DEFAULT_COMPRESSION, true);
- }
- }
- }
-
- // Releases the specified inflater to the list of available inflaters.
- private void releaseDeflater(Deflater def) {
- synchronized (deflaters) {
- if (inflaters.size() < MAX_FLATER) {
- def.reset();
- deflaters.add(def);
- } else {
- def.end();
- }
- }
- }
-
- // End of central directory record
- static class END {
- int disknum;
- int sdisknum;
- int endsub; // endsub
- int centot; // 4 bytes
- long cenlen; // 4 bytes
- long cenoff; // 4 bytes
- int comlen; // comment length
- byte[] comment;
-
- /* members of Zip64 end of central directory locator */
- int diskNum;
- long endpos;
- int disktot;
-
- void write(OutputStream os, long offset) throws IOException {
- boolean hasZip64 = false;
- long xlen = cenlen;
- long xoff = cenoff;
- if (xlen >= ZIP64_MINVAL) {
- xlen = ZIP64_MINVAL;
- hasZip64 = true;
- }
- if (xoff >= ZIP64_MINVAL) {
- xoff = ZIP64_MINVAL;
- hasZip64 = true;
- }
- int count = centot;
- if (count >= ZIP64_MINVAL32) {
- count = ZIP64_MINVAL32;
- hasZip64 = true;
- }
- if (hasZip64) {
- long off64 = offset;
- //zip64 end of central directory record
- writeInt(os, ZIP64_ENDSIG); // zip64 END record signature
- writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end
- writeShort(os, 45); // version made by
- writeShort(os, 45); // version needed to extract
- writeInt(os, 0); // number of this disk
- writeInt(os, 0); // central directory start disk
- writeLong(os, centot); // number of directory entires on disk
- writeLong(os, centot); // number of directory entires
- writeLong(os, cenlen); // length of central directory
- writeLong(os, cenoff); // offset of central directory
-
- //zip64 end of central directory locator
- writeInt(os, ZIP64_LOCSIG); // zip64 END locator signature
- writeInt(os, 0); // zip64 END start disk
- writeLong(os, off64); // offset of zip64 END
- writeInt(os, 1); // total number of disks (?)
- }
- writeInt(os, ENDSIG); // END record signature
- writeShort(os, 0); // number of this disk
- writeShort(os, 0); // central directory start disk
- writeShort(os, count); // number of directory entries on disk
- writeShort(os, count); // total number of directory entries
- writeInt(os, xlen); // length of central directory
- writeInt(os, xoff); // offset of central directory
- if (comment != null) { // zip file comment
- writeShort(os, comment.length);
- writeBytes(os, comment);
- } else {
- writeShort(os, 0);
- }
- }
- }
-
- // Internal node that links a "name" to its pos in cen table.
- // The node itself can be used as a "key" to lookup itself in
- // the HashMap inodes.
- static class IndexNode {
- byte[] name;
- int hashcode; // node is hashable/hashed by its name
- int pos = -1; // position in cen table, -1 menas the
- // entry does not exists in zip file
- IndexNode(byte[] name, int pos) {
- name(name);
- this.pos = pos;
- }
-
- final static IndexNode keyOf(byte[] name) { // get a lookup key;
- return new IndexNode(name, -1);
- }
-
- final void name(byte[] name) {
- this.name = name;
- this.hashcode = Arrays.hashCode(name);
- }
-
- final IndexNode as(byte[] name) { // reuse the node, mostly
- name(name); // as a lookup "key"
- return this;
- }
-
- boolean isDir() {
- return name != null &&
- (name.length == 0 || name[name.length - 1] == '/');
- }
-
- public boolean equals(Object other) {
- if (!(other instanceof IndexNode)) {
- return false;
- }
- return Arrays.equals(name, ((IndexNode)other).name);
- }
-
- public int hashCode() {
- return hashcode;
- }
-
- IndexNode() {}
- IndexNode sibling;
- IndexNode child; // 1st child
- }
-
- static class Entry extends IndexNode {
-
- static final int CEN = 1; // entry read from cen
- static final int NEW = 2; // updated contents in bytes or file
- static final int FILECH = 3; // fch update in "file"
- static final int COPY = 4; // copy of a CEN entry
-
-
- byte[] bytes; // updated content bytes
- Path file; // use tmp file to store bytes;
- int type = CEN; // default is the entry read from cen
-
- // entry attributes
- int version;
- int flag;
- int method = -1; // compression method
- long mtime = -1; // last modification time (in DOS time)
- long atime = -1; // last access time
- long ctime = -1; // create time
- long crc = -1; // crc-32 of entry data
- long csize = -1; // compressed size of entry data
- long size = -1; // uncompressed size of entry data
- byte[] extra;
-
- // cen
- int versionMade;
- int disk;
- int attrs;
- long attrsEx;
- long locoff;
- byte[] comment;
-
- Entry() {}
-
- Entry(byte[] name) {
- name(name);
- this.mtime = this.ctime = this.atime = System.currentTimeMillis();
- this.crc = 0;
- this.size = 0;
- this.csize = 0;
- this.method = METHOD_DEFLATED;
- }
-
- Entry(byte[] name, int type) {
- this(name);
- this.type = type;
- }
-
- Entry (Entry e, int type) {
- name(e.name);
- this.version = e.version;
- this.ctime = e.ctime;
- this.atime = e.atime;
- this.mtime = e.mtime;
- this.crc = e.crc;
- this.size = e.size;
- this.csize = e.csize;
- this.method = e.method;
- this.extra = e.extra;
- this.versionMade = e.versionMade;
- this.disk = e.disk;
- this.attrs = e.attrs;
- this.attrsEx = e.attrsEx;
- this.locoff = e.locoff;
- this.comment = e.comment;
- this.type = type;
- }
-
- Entry (byte[] name, Path file, int type) {
- this(name, type);
- this.file = file;
- this.method = METHOD_STORED;
- }
-
- int version() throws ZipException {
- if (method == METHOD_DEFLATED)
- return 20;
- else if (method == METHOD_STORED)
- return 10;
- throw new ZipException("unsupported compression method");
- }
-
- ///////////////////// CEN //////////////////////
- static Entry readCEN(ZipFileSystem zipfs, int pos)
- throws IOException
- {
- return new Entry().cen(zipfs, pos);
- }
-
- private Entry cen(ZipFileSystem zipfs, int pos)
- throws IOException
- {
- byte[] cen = zipfs.cen;
- if (CENSIG(cen, pos) != CENSIG)
- zerror("invalid CEN header (bad signature)");
- versionMade = CENVEM(cen, pos);
- version = CENVER(cen, pos);
- flag = CENFLG(cen, pos);
- method = CENHOW(cen, pos);
- mtime = dosToJavaTime(CENTIM(cen, pos));
- crc = CENCRC(cen, pos);
- csize = CENSIZ(cen, pos);
- size = CENLEN(cen, pos);
- int nlen = CENNAM(cen, pos);
- int elen = CENEXT(cen, pos);
- int clen = CENCOM(cen, pos);
- disk = CENDSK(cen, pos);
- attrs = CENATT(cen, pos);
- attrsEx = CENATX(cen, pos);
- locoff = CENOFF(cen, pos);
-
- pos += CENHDR;
- name(Arrays.copyOfRange(cen, pos, pos + nlen));
-
- pos += nlen;
- if (elen > 0) {
- extra = Arrays.copyOfRange(cen, pos, pos + elen);
- pos += elen;
- readExtra(zipfs);
- }
- if (clen > 0) {
- comment = Arrays.copyOfRange(cen, pos, pos + clen);
- }
- return this;
- }
-
- int writeCEN(OutputStream os) throws IOException
- {
- int written = CENHDR;
- int version0 = version();
- long csize0 = csize;
- long size0 = size;
- long locoff0 = locoff;
- int elen64 = 0; // extra for ZIP64
- int elenNTFS = 0; // extra for NTFS (a/c/mtime)
- int elenEXTT = 0; // extra for Extended Timestamp
- boolean foundExtraTime = false; // if time stamp NTFS, EXTT present
-
- // confirm size/length
- int nlen = (name != null) ? name.length : 0;
- int elen = (extra != null) ? extra.length : 0;
- int eoff = 0;
- int clen = (comment != null) ? comment.length : 0;
- if (csize >= ZIP64_MINVAL) {
- csize0 = ZIP64_MINVAL;
- elen64 += 8; // csize(8)
- }
- if (size >= ZIP64_MINVAL) {
- size0 = ZIP64_MINVAL; // size(8)
- elen64 += 8;
- }
- if (locoff >= ZIP64_MINVAL) {
- locoff0 = ZIP64_MINVAL;
- elen64 += 8; // offset(8)
- }
- if (elen64 != 0) {
- elen64 += 4; // header and data sz 4 bytes
- }
- while (eoff + 4 < elen) {
- int tag = SH(extra, eoff);
- int sz = SH(extra, eoff + 2);
- if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
- foundExtraTime = true;
- }
- eoff += (4 + sz);
- }
- if (!foundExtraTime) {
- if (isWindows) { // use NTFS
- elenNTFS = 36; // total 36 bytes
- } else { // Extended Timestamp otherwise
- elenEXTT = 9; // only mtime in cen
- }
- }
- writeInt(os, CENSIG); // CEN header signature
- if (elen64 != 0) {
- writeShort(os, 45); // ver 4.5 for zip64
- writeShort(os, 45);
- } else {
- writeShort(os, version0); // version made by
- writeShort(os, version0); // version needed to extract
- }
- writeShort(os, flag); // general purpose bit flag
- writeShort(os, method); // compression method
- // last modification time
- writeInt(os, (int)javaToDosTime(mtime));
- writeInt(os, crc); // crc-32
- writeInt(os, csize0); // compressed size
- writeInt(os, size0); // uncompressed size
- writeShort(os, name.length);
- writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
-
- if (comment != null) {
- writeShort(os, Math.min(clen, 0xffff));
- } else {
- writeShort(os, 0);
- }
- writeShort(os, 0); // starting disk number
- writeShort(os, 0); // internal file attributes (unused)
- writeInt(os, 0); // external file attributes (unused)
- writeInt(os, locoff0); // relative offset of local header
- writeBytes(os, name);
- if (elen64 != 0) {
- writeShort(os, EXTID_ZIP64);// Zip64 extra
- writeShort(os, elen64 - 4); // size of "this" extra block
- if (size0 == ZIP64_MINVAL)
- writeLong(os, size);
- if (csize0 == ZIP64_MINVAL)
- writeLong(os, csize);
- if (locoff0 == ZIP64_MINVAL)
- writeLong(os, locoff);
- }
- if (elenNTFS != 0) {
- writeShort(os, EXTID_NTFS);
- writeShort(os, elenNTFS - 4);
- writeInt(os, 0); // reserved
- writeShort(os, 0x0001); // NTFS attr tag
- writeShort(os, 24);
- writeLong(os, javaToWinTime(mtime));
- writeLong(os, javaToWinTime(atime));
- writeLong(os, javaToWinTime(ctime));
- }
- if (elenEXTT != 0) {
- writeShort(os, EXTID_EXTT);
- writeShort(os, elenEXTT - 4);
- if (ctime == -1)
- os.write(0x3); // mtime and atime
- else
- os.write(0x7); // mtime, atime and ctime
- writeInt(os, javaToUnixTime(mtime));
- }
- if (extra != null) // whatever not recognized
- writeBytes(os, extra);
- if (comment != null) //TBD: 0, Math.min(commentBytes.length, 0xffff));
- writeBytes(os, comment);
- return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT;
- }
-
- ///////////////////// LOC //////////////////////
- static Entry readLOC(ZipFileSystem zipfs, long pos)
- throws IOException
- {
- return readLOC(zipfs, pos, new byte[1024]);
- }
-
- static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- return new Entry().loc(zipfs, pos, buf);
- }
-
- Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- assert (buf.length >= LOCHDR);
- if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
- throw new ZipException("loc: reading failed");
- if (LOCSIG(buf) != LOCSIG)
- throw new ZipException("loc: wrong sig ->"
- + Long.toString(LOCSIG(buf), 16));
- //startPos = pos;
- version = LOCVER(buf);
- flag = LOCFLG(buf);
- method = LOCHOW(buf);
- mtime = dosToJavaTime(LOCTIM(buf));
- crc = LOCCRC(buf);
- csize = LOCSIZ(buf);
- size = LOCLEN(buf);
- int nlen = LOCNAM(buf);
- int elen = LOCEXT(buf);
-
- name = new byte[nlen];
- if (zipfs.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) {
- throw new ZipException("loc: name reading failed");
- }
- if (elen > 0) {
- extra = new byte[elen];
- if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
- != elen) {
- throw new ZipException("loc: ext reading failed");
- }
- }
- pos += (LOCHDR + nlen + elen);
- if ((flag & FLAG_DATADESCR) != 0) {
- // Data Descriptor
- Entry e = zipfs.getEntry0(name); // get the size/csize from cen
- if (e == null)
- throw new ZipException("loc: name not found in cen");
- size = e.size;
- csize = e.csize;
- pos += (method == METHOD_STORED ? size : csize);
- if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
- pos += 24;
- else
- pos += 16;
- } else {
- if (extra != null &&
- (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
- // zip64 ext: must include both size and csize
- int off = 0;
- while (off + 20 < elen) { // HeaderID+DataSize+Data
- int sz = SH(extra, off + 2);
- if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
- size = LL(extra, off + 4);
- csize = LL(extra, off + 12);
- break;
- }
- off += (sz + 4);
- }
- }
- pos += (method == METHOD_STORED ? size : csize);
- }
- return this;
- }
-
- int writeLOC(OutputStream os)
- throws IOException
- {
- writeInt(os, LOCSIG); // LOC header signature
- int version = version();
- int nlen = (name != null) ? name.length : 0;
- int elen = (extra != null) ? extra.length : 0;
- boolean foundExtraTime = false; // if extra timestamp present
- int eoff = 0;
- int elen64 = 0;
- int elenEXTT = 0;
- int elenNTFS = 0;
- if ((flag & FLAG_DATADESCR) != 0) {
- writeShort(os, version()); // version needed to extract
- writeShort(os, flag); // general purpose bit flag
- writeShort(os, method); // compression method
- // last modification time
- writeInt(os, (int)javaToDosTime(mtime));
- // store size, uncompressed size, and crc-32 in data descriptor
- // immediately following compressed entry data
- writeInt(os, 0);
- writeInt(os, 0);
- writeInt(os, 0);
- } else {
- if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
- elen64 = 20; //headid(2) + size(2) + size(8) + csize(8)
- writeShort(os, 45); // ver 4.5 for zip64
- } else {
- writeShort(os, version()); // version needed to extract
- }
- writeShort(os, flag); // general purpose bit flag
- writeShort(os, method); // compression method
- // last modification time
- writeInt(os, (int)javaToDosTime(mtime));
- writeInt(os, crc); // crc-32
- if (elen64 != 0) {
- writeInt(os, ZIP64_MINVAL);
- writeInt(os, ZIP64_MINVAL);
- } else {
- writeInt(os, csize); // compressed size
- writeInt(os, size); // uncompressed size
- }
- }
- while (eoff + 4 < elen) {
- int tag = SH(extra, eoff);
- int sz = SH(extra, eoff + 2);
- if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
- foundExtraTime = true;
- }
- eoff += (4 + sz);
- }
- if (!foundExtraTime) {
- if (isWindows) {
- elenNTFS = 36; // NTFS, total 36 bytes
- } else { // on unix use "ext time"
- elenEXTT = 9;
- if (atime != -1)
- elenEXTT += 4;
- if (ctime != -1)
- elenEXTT += 4;
- }
- }
- writeShort(os, name.length);
- writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
- writeBytes(os, name);
- if (elen64 != 0) {
- writeShort(os, EXTID_ZIP64);
- writeShort(os, 16);
- writeLong(os, size);
- writeLong(os, csize);
- }
- if (elenNTFS != 0) {
- writeShort(os, EXTID_NTFS);
- writeShort(os, elenNTFS - 4);
- writeInt(os, 0); // reserved
- writeShort(os, 0x0001); // NTFS attr tag
- writeShort(os, 24);
- writeLong(os, javaToWinTime(mtime));
- writeLong(os, javaToWinTime(atime));
- writeLong(os, javaToWinTime(ctime));
- }
- if (elenEXTT != 0) {
- writeShort(os, EXTID_EXTT);
- writeShort(os, elenEXTT - 4);// size for the folowing data block
- int fbyte = 0x1;
- if (atime != -1) // mtime and atime
- fbyte |= 0x2;
- if (ctime != -1) // mtime, atime and ctime
- fbyte |= 0x4;
- os.write(fbyte); // flags byte
- writeInt(os, javaToUnixTime(mtime));
- if (atime != -1)
- writeInt(os, javaToUnixTime(atime));
- if (ctime != -1)
- writeInt(os, javaToUnixTime(ctime));
- }
- if (extra != null) {
- writeBytes(os, extra);
- }
- return LOCHDR + name.length + elen + elen64 + elenNTFS + elenEXTT;
- }
-
- // Data Descriptior
- int writeEXT(OutputStream os)
- throws IOException
- {
- writeInt(os, EXTSIG); // EXT header signature
- writeInt(os, crc); // crc-32
- if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
- writeLong(os, csize);
- writeLong(os, size);
- return 24;
- } else {
- writeInt(os, csize); // compressed size
- writeInt(os, size); // uncompressed size
- return 16;
- }
- }
-
- // read NTFS, UNIX and ZIP64 data from cen.extra
- void readExtra(ZipFileSystem zipfs) throws IOException {
- if (extra == null)
- return;
- int elen = extra.length;
- int off = 0;
- int newOff = 0;
- while (off + 4 < elen) {
- // extra spec: HeaderID+DataSize+Data
- int pos = off;
- int tag = SH(extra, pos);
- int sz = SH(extra, pos + 2);
- pos += 4;
- if (pos + sz > elen) // invalid data
- break;
- switch (tag) {
- case EXTID_ZIP64 :
- if (size == ZIP64_MINVAL) {
- if (pos + 8 > elen) // invalid zip64 extra
- break; // fields, just skip
- size = LL(extra, pos);
- pos += 8;
- }
- if (csize == ZIP64_MINVAL) {
- if (pos + 8 > elen)
- break;
- csize = LL(extra, pos);
- pos += 8;
- }
- if (locoff == ZIP64_MINVAL) {
- if (pos + 8 > elen)
- break;
- locoff = LL(extra, pos);
- pos += 8;
- }
- break;
- case EXTID_NTFS:
- pos += 4; // reserved 4 bytes
- if (SH(extra, pos) != 0x0001)
- break;
- if (SH(extra, pos + 2) != 24)
- break;
- // override the loc field, datatime here is
- // more "accurate"
- mtime = winToJavaTime(LL(extra, pos + 4));
- atime = winToJavaTime(LL(extra, pos + 12));
- ctime = winToJavaTime(LL(extra, pos + 20));
- break;
- case EXTID_EXTT:
- // spec says the Extened timestamp in cen only has mtime
- // need to read the loc to get the extra a/ctime
- byte[] buf = new byte[LOCHDR];
- if (zipfs.readFullyAt(buf, 0, buf.length , locoff)
- != buf.length)
- throw new ZipException("loc: reading failed");
- if (LOCSIG(buf) != LOCSIG)
- throw new ZipException("loc: wrong sig ->"
- + Long.toString(LOCSIG(buf), 16));
-
- int locElen = LOCEXT(buf);
- if (locElen < 9) // EXTT is at lease 9 bytes
- break;
- int locNlen = LOCNAM(buf);
- buf = new byte[locElen];
- if (zipfs.readFullyAt(buf, 0, buf.length , locoff + LOCHDR + locNlen)
- != buf.length)
- throw new ZipException("loc extra: reading failed");
- int locPos = 0;
- while (locPos + 4 < buf.length) {
- int locTag = SH(buf, locPos);
- int locSZ = SH(buf, locPos + 2);
- locPos += 4;
- if (locTag != EXTID_EXTT) {
- locPos += locSZ;
- continue;
- }
- int flag = CH(buf, locPos++);
- if ((flag & 0x1) != 0) {
- mtime = unixToJavaTime(LG(buf, locPos));
- locPos += 4;
- }
- if ((flag & 0x2) != 0) {
- atime = unixToJavaTime(LG(buf, locPos));
- locPos += 4;
- }
- if ((flag & 0x4) != 0) {
- ctime = unixToJavaTime(LG(buf, locPos));
- locPos += 4;
- }
- break;
- }
- break;
- default: // unknown tag
- System.arraycopy(extra, off, extra, newOff, sz + 4);
- newOff += (sz + 4);
- }
- off += (sz + 4);
- }
- if (newOff != 0 && newOff != extra.length)
- extra = Arrays.copyOf(extra, newOff);
- else
- extra = null;
- }
- }
-
- private static class ExChannelCloser {
- Path path;
- SeekableByteChannel ch;
- Set<InputStream> streams;
- ExChannelCloser(Path path,
- SeekableByteChannel ch,
- Set<InputStream> streams)
- {
- this.path = path;
- this.ch = ch;
- this.streams = streams;
- }
- }
-
- // ZIP directory has two issues:
- // (1) ZIP spec does not require the ZIP file to include
- // directory entry
- // (2) all entries are not stored/organized in a "tree"
- // structure.
- // A possible solution is to build the node tree ourself as
- // implemented below.
- private IndexNode root;
-
- private void addToTree(IndexNode inode, HashSet<IndexNode> dirs) {
- if (dirs.contains(inode)) {
- return;
- }
- IndexNode parent;
- byte[] name = inode.name;
- byte[] pname = getParent(name);
- if (inodes.containsKey(LOOKUPKEY.as(pname))) {
- parent = inodes.get(LOOKUPKEY);
- } else { // pseudo directory entry
- parent = new IndexNode(pname, -1);
- inodes.put(parent, parent);
- }
- addToTree(parent, dirs);
- inode.sibling = parent.child;
- parent.child = inode;
- if (name[name.length -1] == '/')
- dirs.add(inode);
- }
-
- private void removeFromTree(IndexNode inode) {
- IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
- IndexNode child = parent.child;
- if (child.equals(inode)) {
- parent.child = child.sibling;
- } else {
- IndexNode last = child;
- while ((child = child.sibling) != null) {
- if (child.equals(inode)) {
- last.sibling = child.sibling;
- break;
- } else {
- last = child;
- }
- }
- }
- }
-
- private void buildNodeTree() throws IOException {
- beginWrite();
- try {
- HashSet<IndexNode> dirs = new HashSet<>();
- IndexNode root = new IndexNode(ROOTPATH, -1);
- inodes.put(root, root);
- dirs.add(root);
- for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) {
- addToTree(node, dirs);
- }
- } finally {
- endWrite();
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.DirectoryStream.Filter;
-import java.nio.file.attribute.*;
-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;
-import java.util.zip.ZipError;
-import java.util.concurrent.ExecutorService;
-
-/*
- *
- * @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 "jar";
- }
-
- protected Path uriToPath(URI uri) {
- String scheme = uri.getScheme();
- if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
- throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
- }
- try {
- // only support legacy JAR URL syntax jar:{uri}!/{entry} for now
- String spec = uri.getRawSchemeSpecificPart();
- int sep = spec.indexOf("!/");
- if (sep != -1)
- spec = spec.substring(0, sep);
- return Paths.get(new URI(spec)).toAbsolutePath();
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e.getMessage(), e);
- }
- }
-
- private boolean ensureFile(Path path) {
- try {
- BasicFileAttributes attrs =
- Files.readAttributes(path, BasicFileAttributes.class);
- if (!attrs.isRegularFile())
- throw new UnsupportedOperationException();
- return true;
- } catch (IOException ioe) {
- return false;
- }
- }
-
- @Override
- public FileSystem newFileSystem(URI uri, Map<String, ?> env)
- throws IOException
- {
- Path path = uriToPath(uri);
- synchronized(filesystems) {
- Path realPath = null;
- if (ensureFile(path)) {
- realPath = path.toRealPath();
- if (filesystems.containsKey(realPath))
- throw new FileSystemAlreadyExistsException();
- }
- ZipFileSystem zipfs = null;
- try {
- zipfs = new ZipFileSystem(this, path, env);
- } catch (ZipError ze) {
- String pname = path.toString();
- if (pname.endsWith(".zip") || pname.endsWith(".jar"))
- throw ze;
- // assume NOT a zip/jar file
- throw new UnsupportedOperationException();
- }
- filesystems.put(realPath, zipfs);
- return zipfs;
- }
- }
-
- @Override
- public FileSystem newFileSystem(Path path, Map<String, ?> env)
- throws IOException
- {
- if (path.getFileSystem() != FileSystems.getDefault()) {
- throw new UnsupportedOperationException();
- }
- ensureFile(path);
- try {
- return new ZipFileSystem(this, path, env);
- } catch (ZipError ze) {
- String pname = path.toString();
- if (pname.endsWith(".zip") || pname.endsWith(".jar"))
- throw ze;
- throw new UnsupportedOperationException();
- }
- }
-
- @Override
- public Path getPath(URI uri) {
-
- String spec = uri.getSchemeSpecificPart();
- int sep = spec.indexOf("!/");
- if (sep == -1)
- throw new IllegalArgumentException("URI: "
- + uri
- + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
- return getFileSystem(uri).getPath(spec.substring(sep + 1));
- }
-
-
- @Override
- public FileSystem getFileSystem(URI uri) {
- synchronized (filesystems) {
- ZipFileSystem zipfs = null;
- try {
- zipfs = filesystems.get(uriToPath(uri).toRealPath());
- } catch (IOException x) {
- // ignore the ioe from toRealPath(), return FSNFE
- }
- if (zipfs == null)
- throw new FileSystemNotFoundException();
- return zipfs;
- }
- }
-
- // Checks that the given file is a UnixPath
- static final ZipPath toZipPath(Path path) {
- if (path == null)
- throw new NullPointerException();
- if (!(path instanceof ZipPath))
- throw new ProviderMismatchException();
- return (ZipPath)path;
- }
-
- @Override
- public void checkAccess(Path path, AccessMode... modes) throws IOException {
- toZipPath(path).checkAccess(modes);
- }
-
- @Override
- public void copy(Path src, Path target, CopyOption... options)
- throws IOException
- {
- toZipPath(src).copy(toZipPath(target), options);
- }
-
- @Override
- public void createDirectory(Path path, FileAttribute<?>... attrs)
- throws IOException
- {
- toZipPath(path).createDirectory(attrs);
- }
-
- @Override
- public final void delete(Path path) throws IOException {
- toZipPath(path).delete();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public <V extends FileAttributeView> V
- getFileAttributeView(Path path, Class<V> type, LinkOption... options)
- {
- return ZipFileAttributeView.get(toZipPath(path), type);
- }
-
- @Override
- public FileStore getFileStore(Path path) throws IOException {
- return toZipPath(path).getFileStore();
- }
-
- @Override
- public boolean isHidden(Path path) {
- return toZipPath(path).isHidden();
- }
-
- @Override
- public boolean isSameFile(Path path, Path other) throws IOException {
- return toZipPath(path).isSameFile(other);
- }
-
- @Override
- public void move(Path src, Path target, CopyOption... options)
- throws IOException
- {
- toZipPath(src).move(toZipPath(target), options);
- }
-
- @Override
- public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
- Set<? extends OpenOption> options,
- ExecutorService exec,
- FileAttribute<?>... attrs)
- throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SeekableByteChannel newByteChannel(Path path,
- Set<? extends OpenOption> options,
- FileAttribute<?>... attrs)
- throws IOException
- {
- return toZipPath(path).newByteChannel(options, attrs);
- }
-
- @Override
- public DirectoryStream<Path> newDirectoryStream(
- Path path, Filter<? super Path> filter) throws IOException
- {
- return toZipPath(path).newDirectoryStream(filter);
- }
-
- @Override
- public FileChannel newFileChannel(Path path,
- Set<? extends OpenOption> options,
- FileAttribute<?>... attrs)
- throws IOException
- {
- return toZipPath(path).newFileChannel(options, attrs);
- }
-
- @Override
- public InputStream newInputStream(Path path, OpenOption... options)
- throws IOException
- {
- return toZipPath(path).newInputStream(options);
- }
-
- @Override
- public OutputStream newOutputStream(Path path, OpenOption... options)
- throws IOException
- {
- return toZipPath(path).newOutputStream(options);
- }
-
- @Override
- public <A extends BasicFileAttributes> A
- readAttributes(Path path, Class<A> type, LinkOption... options)
- throws IOException
- {
- if (type == BasicFileAttributes.class || type == ZipFileAttributes.class)
- return (A)toZipPath(path).getAttributes();
- return null;
- }
-
- @Override
- public Map<String, Object>
- readAttributes(Path path, String attribute, LinkOption... options)
- throws IOException
- {
- return toZipPath(path).readAttributes(attribute, options);
- }
-
- @Override
- public Path readSymbolicLink(Path link) throws IOException {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- @Override
- public void setAttribute(Path path, String attribute,
- Object value, LinkOption... options)
- throws IOException
- {
- toZipPath(path).setAttribute(attribute, value, options);
- }
-
- //////////////////////////////////////////////////////////////
- void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException {
- synchronized (filesystems) {
- zfpath = zfpath.toRealPath();
- if (filesystems.get(zfpath) == zfs)
- filesystems.remove(zfpath);
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.Map;
-import static com.sun.nio.zipfs.ZipConstants.*;
-import static com.sun.nio.zipfs.ZipUtils.*;
-
-/**
- * Print all loc and cen headers of the ZIP file
- *
- * @author Xueming Shen
- */
-
-public class ZipInfo {
-
- public static void main(String[] args) throws Throwable {
- if (args.length < 1) {
- print("Usage: java ZipInfo zfname");
- } else {
- Map<String, ?> env = Collections.emptyMap();
- ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
- .newFileSystem(Paths.get(args[0]), env));
- byte[] cen = zfs.cen;
- if (cen == null) {
- print("zip file is empty%n");
- return;
- }
- int pos = 0;
- byte[] buf = new byte[1024];
- int no = 1;
- while (pos + CENHDR < cen.length) {
- print("----------------#%d--------------------%n", no++);
- printCEN(cen, pos);
-
- // use size CENHDR as the extra bytes to read, just in case the
- // loc.extra is bigger than the cen.extra, try to avoid to read
- // twice
- long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR;
- if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
- ZipFileSystem.zerror("read loc header failed");
- if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) {
- // have to read the second time;
- len = LOCHDR + LOCNAM(buf) + LOCEXT(buf);
- if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
- ZipFileSystem.zerror("read loc header failed");
- }
- printLOC(buf);
- pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos);
- }
- zfs.close();
- }
- }
-
- static void print(String fmt, Object... objs) {
- System.out.printf(fmt, objs);
- }
-
- static void printLOC(byte[] loc) {
- print("%n");
- print("[Local File Header]%n");
- print(" Signature : %#010x%n", LOCSIG(loc));
- if (LOCSIG(loc) != LOCSIG) {
- print(" Wrong signature!");
- return;
- }
- print(" Version : %#6x [%d.%d]%n",
- LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10);
- print(" Flag : %#6x%n", LOCFLG(loc));
- print(" Method : %#6x%n", LOCHOW(loc));
- print(" LastMTime : %#10x [%tc]%n",
- LOCTIM(loc), dosToJavaTime(LOCTIM(loc)));
- print(" CRC : %#10x%n", LOCCRC(loc));
- print(" CSize : %#10x%n", LOCSIZ(loc));
- print(" Size : %#10x%n", LOCLEN(loc));
- print(" NameLength : %#6x [%s]%n",
- LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc)));
- print(" ExtraLength : %#6x%n", LOCEXT(loc));
- if (LOCEXT(loc) != 0)
- printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc));
- }
-
- static void printCEN(byte[] cen, int off) {
- print("[Central Directory Header]%n");
- print(" Signature : %#010x%n", CENSIG(cen, off));
- if (CENSIG(cen, off) != CENSIG) {
- print(" Wrong signature!");
- return;
- }
- print(" VerMadeby : %#6x [%d, %d.%d]%n",
- CENVEM(cen, off), (CENVEM(cen, off) >> 8),
- (CENVEM(cen, off) & 0xff) / 10,
- (CENVEM(cen, off) & 0xff) % 10);
- print(" VerExtract : %#6x [%d.%d]%n",
- CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10);
- print(" Flag : %#6x%n", CENFLG(cen, off));
- print(" Method : %#6x%n", CENHOW(cen, off));
- print(" LastMTime : %#10x [%tc]%n",
- CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off)));
- print(" CRC : %#10x%n", CENCRC(cen, off));
- print(" CSize : %#10x%n", CENSIZ(cen, off));
- print(" Size : %#10x%n", CENLEN(cen, off));
- print(" NameLen : %#6x [%s]%n",
- CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off)));
- print(" ExtraLen : %#6x%n", CENEXT(cen, off));
- if (CENEXT(cen, off) != 0)
- printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off));
- print(" CommentLen : %#6x%n", CENCOM(cen, off));
- print(" DiskStart : %#6x%n", CENDSK(cen, off));
- print(" Attrs : %#6x%n", CENATT(cen, off));
- print(" AttrsEx : %#10x%n", CENATX(cen, off));
- print(" LocOff : %#10x%n", CENOFF(cen, off));
-
- }
-
- static long locoff(byte[] cen, int pos) {
- long locoff = CENOFF(cen, pos);
- if (locoff == ZIP64_MINVAL) { //ZIP64
- int off = pos + CENHDR + CENNAM(cen, pos);
- int end = off + CENEXT(cen, pos);
- while (off + 4 < end) {
- int tag = SH(cen, off);
- int sz = SH(cen, off + 2);
- if (tag != EXTID_ZIP64) {
- off += 4 + sz;
- continue;
- }
- off += 4;
- if (CENLEN(cen, pos) == ZIP64_MINVAL)
- off += 8;
- if (CENSIZ(cen, pos) == ZIP64_MINVAL)
- off += 8;
- return LL(cen, off);
- }
- // should never be here
- }
- return locoff;
- }
-
- static void printExtra(byte[] extra, int off, int len) {
- int end = off + len;
- while (off + 4 <= end) {
- int tag = SH(extra, off);
- int sz = SH(extra, off + 2);
- print(" [tag=0x%04x, sz=%d, data= ", tag, sz);
- if (off + sz > end) {
- print(" Error: Invalid extra data, beyond extra length");
- break;
- }
- off += 4;
- for (int i = 0; i < sz; i++)
- print("%02x ", extra[off + i]);
- print("]%n");
- switch (tag) {
- case EXTID_ZIP64 :
- print(" ->ZIP64: ");
- int pos = off;
- while (pos + 8 <= off + sz) {
- print(" *0x%x ", LL(extra, pos));
- pos += 8;
- }
- print("%n");
- break;
- case EXTID_NTFS:
- print(" ->PKWare NTFS%n");
- // 4 bytes reserved
- if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24)
- print(" Error: Invalid NTFS sub-tag or subsz");
- print(" mtime:%tc%n",
- winToJavaTime(LL(extra, off + 8)));
- print(" atime:%tc%n",
- winToJavaTime(LL(extra, off + 16)));
- print(" ctime:%tc%n",
- winToJavaTime(LL(extra, off + 24)));
- break;
- case EXTID_EXTT:
- print(" ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]);
- pos = off + 1 ;
- while (pos + 4 <= off + sz) {
- print(" *%tc%n",
- unixToJavaTime(LG(extra, pos)));
- pos += 4;
- }
- break;
- default:
- print(" ->[tag=%x, size=%d]%n", tag, sz);
- }
- off += sz;
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,884 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.*;
-import java.net.URI;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.DirectoryStream.Filter;
-import java.nio.file.attribute.*;
-import java.util.*;
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-
-
-/**
- *
- * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
- */
-
-public class ZipPath implements 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 getFileName() {
- 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(LinkOption... options) throws IOException {
- ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath();
- realPath.checkAccess();
- return realPath;
- }
-
- 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() {
- try {
- return new URI("jar",
- zfs.getZipFile().toUri() +
- "!" +
- zfs.getString(toAbsolutePath().path),
- null);
- } 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 new ZipPath(getFileSystem(), new byte[0], true);
- 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.length > 0 && path[0] == '/');
- }
-
- @Override
- public ZipPath resolve(Path other) {
- 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 Path resolveSibling(Path other) {
- if (other == null)
- throw new NullPointerException();
- Path parent = getParent();
- return (parent == null) ? other : parent.resolve(other);
- }
-
- @Override
- public boolean startsWith(Path other) {
- final ZipPath o = checkPath(other);
- if (o.isAbsolute() != this.isAbsolute() ||
- o.path.length > this.path.length)
- return false;
- int olast = o.path.length;
- for (int i = 0; i < olast; i++) {
- if (o.path[i] != this.path[i])
- return false;
- }
- olast--;
- return o.path.length == this.path.length ||
- o.path[olast] == '/' ||
- this.path[olast + 1] == '/';
- }
-
- @Override
- public boolean endsWith(Path other) {
- final ZipPath o = checkPath(other);
- int olast = o.path.length - 1;
- if (olast > 0 && o.path[olast] == '/')
- olast--;
- int last = this.path.length - 1;
- if (last > 0 && this.path[last] == '/')
- last--;
- if (olast == -1) // o.path.length == 0
- return last == -1;
- if ((o.isAbsolute() &&(!this.isAbsolute() || olast != last)) ||
- (last < olast))
- return false;
- for (; olast >= 0; olast--, last--) {
- if (o.path[olast] != this.path[last])
- return false;
- }
- return o.path[olast + 1] == '/' ||
- last == -1 || this.path[last] == '/';
- }
-
- @Override
- public ZipPath resolve(String other) {
- return resolve(getFileSystem().getPath(other));
- }
-
- @Override
- public final Path resolveSibling(String other) {
- return resolveSibling(getFileSystem().getPath(other));
- }
-
- @Override
- public final boolean startsWith(String other) {
- return startsWith(getFileSystem().getPath(other));
- }
-
- @Override
- public final boolean endsWith(String other) {
- return endsWith(getFileSystem().getPath(other));
- }
-
- @Override
- public Path normalize() {
- byte[] resolved = getResolved();
- if (resolved == path) // no change
- return this;
- 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)'.') {
- if (m == 0 && path[0] == '/') // absolute path
- to[m++] = '/';
- 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;
- }
-
- 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 final File toFile() {
- throw new UnsupportedOperationException();
- }
-
- @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();
- }
- };
- }
-
- /////////////////////////////////////////////////////////////////////
-
-
- void createDirectory(FileAttribute<?>... attrs)
- throws IOException
- {
- zfs.createDirectory(getResolvedPath(), attrs);
- }
-
- 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());
- }
-
- DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
- throws IOException
- {
- return new ZipDirectoryStream(this, filter);
- }
-
- void delete() throws IOException {
- zfs.deleteFile(getResolvedPath(), true);
- }
-
- 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;
- }
-
- 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);
- }
-
- Map<String, Object> readAttributes(String attributes, LinkOption... options)
- throws IOException
-
- {
- String view = null;
- String attrs = null;
- int colonPos = attributes.indexOf(':');
- if (colonPos == -1) {
- view = "basic";
- attrs = attributes;
- } else {
- view = attributes.substring(0, colonPos++);
- attrs = attributes.substring(colonPos);
- }
- ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
- if (zfv == null) {
- throw new UnsupportedOperationException("view not supported");
- }
- return zfv.readAttributes(attrs);
- }
-
- 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));
- }
-
- boolean isSameFile(Path other) throws IOException {
- if (this.equals(other))
- return true;
- if (other == null ||
- this.getFileSystem() != other.getFileSystem())
- return false;
- this.checkAccess();
- ((ZipPath)other).checkAccess();
- return Arrays.equals(this.getResolvedPath(),
- ((ZipPath)other).getResolvedPath());
- }
-
- 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);
- }
-
- 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());
- }
-
- boolean exists() {
- if (path.length == 1 && path[0] == '/')
- return true;
- try {
- return zfs.exists(getResolvedPath());
- } catch (IOException x) {}
- return false;
- }
-
- OutputStream newOutputStream(OpenOption... options) throws IOException
- {
- if (options.length == 0)
- return zfs.newOutputStream(getResolvedPath(),
- CREATE_NEW, WRITE);
- return zfs.newOutputStream(getResolvedPath(), options);
- }
-
- void move(ZipPath target, CopyOption... options)
- throws IOException
- {
- if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
- {
- zfs.copyFile(true,
- getResolvedPath(), target.getResolvedPath(),
- options);
- } else {
- copyToTarget(target, options);
- delete();
- }
- }
-
- void copy(ZipPath target, CopyOption... options)
- throws IOException
- {
- if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
- zfs.copyFile(false,
- getResolvedPath(), target.getResolvedPath(),
- options);
- else
- copyToTarget(target, options);
- }
-
- private void copyToTarget(ZipPath 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 = true;
- }
- // 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 =
- ZipFileAttributeView.get(target, BasicFileAttributeView.class);
- try {
- view.setTimes(zfas.lastModifiedTime(),
- zfas.lastAccessTime(),
- zfas.creationTime());
- } catch (IOException x) {
- // rollback?
- try {
- target.delete();
- } catch (IOException ignore) { }
- throw x;
- }
- }
- }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-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;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- * @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 & 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 & 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 & 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;
- }
-
-
- // used to adjust values between Windows and java epoch
- private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
- public static final long winToJavaTime(long wtime) {
- return TimeUnit.MILLISECONDS.convert(
- wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
- }
-
- public static final long javaToWinTime(long time) {
- return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
- - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
- }
-
- public static final long unixToJavaTime(long utime) {
- return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
- }
-
- public static final long javaToUnixTime(long time) {
- return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
- }
-
- 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();
- }
-}
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -5166,39 +5166,7 @@
} else if (log_file[0] != '\0' && (errstrm = fopen(log_file,"a+")) != NULL) {
return;
} else {
- char log_file_name[PATH_MAX+100];
- char tmpdir[PATH_MAX];
-#ifdef WIN32
- int n = GetTempPath(PATH_MAX,tmpdir); //API returns with trailing '\'
- if (n < 1 || n > PATH_MAX) {
- sprintf(tmpdir,"C:\\");
- }
- sprintf(log_file_name, "%sunpack.log", tmpdir);
-#else
- sprintf(tmpdir,"/tmp");
- sprintf(log_file_name, "/tmp/unpack.log");
-#endif
- if ((errstrm = fopen(log_file_name, "a+")) != NULL) {
- log_file = errstrm_name = saveStr(log_file_name);
- return ;
- }
-
- char *tname = tempnam(tmpdir,"#upkg");
- if (tname == NULL) return;
- sprintf(log_file_name, "%s", tname);
- ::free(tname);
- if ((errstrm = fopen(log_file_name, "a+")) != NULL) {
- log_file = errstrm_name = saveStr(log_file_name);
- return ;
- }
-#ifndef WIN32
- sprintf(log_file_name, "/dev/null");
- // On windows most likely it will fail.
- if ( (errstrm = fopen(log_file_name, "a+")) != NULL) {
- log_file = errstrm_name = saveStr(log_file_name);
- return ;
- }
-#endif
+ fprintf(stderr, "Can not open log file %s\n", log_file);
// Last resort
// (Do not use stdout, since it might be jarout->jarfp.)
errstrm = stderr;
--- a/jdk/src/share/native/sun/awt/giflib/dgif_lib.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/giflib/dgif_lib.c Wed Apr 16 10:53:10 2014 -0700
@@ -435,9 +435,7 @@
Private->PixelCount = (long)GifFile->Image.Width *
(long)GifFile->Image.Height;
- DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
-
- return GIF_OK;
+ return DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
}
/******************************************************************************
--- a/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c Wed Apr 16 10:53:10 2014 -0700
@@ -249,6 +249,7 @@
/* fill the block */
len = (*env)->CallIntMethod(env, this, readID,
blockh, remain, blockLength + 1);
+ if (len > blockLength + 1) len = blockLength + 1;
if ((*env)->ExceptionOccurred(env)) {
return 0;
}
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Wed Apr 16 10:53:10 2014 -0700
@@ -945,6 +945,9 @@
JPEGImageReader_readInputDataID,
sb->hstreamBuffer, 0,
sb->bufferLength);
+ if ((ret > 0) && ((unsigned int)ret > sb->bufferLength)) {
+ ret = sb->bufferLength;
+ }
if ((*env)->ExceptionOccurred(env)
|| !GET_ARRAYS(env, data, &(src->next_input_byte))) {
cinfo->err->error_exit((j_common_ptr) cinfo);
@@ -1041,6 +1044,7 @@
JPEGImageReader_readInputDataID,
sb->hstreamBuffer,
offset, buflen);
+ if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
if ((*env)->ExceptionOccurred(env)
|| !GET_ARRAYS(env, data, &(src->next_input_byte))) {
cinfo->err->error_exit((j_common_ptr) cinfo);
--- a/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Wed Apr 16 10:53:10 2014 -0700
@@ -349,6 +349,12 @@
TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
compptr->dc_tbl_no, compptr->ac_tbl_no);
+
+ /* This CSi (cc) should differ from the previous CSi */
+ for (ci = 0; ci < i; ci++) {
+ if (cinfo->cur_comp_info[ci] == compptr)
+ ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+ }
}
/* Collect the additional scan parameters Ss, Se, Ah/Al. */
--- a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Wed Apr 16 10:53:10 2014 -0700
@@ -289,6 +289,7 @@
buflen = (*env)->GetArrayLength(env, src->hInputBuffer);
ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID,
src->hInputBuffer, 0, buflen);
+ if (ret > buflen) ret = buflen;
if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) {
cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
}
@@ -349,6 +350,7 @@
}
ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID,
src->hInputBuffer, offset, buflen);
+ if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) {
cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
}
@@ -424,6 +426,7 @@
ret = (*env)->CallIntMethod(env, src->hInputStream,
InputStream_readID,
src->hInputBuffer, 0, buflen);
+ if (ret > buflen) ret = buflen;
if ((*env)->ExceptionOccurred(env)) {
cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
}
--- a/jdk/src/share/native/sun/awt/libpng/pngrtran.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/libpng/pngrtran.c Wed Apr 16 10:53:10 2014 -0700
@@ -1862,6 +1862,9 @@
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
+
+ if (png_ptr->palette == NULL)
+ png_error (png_ptr, "Palette is NULL in indexed image");
}
else
{
--- a/jdk/src/share/native/sun/awt/libpng/pngset.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/libpng/pngset.c Wed Apr 16 10:53:10 2014 -0700
@@ -512,6 +512,17 @@
}
}
+ if ((num_palette > 0 && palette == NULL) ||
+ (num_palette == 0
+# ifdef PNG_MNG_FEATURES_SUPPORTED
+ && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+# endif
+ ))
+ {
+ png_error(png_ptr, "Invalid palette");
+ return;
+ }
+
/* It may not actually be necessary to set png_ptr->palette here;
* we do it for backward compatibility with the way the png_handle_tRNS
* function used to do the allocation.
--- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Wed Apr 16 10:53:10 2014 -0700
@@ -228,6 +228,49 @@
}
}
+/*
+ * We have to make sure that awt_setPixels can be safely applied to the given pair of
+ * raster and mlib image.
+ *
+ * In particular, make sure that
+ * - dimension is the same
+ * - number of channels in mlib image corresponds to the number of bands in the raster
+ * - sample size in image and raster are the same.
+ *
+ * Returns:
+ * -1 to indicate failure,
+ * 1 to indicate success
+ */
+static int setPixelsFormMlibImage(JNIEnv *env, RasterS_t *rasterP, mlib_image* img) {
+ if (rasterP->width != img->width || rasterP->height != img->height) {
+ /* dimension does not match */
+ return -1;
+ }
+
+ if (rasterP->numBands != img->channels) {
+ /* number of bands does not match */
+ return -1;
+ }
+
+ switch (rasterP->dataType) {
+ case BYTE_DATA_TYPE:
+ if (img->type != MLIB_BYTE) {
+ return -1;
+ }
+ break;
+ case SHORT_DATA_TYPE:
+ if (img->type != MLIB_SHORT && img->type != MLIB_USHORT) {
+ return -1;
+ }
+ break;
+ default:
+ /* awt_setPixels does not support such rasters */
+ return -1;
+ }
+
+ return awt_setPixels(env, rasterP, mlib_ImageGetData(img));
+}
+
/***************************************************************************
* External Functions *
***************************************************************************/
@@ -700,7 +743,9 @@
/* Means that we couldn't write directly into the destination buffer */
if (ddata == NULL) {
- retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
+ if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
+ retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
+ }
}
/* Release the pinned memory */
@@ -1107,7 +1152,7 @@
/* Need to store it back into the array */
if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
(*env)->ExceptionClear(env); // Could not store the array, try another way
- retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
+ retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
}
}
@@ -1433,6 +1478,14 @@
retStatus = 0;
}
+ /* Release the LUT */
+ for (i=0; i < lut_nbands; i++) {
+ (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
+ (jbyte *) jtable[i].table, JNI_ABORT);
+ }
+ free ((void *) jtable);
+ free ((void *) tbl);
+
/*
* Means that we couldn't write directly into
* the destination buffer
@@ -1446,13 +1499,6 @@
}
}
- /* Release the LUT */
- for (i=0; i < lut_nbands; i++) {
- (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
- (jbyte *) jtable[i].table, JNI_ABORT);
- }
- free ((void *) jtable);
- free ((void *) tbl);
/* Release the pinned memory */
freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
@@ -1670,18 +1716,20 @@
retStatus = 0;
}
+ /* Release the LUT */
+ for (i=0; i < lut_nbands; i++) {
+ (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
+ (jbyte *) jtable[i].table, JNI_ABORT);
+ }
+
/*
* Means that we couldn't write directly into
* the destination buffer
*/
if (ddata == NULL) {
- retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
- }
-
- /* Release the LUT */
- for (i=0; i < lut_nbands; i++) {
- (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
- (jbyte *) jtable[i].table, JNI_ABORT);
+ if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
+ retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
+ }
}
/* Release the pinned memory */
@@ -2643,7 +2691,7 @@
}
}
else if (mlibImP->type == MLIB_SHORT) {
- return awt_setPixels(env, rasterP, mlibImP->data);
+ return setPixelsFormMlibImage(env, rasterP, mlibImP);
}
}
else {
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -154,6 +154,7 @@
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
LEReferenceToArrayOf<LookupValue> valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount);
+ if (LE_FAILURE(success)) { return newGlyph; }
newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success));
}
}
--- a/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -110,6 +110,8 @@
LEErrorCode &success,
le_bool backtrack)
{
+ if (LE_FAILURE(success)) { return FALSE; }
+
le_int32 direction = 1;
le_int32 match = 0;
@@ -255,6 +257,7 @@
le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
le_uint16 substCount = SWAPW(subRuleTable->substCount);
LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2);
+ if (LE_FAILURE(success)) { return 0; }
if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) {
LEReferenceToArrayOf<SubstitutionLookupRecord>
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount);
@@ -315,6 +318,7 @@
LEReferenceToArrayOf<le_uint16> classArray(base, success, subClassRuleTable->classArray, matchCount+1);
+ if (LE_FAILURE(success)) { return 0; }
if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) {
LEReferenceToArrayOf<SubstitutionLookupRecord>
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount);
@@ -573,7 +577,7 @@
if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
LEReferenceToArrayOf<SubstitutionLookupRecord>
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
-
+ if (LE_FAILURE(success)) { return 0; }
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
return inputGlyphCount + 1;
@@ -601,9 +605,10 @@
le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
LEReferenceToArrayOf<Offset> inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset
+ if (LE_FAILURE(success)) { return 0; }
const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
- if( LE_FAILURE(success) ) { return 0; }
+ if( LE_FAILURE(success)) { return 0; }
LEReferenceToArrayOf<Offset> lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2);
if( LE_FAILURE(success) ) { return 0; }
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -95,7 +95,7 @@
if (actionOffset != 0) {
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
- ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment)
+ ap.addObject(ligActionIndex, success);
LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
LigatureActionEntry action;
le_int32 offset, i = 0;
@@ -111,7 +111,6 @@
do {
le_uint32 componentGlyph = componentStack[m--]; // pop off
- ap.addObject(success);
action = SWAPL(*ap.getAlias());
if (m < 0) {
@@ -145,7 +144,8 @@
LE_DEBUG_BAD_FONT("m<0")
}
#endif
- } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
+ ap.addObject(success);
+ } while (LE_SUCCESS(success) && !(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
while (mm >= 0) {
if (++m >= nComponents) {
--- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -282,6 +282,7 @@
for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
+ if (LE_FAILURE(success)) { continue; }
le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
// don't add the required feature to the list more than once...
--- a/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -67,6 +67,7 @@
LEPoint markAnchor;
LEReferenceTo<MarkArray> markArray(base, success, (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)));
+ if(LE_FAILURE(success)) return 0;
le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success);
le_uint16 mcCount = SWAPW(classCount);
--- a/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -79,8 +79,8 @@
Offset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success)
{
+ if(LE_FAILURE(success)) return 0;
const TagAndOffsetRecord *r0 = (const TagAndOffsetRecord*)records.getAlias();
- if(LE_FAILURE(success)) return 0;
le_uint32 recordCount = records.getCount();
le_uint8 bit = highBit(recordCount);
--- a/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -73,6 +73,7 @@
if (offset != 0) {
LEReferenceToArrayOf<TTGlyphID> glyphArray(subtableHeader, success, offset, LE_UNBOUNDED_ARRAY);
+ if (LE_FAILURE(success)) { continue; }
TTGlyphID newGlyph = SWAPW(glyphArray(LE_GET_GLYPH(thisGlyph) - firstGlyph, success));
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -97,6 +97,7 @@
LEReferenceToArrayOf<EntryTableIndex> stateArray(stHeader, success, currentState, LE_UNBOUNDED_ARRAY);
EntryTableIndex entryTableIndex = stateArray.getObject((le_uint8)classCode, success);
+ if (LE_FAILURE(success)) { break; }
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
LE_STATE_PATIENCE_INCR(currGlyph);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Wed Apr 16 10:53:10 2014 -0700
@@ -81,7 +81,7 @@
cmsUInt32Number surround;
cmsFloat64Number n, Nbb, Ncb, z, FL, D;
- cmsContext ContextID;
+ cmsContext ContextID;
} cmsCIECAM02;
@@ -467,6 +467,7 @@
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
+ memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
@@ -491,6 +492,7 @@
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
+ memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Wed Apr 16 10:53:10 2014 -0700
@@ -59,8 +59,8 @@
// IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
-#define MAXID 128 // Max lenght of identifier
-#define MAXSTR 1024 // Max lenght of string
+#define MAXID 128 // Max length of identifier
+#define MAXSTR 1024 // Max length of string
#define MAXTABLES 255 // Max Number of tables in a single stream
#define MAXINCLUDE 20 // Max number of nested includes
@@ -383,28 +383,28 @@
//Forward declaration of some internal functions
static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
-// Checks if c is a separator
+// Checks whatever c is a separator
static
cmsBool isseparator(int c)
{
- return (c == ' ') || (c == '\t') || (c == '\r');
+ return (c == ' ') || (c == '\t') ;
}
-// Checks whatever if c is a valid identifier char
+// Checks whatever c is a valid identifier char
static
cmsBool ismiddle(int c)
{
return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
}
-// Checks whatsever if c is a valid identifier middle char.
+// Checks whatsever c is a valid identifier middle char.
static
cmsBool isidchar(int c)
{
return isalnum(c) || ismiddle(c);
}
-// Checks whatsever if c is a valid identifier first char.
+// Checks whatsever c is a valid identifier first char.
static
cmsBool isfirstidchar(int c)
{
@@ -436,7 +436,6 @@
}
-
// Makes a file path based on a given reference path
// NOTE: this function doesn't check if the path exists or even if it's legal
static
@@ -634,6 +633,7 @@
cmsFloat64Number dnum = 0.0;
int sign = 1;
+ // keep safe
if (Buffer == NULL) return 0.0;
if (*Buffer == '-' || *Buffer == '+') {
@@ -869,6 +869,14 @@
// Next line
+ case '\r':
+ NextCh(it8);
+ if (it8 ->ch == '\n')
+ NextCh(it8);
+ it8->sy = SEOLN;
+ it8->lineno++;
+ break;
+
case '\n':
NextCh(it8);
it8->sy = SEOLN;
@@ -878,7 +886,7 @@
// Comment
case '#':
NextCh(it8);
- while (it8->ch && it8->ch != '\n')
+ while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
NextCh(it8);
it8->sy = SCOMMENT;
@@ -996,6 +1004,9 @@
{
switch (it8->sy) {
+ case SEOLN: // Empty value
+ Buffer[0]=0;
+ break;
case SIDENT: strncpy(Buffer, it8->id, max);
Buffer[max-1]=0;
break;
@@ -1145,9 +1156,9 @@
if (*Key != '#') { // Comments are ignored
if (cmsstrcasecmp(Key, p->Keyword) == 0)
- break;
+ break;
}
- }
+ }
if (p == NULL)
return FALSE;
@@ -1157,11 +1168,13 @@
for (; p != NULL; p = p->NextSubkey) {
+ if (p ->Subkey == NULL) continue;
+
if (LastPtr) *LastPtr = p;
if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
- return TRUE;
- }
+ return TRUE;
+ }
return FALSE;
}
@@ -1284,7 +1297,7 @@
it8 ->nTable = nTable;
- return nTable;
+ return (cmsInt32Number) nTable;
}
@@ -1389,7 +1402,7 @@
cmsIT8* it8 = (cmsIT8*) hIT8;
char Buffer[1024];
- sprintf(Buffer, "%d", Val);
+ sprintf(Buffer, "%u", Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
}
@@ -1426,6 +1439,8 @@
{
const char *v = cmsIT8GetProperty(hIT8, cProp);
+ if (v == NULL) return 0.0;
+
return ParseFloatNumber(v);
}
@@ -1458,7 +1473,7 @@
t -> nSamples = 10;
}
- t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *));
+ t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
if (t->DataFormat == NULL) {
SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
@@ -1514,7 +1529,7 @@
t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
- t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*));
+ t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*));
if (t->Data == NULL) {
SynError(it8, "AllocateDataSet: Unable to allocate data array");
@@ -1573,7 +1588,7 @@
if (str == NULL)
str = " ";
- // Lenghth to write
+ // Length to write
len = (cmsUInt32Number) strlen(str);
f ->Used += len;
@@ -2097,7 +2112,7 @@
NextCh(it8);
// If a newline is found, then this is a type string
- if (it8 ->ch == '\n') {
+ if (it8 ->ch == '\n' || it8->ch == '\r') {
cmsIT8SetSheetType(it8, it8 ->id);
InSymbol(it8);
@@ -2212,7 +2227,7 @@
char Buffer[256];
char *Type = p ->Value;
- int nTable = k;
+ int nTable = (int) k;
snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
@@ -2566,6 +2581,8 @@
Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
+ if (Buffer == NULL) return 0.0;
+
return ParseFloatNumber(Buffer);
}
@@ -2778,7 +2795,7 @@
if (Formatter == NULL)
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
else
- strcpy(it8->DoubleFormatter, Formatter);
+ strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Wed Apr 16 10:53:10 2014 -0700
@@ -270,7 +270,7 @@
// m2 holds CHAD from output white to D50 times abs. col. scaling
// Observer is not adapted, undo the chromatic adaptation
- _cmsMAT3per(m, &m3, ChromaticAdaptationMatrixOut);
+ _cmsMAT3per(m, &m2, ChromaticAdaptationMatrixOut);
m3 = *ChromaticAdaptationMatrixIn;
if (!_cmsMAT3inverse(&m3, &m4)) return FALSE;
@@ -411,57 +411,61 @@
// Handle PCS mismatches. A specialized stage is added to the LUT in such case
switch (InPCS) {
- case cmsSigXYZData: // Input profile operates in XYZ
-
- switch (OutPCS) {
+ case cmsSigXYZData: // Input profile operates in XYZ
- case cmsSigXYZData: // XYZ -> XYZ
- if (!IsEmptyLayer(m, off))
- cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
- break;
+ switch (OutPCS) {
- case cmsSigLabData: // XYZ -> Lab
- if (!IsEmptyLayer(m, off))
- cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
- cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
- break;
+ case cmsSigXYZData: // XYZ -> XYZ
+ if (!IsEmptyLayer(m, off) &&
+ !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+ return FALSE;
+ break;
- default:
- return FALSE; // Colorspace mismatch
- }
- break;
-
+ case cmsSigLabData: // XYZ -> Lab
+ if (!IsEmptyLayer(m, off) &&
+ !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+ return FALSE;
+ if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
+ return FALSE;
+ break;
- case cmsSigLabData: // Input profile operates in Lab
-
- switch (OutPCS) {
+ default:
+ return FALSE; // Colorspace mismatch
+ }
+ break;
- case cmsSigXYZData: // Lab -> XYZ
+ case cmsSigLabData: // Input profile operates in Lab
- cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
- if (!IsEmptyLayer(m, off))
- cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
- break;
+ switch (OutPCS) {
+
+ case cmsSigXYZData: // Lab -> XYZ
- case cmsSigLabData: // Lab -> Lab
+ if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)))
+ return FALSE;
+ if (!IsEmptyLayer(m, off) &&
+ !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+ return FALSE;
+ break;
- if (!IsEmptyLayer(m, off)) {
- cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
- cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
- cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
- }
- break;
+ case cmsSigLabData: // Lab -> Lab
- default:
- return FALSE; // Mismatch
+ if (!IsEmptyLayer(m, off)) {
+ if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)) ||
+ !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)) ||
+ !cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
+ return FALSE;
}
break;
+ default:
+ return FALSE; // Mismatch
+ }
+ break;
- // On colorspaces other than PCS, check for same space
- default:
- if (InPCS != OutPCS) return FALSE;
- break;
+ // On colorspaces other than PCS, check for same space
+ default:
+ if (InPCS != OutPCS) return FALSE;
+ break;
}
return TRUE;
@@ -497,7 +501,8 @@
cmsFloat64Number AdaptationStates[],
cmsUInt32Number dwFlags)
{
- cmsPipeline* Lut, *Result;
+ cmsPipeline* Lut = NULL;
+ cmsPipeline* Result;
cmsHPROFILE hProfile;
cmsMAT3 m;
cmsVEC3 off;
@@ -593,8 +598,11 @@
}
// Concatenate to the output LUT
- cmsPipelineCat(Result, Lut);
+ if (!cmsPipelineCat(Result, Lut))
+ goto Error;
+
cmsPipelineFree(Lut);
+ Lut = NULL;
// Update current space
CurrentColorSpace = ColorSpaceOut;
@@ -604,6 +612,7 @@
Error:
+ if (Lut != NULL) cmsPipelineFree(Lut);
if (Result != NULL) cmsPipelineFree(Result);
return NULL;
@@ -742,7 +751,8 @@
if (CLUT == NULL) goto Error;
// This is the one and only MPE in this LUT
- cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
+ if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
+ goto Error;
// Sample it. We cannot afford pre/post linearization this time.
if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
@@ -959,7 +969,8 @@
CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
if (CLUT == NULL) goto Cleanup;
- cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
+ if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
+ goto Cleanup;
cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
@@ -1057,7 +1068,7 @@
}
// The plug-in registration. User can add new intents or override default routines
-cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
cmsIntentsList* fl;
@@ -1072,7 +1083,7 @@
fl = SearchIntent(Plugin ->Intent);
if (fl == NULL) {
- fl = (cmsIntentsList*) _cmsPluginMalloc(sizeof(cmsIntentsList));
+ fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
if (fl == NULL) return FALSE;
}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Wed Apr 16 10:53:10 2014 -0700
@@ -302,8 +302,6 @@
return NULL;
}
-
-
chunk ->BlockSize = Initial;
chunk ->Used = 0;
chunk ->next = NULL;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Wed Apr 16 10:53:10 2014 -0700
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2012 Marti Maria Saguer
+// Copyright (c) 1998-2013 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -99,7 +99,7 @@
static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
// As a way to install new parametric curves
-cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
_cmsParametricCurvesCollection* fl;
@@ -110,7 +110,7 @@
return TRUE;
}
- fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(sizeof(_cmsParametricCurvesCollection));
+ fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
@@ -258,7 +258,8 @@
}
p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
- return p;
+ if (p->InterpParams != NULL)
+ return p;
Error:
if (p -> Segments) _cmsFree(ContextID, p ->Segments);
@@ -423,7 +424,7 @@
if (e > 0)
Val = pow(e, Params[0]) + Params[5];
else
- Val = 0;
+ Val = Params[5];
}
else
Val = R*Params[3] + Params[6];
@@ -458,7 +459,7 @@
e = Params[1]*R + Params[2];
if (e < 0)
- Val = 0;
+ Val = Params[3];
else
Val = pow(e, Params[0]) + Params[3];
break;
@@ -478,7 +479,7 @@
e = Params[2] * pow(R, Params[0]) + Params[3];
if (e <= 0)
- Val = 0;
+ Val = Params[4];
else
Val = Params[1]*log10(e) + Params[4];
break;
@@ -544,7 +545,7 @@
// Type == 0 means segment is sampled
if (g ->Segments[i].Type == 0) {
- cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0);
+ cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0);
cmsFloat32Number Out;
// Setup the table (TODO: clean that)
@@ -629,20 +630,21 @@
// Use a segmented curve to store the floating point table
cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[])
{
- cmsCurveSegment Seg[2];
+ cmsCurveSegment Seg[3];
- // Initialize segmented curve part up to 0
- Seg[0].x0 = -1;
+ // A segmented tone curve should have function segments in the first and last positions
+ // Initialize segmented curve part up to 0 to constant value = samples[0]
+ Seg[0].x0 = MINUS_INF;
Seg[0].x1 = 0;
Seg[0].Type = 6;
Seg[0].Params[0] = 1;
Seg[0].Params[1] = 0;
Seg[0].Params[2] = 0;
- Seg[0].Params[3] = 0;
+ Seg[0].Params[3] = values[0];
Seg[0].Params[4] = 0;
- // From zero to any
+ // From zero to 1
Seg[1].x0 = 0;
Seg[1].x1 = 1.0;
Seg[1].Type = 0;
@@ -650,7 +652,19 @@
Seg[1].nGridPoints = nEntries;
Seg[1].SampledPoints = (cmsFloat32Number*) values;
- return cmsBuildSegmentedToneCurve(ContextID, 2, Seg);
+ // Final segment is constant = lastsample
+ Seg[2].x0 = 1.0;
+ Seg[2].x1 = PLUS_INF;
+ Seg[2].Type = 6;
+
+ Seg[2].Params[0] = 1;
+ Seg[2].Params[1] = 0;
+ Seg[2].Params[2] = 0;
+ Seg[2].Params[3] = values[nEntries-1];
+ Seg[2].Params[4] = 0;
+
+
+ return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
}
// Parametric curves
@@ -993,7 +1007,7 @@
if (Tab == NULL) return FALSE;
- if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do
+ if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do
nItems = Tab -> nEntries;
@@ -1020,11 +1034,20 @@
if (z[i] == 0.) Zeros++;
if (z[i] >= 65535.) Poles++;
- if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
+ if (z[i] < z[i-1]) {
+ cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
+ return FALSE;
+ }
}
- if (Zeros > (nItems / 3)) return FALSE; // Degenerated, mostly zeros
- if (Poles > (nItems / 3)) return FALSE; // Degenerated, mostly poles
+ if (Zeros > (nItems / 3)) {
+ cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
+ return FALSE;
+ }
+ if (Poles > (nItems / 3)) {
+ cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
+ return FALSE;
+ }
// Seems ok
for (i=0; i < nItems; i++) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Wed Apr 16 10:53:10 2014 -0700
@@ -249,13 +249,10 @@
cmsFloat64Number dE1, dE2, ErrorRatio;
// Assume in-gamut by default.
- dE1 = 0.;
- dE2 = 0;
ErrorRatio = 1.0;
// Convert input to Lab
- if (t -> hInput != NULL)
- cmsDoTransform(t -> hInput, In, &LabIn1, 1);
+ cmsDoTransform(t -> hInput, In, &LabIn1, 1);
// converts from PCS to colorant. This always
// does return in-gamut values,
@@ -267,7 +264,7 @@
memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab));
// Try again, but this time taking Check as input
- cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1);
+ cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1);
cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1);
// Take difference of direct value
@@ -374,7 +371,7 @@
ProfileList[nGamutPCSposition] = hLab;
BPCList[nGamutPCSposition] = 0;
AdaptationList[nGamutPCSposition] = 1.0;
- Intents[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
+ IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
ColorSpace = cmsGetColorSpace(hGamut);
@@ -385,45 +382,48 @@
// 16 bits to Lab double
Chain.hInput = cmsCreateExtendedTransform(ContextID,
- nGamutPCSposition + 1,
- ProfileList,
- BPCList,
- Intents,
- AdaptationList,
- NULL, 0,
- dwFormat, TYPE_Lab_DBL,
- cmsFLAGS_NOCACHE);
+ nGamutPCSposition + 1,
+ ProfileList,
+ BPCList,
+ IntentList,
+ AdaptationList,
+ NULL, 0,
+ dwFormat, TYPE_Lab_DBL,
+ cmsFLAGS_NOCACHE);
// Does create the forward step. Lab double to device
dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
Chain.hForward = cmsCreateTransformTHR(ContextID,
- hLab, TYPE_Lab_DBL,
- hGamut, dwFormat,
- INTENT_RELATIVE_COLORIMETRIC,
- cmsFLAGS_NOCACHE);
+ hLab, TYPE_Lab_DBL,
+ hGamut, dwFormat,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOCACHE);
// Does create the backwards step
Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
- hLab, TYPE_Lab_DBL,
- INTENT_RELATIVE_COLORIMETRIC,
- cmsFLAGS_NOCACHE);
+ hLab, TYPE_Lab_DBL,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOCACHE);
// All ok?
- if (Chain.hForward && Chain.hReverse) {
+ if (Chain.hInput && Chain.hForward && Chain.hReverse) {
// Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
// dE when doing a transform back and forth on the colorimetric intent.
Gamut = cmsPipelineAlloc(ContextID, 3, 1);
-
if (Gamut != NULL) {
- CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
- cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT);
-
- cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
+ CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
+ if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
+ cmsPipelineFree(Gamut);
+ Gamut = NULL;
+ }
+ else {
+ cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
+ }
}
}
else
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Wed Apr 16 10:53:10 2014 -0700
@@ -83,7 +83,6 @@
// Set the interpolation method
-
cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
{
// Invoke factory, possibly in the Plug-in
@@ -831,7 +830,7 @@
register cmsUInt16Number Output[],
register const cmsInterpParams* p16)
{
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
+ const cmsUInt16Number* LutTable;
cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk;
int K0, K1;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Wed Apr 16 10:53:10 2014 -0700
@@ -154,7 +154,6 @@
return iohandler;
Error:
- if (fm) _cmsFree(ContextID, fm);
if (iohandler) _cmsFree(ContextID, iohandler);
return NULL;
@@ -223,12 +222,17 @@
// Writes data to memory, also keeps used space for further reference.
static
-cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr)
+cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr)
{
FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
if (ResData == NULL) return FALSE; // Housekeeping
+ // Check for available space. Clip.
+ if (iohandler ->UsedSpace + size > ResData->Size) {
+ size = ResData ->Size - iohandler ->UsedSpace;
+ }
+
if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing
memmove(ResData ->Block + ResData ->Pointer, Ptr, size);
@@ -350,7 +354,7 @@
return nReaded;
}
-// Position file pointer in the file
+// Postion file pointer in the file
static
cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset)
{
@@ -389,13 +393,15 @@
return TRUE;
}
-// Create a iohandler for disk based files. if FileName is NULL, then 'stream' member is also set
-// to NULL and no real writting is performed. This only happens in writting access mode
+// Create a iohandler for disk based files.
cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode)
{
cmsIOHANDLER* iohandler = NULL;
FILE* fm = NULL;
+ _cmsAssert(FileName != NULL);
+ _cmsAssert(AccessMode != NULL);
+
iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
if (iohandler == NULL) return NULL;
@@ -432,11 +438,8 @@
iohandler ->UsedSpace = 0;
// Keep track of the original file
- if (FileName != NULL) {
-
- strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
- iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
- }
+ strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
+ iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
iohandler ->Read = FileRead;
iohandler ->Seek = FileSeek;
@@ -616,6 +619,31 @@
return _cmsSearchTag(Icc, sig, FALSE) >= 0;
}
+/*
+ * Enforces that the profile version is per. spec.
+ * Operates on the big endian bytes from the profile.
+ * Called before converting to platform endianness.
+ * Byte 0 is BCD major version, so max 9.
+ * Byte 1 is 2 BCD digits, one per nibble.
+ * Reserved bytes 2 & 3 must be 0.
+ */
+static cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
+{
+ cmsUInt8Number* pByte = (cmsUInt8Number*)&DWord;
+ cmsUInt8Number temp1;
+ cmsUInt8Number temp2;
+
+ if (*pByte > 0x09) *pByte = (cmsUInt8Number)9;
+ temp1 = *(pByte+1) & 0xf0;
+ temp2 = *(pByte+1) & 0x0f;
+ if (temp1 > 0x90) temp1 = 0x90;
+ if (temp2 > 9) temp2 = 0x09;
+ *(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
+ *(pByte+2) = (cmsUInt8Number)0;
+ *(pByte+3) = (cmsUInt8Number)0;
+
+ return DWord;
+}
// Read profile header and validate it
cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
@@ -643,12 +671,15 @@
Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass);
Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace);
Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs);
+
Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent);
Icc -> flags = _cmsAdjustEndianess32(Header.flags);
Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer);
Icc -> model = _cmsAdjustEndianess32(Header.model);
+ Icc -> creator = _cmsAdjustEndianess32(Header.creator);
+
_cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
- Icc -> Version = _cmsAdjustEndianess32(Header.version);
+ Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version));
// Get size as reported in header
HeaderSize = _cmsAdjustEndianess32(Header.size);
@@ -815,28 +846,33 @@
cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
- return (cmsUInt32Number) Icc ->manufacturer;
+ return Icc ->manufacturer;
}
void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
- Icc -> manufacturer = (cmsUInt32Number) manufacturer;
+ Icc -> manufacturer = manufacturer;
+}
+
+cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile)
+{
+ _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
+ return Icc ->creator;
}
cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
- return (cmsUInt32Number) Icc ->model;
+ return Icc ->model;
}
void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
- Icc -> model = (cmsUInt32Number) model;
+ Icc -> model = model;
}
-
void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
@@ -1073,7 +1109,6 @@
return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
}
-
static
cmsBool SanityCheck(_cmsICCPROFILE* profile)
{
@@ -1112,11 +1147,13 @@
cmsIOHANDLER* io = Icc ->IOhandler;
cmsTagDescriptor* TagDescriptor;
cmsTagTypeSignature TypeBase;
+ cmsTagTypeSignature Type;
cmsTagTypeHandler* TypeHandler;
+ cmsFloat64Number Version = cmsGetProfileVersion((cmsHPROFILE) Icc);
+ cmsTagTypeHandler LocalTypeHandler;
for (i=0; i < Icc -> TagCount; i++) {
-
if (Icc ->TagNames[i] == 0) continue;
// Linked tags are not written
@@ -1168,7 +1205,16 @@
TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
if (TagDescriptor == NULL) continue; // Unsupported, ignore it
- TypeHandler = Icc ->TagTypeHandlers[i];
+ if (TagDescriptor ->DecideType != NULL) {
+
+ Type = TagDescriptor ->DecideType(Version, Data);
+ }
+ else {
+
+ Type = TagDescriptor ->SupportedTypes[0];
+ }
+
+ TypeHandler = _cmsGetTagTypeHandler(Type);
if (TypeHandler == NULL) {
cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
@@ -1179,9 +1225,10 @@
if (!_cmsWriteTypeBase(io, TypeBase))
return FALSE;
- TypeHandler ->ContextID = Icc ->ContextID;
- TypeHandler ->ICCVersion = Icc ->Version;
- if (!TypeHandler ->WritePtr(TypeHandler, io, Data, TagDescriptor ->ElemCount)) {
+ LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID;
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, io, Data, TagDescriptor ->ElemCount)) {
char String[5];
@@ -1318,8 +1365,8 @@
// Should we just calculate the needed space?
if (MemPtr == NULL) {
- *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL);
- return (*BytesNeeded == 0 ? FALSE : TRUE);
+ *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL);
+ return (*BytesNeeded == 0 ? FALSE : TRUE);
}
// That is a real write operation
@@ -1357,10 +1404,11 @@
cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
if (TypeHandler != NULL) {
+ cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
- TypeHandler ->ContextID = Icc ->ContextID; // As an additional parameters
- TypeHandler ->ICCVersion = Icc ->Version;
- TypeHandler ->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
+ LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameters
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
}
else
_cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
@@ -1404,6 +1452,7 @@
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
cmsIOHANDLER* io = Icc ->IOhandler;
cmsTagTypeHandler* TypeHandler;
+ cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor;
cmsTagTypeSignature BaseType;
cmsUInt32Number Offset, TagSize;
@@ -1427,7 +1476,7 @@
// Seek to its location
if (!io -> Seek(io, Offset))
- return NULL;
+ return NULL;
// Search for support on this tag
TagDescriptor = _cmsGetTagDescriptor(sig);
@@ -1444,14 +1493,15 @@
// Get type handler
TypeHandler = _cmsGetTagTypeHandler(BaseType);
if (TypeHandler == NULL) return NULL;
+ LocalTypeHandler = *TypeHandler;
// Read the tag
Icc -> TagTypeHandlers[n] = TypeHandler;
- TypeHandler ->ContextID = Icc ->ContextID;
- TypeHandler ->ICCVersion = Icc ->Version;
- Icc -> TagPtrs[n] = TypeHandler ->ReadPtr(TypeHandler, io, &ElemCount, TagSize);
+ LocalTypeHandler.ContextID = Icc ->ContextID;
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize);
// The tag type is supported, but something wrong happend and we cannot read the tag.
// let know the user about this (although it is just a warning)
@@ -1472,7 +1522,7 @@
_cmsTagSignature2String(String, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
- String, TagDescriptor ->ElemCount, ElemCount);
+ String, TagDescriptor ->ElemCount, ElemCount);
}
@@ -1504,6 +1554,7 @@
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
cmsTagTypeHandler* TypeHandler = NULL;
+ cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor = NULL;
cmsTagTypeSignature Type;
int i;
@@ -1534,9 +1585,10 @@
if (TypeHandler != NULL) {
- TypeHandler ->ContextID = Icc ->ContextID; // As an additional parameter
- TypeHandler ->ICCVersion = Icc ->Version;
- TypeHandler->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
+ LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
}
}
}
@@ -1575,7 +1627,7 @@
// Let the tag descriptor to decide the type base on depending on
// the data. This is useful for example on parametric curves, where
// curves specified by a table cannot be saved as parametric and needs
- // to be revented to single v2-curves, even on v4 profiles.
+ // to be casted to single v2-curves, even on v4 profiles.
Type = TagDescriptor ->DecideType(Version, data);
}
@@ -1613,9 +1665,10 @@
Icc ->TagSizes[i] = 0;
Icc ->TagOffsets[i] = 0;
- TypeHandler ->ContextID = Icc ->ContextID;
- TypeHandler ->ICCVersion = Icc ->Version;
- Icc ->TagPtrs[i] = TypeHandler ->DupPtr(TypeHandler, data, TagDescriptor ->ElemCount);
+ LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID;
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
if (Icc ->TagPtrs[i] == NULL) {
@@ -1642,6 +1695,7 @@
int i;
cmsIOHANDLER* MemIO;
cmsTagTypeHandler* TypeHandler = NULL;
+ cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor = NULL;
cmsUInt32Number rc;
cmsUInt32Number Offset, TagSize;
@@ -1657,15 +1711,16 @@
Offset = Icc ->TagOffsets[i];
TagSize = Icc ->TagSizes[i];
-
// read the data directly, don't keep copy
if (data != NULL) {
if (BufferSize < TagSize)
- TagSize = BufferSize;
+ TagSize = BufferSize;
if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
+
+ return TagSize;
}
return Icc ->TagSizes[i];
@@ -1679,9 +1734,11 @@
TagSize = Icc ->TagSizes[i];
if (BufferSize < TagSize)
- TagSize = BufferSize;
+ TagSize = BufferSize;
memmove(data, Icc ->TagPtrs[i], TagSize);
+
+ return TagSize;
}
return Icc ->TagSizes[i];
@@ -1697,7 +1754,7 @@
if (data == NULL) {
MemIO = cmsOpenIOhandlerFromNULL(cmsGetProfileContextID(hProfile));
} else{
- MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
+ MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
}
if (MemIO == NULL) return 0;
@@ -1705,20 +1762,22 @@
TypeHandler = Icc ->TagTypeHandlers[i];
TagDescriptor = _cmsGetTagDescriptor(sig);
if (TagDescriptor == NULL) {
- cmsCloseIOhandler(MemIO);
- return 0;
+ cmsCloseIOhandler(MemIO);
+ return 0;
}
+ // FIXME: No handling for TypeHandler == NULL here?
// Serialize
- TypeHandler ->ContextID = Icc ->ContextID;
- TypeHandler ->ICCVersion = Icc ->Version;
+ LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID;
+ LocalTypeHandler.ICCVersion = Icc ->Version;
if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
cmsCloseIOhandler(MemIO);
return 0;
}
- if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
+ if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
cmsCloseIOhandler(MemIO);
return 0;
}
@@ -1756,7 +1815,7 @@
// Using this function you can collapse several tag entries to the same block in the profile
cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest)
{
- _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
+ _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
int i;
if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Wed Apr 16 10:53:10 2014 -0700
@@ -129,7 +129,6 @@
Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag);
if (Tag != NULL) {
-
*Dest = *Tag;
return TRUE;
}
@@ -193,7 +192,8 @@
if (GrayTRC == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 1, 3);
- if (Lut == NULL) return NULL;
+ if (Lut == NULL)
+ goto Error;
if (cmsGetPCS(hProfile) == cmsSigLabData) {
@@ -204,28 +204,35 @@
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
- if (EmptyTab == NULL) {
-
- cmsPipelineFree(Lut);
- return NULL;
- }
+ if (EmptyTab == NULL)
+ goto Error;
LabCurves[0] = GrayTRC;
LabCurves[1] = EmptyTab;
LabCurves[2] = EmptyTab;
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL));
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL)) ||
+ !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves))) {
+ cmsFreeToneCurve(EmptyTab);
+ goto Error;
+ }
cmsFreeToneCurve(EmptyTab);
}
else {
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC));
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL));
+
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC)) ||
+ !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL)))
+ goto Error;
}
return Lut;
+
+Error:
+ cmsFreeToneCurve(GrayTRC);
+ cmsPipelineFree(Lut);
+ return NULL;
}
// RGB Matrix shaper
@@ -259,49 +266,31 @@
Lut = cmsPipelineAlloc(ContextID, 3, 3);
if (Lut != NULL) {
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes));
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)) ||
+ !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL)))
+ goto Error;
// Note that it is certainly possible a single profile would have a LUT based
// tag for output working in lab and a matrix-shaper for the fallback cases.
// This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) {
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID)))
+ goto Error;
}
}
return Lut;
+
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
-/*static
-cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
-{
- cmsContext ContextID = cmsGetProfileContextID(hProfile);
- cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
- cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
-
- if (Lut == NULL) return NULL;
-
- // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
- // and since the formatter has already accomodated to 0..1.0, we should undo this change
- if ( spc == cmsSigLabData)
- {
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
- }
- else
- if (spc == cmsSigXYZData)
- {
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
- }
-
- return Lut;
-}
-*/
static
cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
@@ -316,23 +305,31 @@
// these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0)
if ( spc == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+ goto Error;
}
else if (spc == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+ goto Error;
}
if ( PCS == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+ goto Error;
}
else if( PCS == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+ goto Error;
}
return Lut;
+
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
@@ -359,8 +356,11 @@
return NULL;
}
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE));
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) ||
+ !cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) {
+ cmsPipelineFree(Lut);
+ return NULL;
+ }
return Lut;
}
@@ -395,12 +395,18 @@
return Lut;
// If the input is Lab, add also a conversion at the begin
- if (cmsGetColorSpace(hProfile) == cmsSigLabData)
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+ if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
+ !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+ goto Error;
// Add a matrix for conversion V2 to V4 Lab PCS
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error;
+
return Lut;
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// Lut was not found, try to create a matrix-shaper
@@ -445,21 +451,27 @@
if (cmsGetPCS(hProfile) == cmsSigLabData) {
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL)))
+ goto Error;
}
else {
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL)))
+ goto Error;
}
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC)))
+ goto Error;
+
cmsFreeToneCurve(RevGrayTRC);
-
return Lut;
+
+Error:
+ cmsFreeToneCurve(RevGrayTRC);
+ cmsPipelineFree(Lut);
+ return NULL;
}
-
-
static
cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
{
@@ -506,15 +518,21 @@
// This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) {
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID)))
+ goto Error;
}
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL));
- cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)) ||
+ !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes)))
+ goto Error;
}
cmsFreeToneCurveTriple(InvShapes);
return Lut;
+Error:
+ cmsFreeToneCurveTriple(InvShapes);
+ cmsPipelineFree(Lut);
+ return NULL;
}
@@ -540,30 +558,6 @@
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
-/*static
-cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
-{
- cmsContext ContextID = cmsGetProfileContextID(hProfile);
- cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
- cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
-
- if (Lut == NULL) return NULL;
-
- // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
- // and since the formatter has already accomodated to 0..1.0, we should undo this change
- if ( PCS == cmsSigLabData)
- {
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
- }
- else
- if (PCS == cmsSigXYZData)
- {
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
- }
-
- return Lut;
-}*/
-
static
cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
@@ -578,25 +572,33 @@
// and since the formatter has already accomodated to 0..1.0, we should undo this change
if ( PCS == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+ goto Error;
}
else
if (PCS == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+ goto Error;
}
// the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline
if ( dataSpace == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+ goto Error;
}
- else if ( dataSpace == cmsSigXYZData)
+ else if (dataSpace == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+ goto Error;
}
return Lut;
+
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// Create an output MPE LUT from agiven profile. Version mismatches are handled here
@@ -636,30 +638,35 @@
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
if (cmsGetPCS(hProfile) == cmsSigLabData)
- ChangeInterpolationToTrilinear(Lut);
+ ChangeInterpolationToTrilinear(Lut);
// We need to adjust data only for Lab and Lut16 type
if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
return Lut;
// Add a matrix for conversion V4 to V2 Lab PCS
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+ goto Error;
// If the output is Lab, add also a conversion at the end
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error;
return Lut;
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// Lut not found, try to create a matrix-shaper
// Check if this is a grayscale profile.
- if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
+ if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
- // if so, build appropiate conversion tables.
- // The tables are the PCS iluminant, scaled across GrayTRC
- return BuildGrayOutputPipeline(hProfile);
+ // if so, build appropiate conversion tables.
+ // The tables are the PCS iluminant, scaled across GrayTRC
+ return BuildGrayOutputPipeline(hProfile);
}
// Not gray, create a normal matrix-shaper, which only operates in XYZ space
@@ -681,25 +688,32 @@
if (spc == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+ goto Error;
}
else
if (spc == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+ goto Error;
}
if (PCS == cmsSigLabData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+ goto Error;
}
else
if (PCS == cmsSigXYZData)
{
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+ goto Error;
}
- return Lut;
+ return Lut;
+Error:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
@@ -721,15 +735,21 @@
if (nc == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 0, 0);
- if (Lut == NULL) {
- cmsFreeNamedColorList(nc);
- return NULL;
- }
+ if (Lut == NULL)
+ goto Error;
+
+ if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE)))
+ goto Error;
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE));
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+ if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error;
+
return Lut;
+Error:
+ cmsPipelineFree(Lut);
+ cmsFreeNamedColorList(nc);
+ return NULL;
}
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
@@ -760,10 +780,10 @@
Lut = cmsPipelineDup(Lut);
if (Lut == NULL) return NULL;
- // Now it is time for a controversial stuff. I found that for 3D LUTS using
- // Lab used as indexer space, trilinear interpolation should be used
+ // Now it is time for a controversial stuff. I found that for 3D LUTS using
+ // Lab used as indexer space, trilinear interpolation should be used
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
- ChangeInterpolationToTrilinear(Lut);
+ ChangeInterpolationToTrilinear(Lut);
// After reading it, we have info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
@@ -774,16 +794,20 @@
// Here it is possible to get Lab on both sides
if (cmsGetPCS(hProfile) == cmsSigLabData) {
- cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+ if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+ goto Error2;
}
if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
- cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+ if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+ goto Error2;
}
return Lut;
-
+Error2:
+ cmsPipelineFree(Lut);
+ return NULL;
}
// ---------------------------------------------------------------------------------------------------------------
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Wed Apr 16 10:53:10 2014 -0700
@@ -264,10 +264,10 @@
if (NewElem ->TheCurves != NULL) {
for (i=0; i < NewElem ->nCurves; i++) {
if (NewElem ->TheCurves[i])
- cmsFreeToneCurve(Data ->TheCurves[i]);
+ cmsFreeToneCurve(NewElem ->TheCurves[i]);
}
}
- _cmsFree(mpe ->ContextID, Data ->TheCurves);
+ _cmsFree(mpe ->ContextID, NewElem ->TheCurves);
_cmsFree(mpe ->ContextID, NewElem);
return NULL;
}
@@ -392,6 +392,8 @@
void MatrixElemTypeFree(cmsStage* mpe)
{
_cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
+ if (Data == NULL)
+ return;
if (Data ->Double)
_cmsFree(mpe ->ContextID, Data ->Double);
@@ -526,10 +528,15 @@
if (Data ->Tab.T) {
- if (Data ->HasFloatValues)
+ if (Data ->HasFloatValues) {
NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number));
- else
+ if (NewElem ->Tab.TFloat == NULL)
+ goto Error;
+ } else {
NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
+ if (NewElem ->Tab.TFloat == NULL)
+ goto Error;
+ }
}
NewElem ->Params = _cmsComputeInterpParamsEx(mpe ->ContextID,
@@ -538,8 +545,14 @@
Data ->Params ->nOutputs,
NewElem ->Tab.T,
Data ->Params ->dwFlags);
-
- return (void*) NewElem;
+ if (NewElem->Params != NULL)
+ return (void*) NewElem;
+ Error:
+ if (NewElem->Tab.T)
+ // This works for both types
+ _cmsFree(mpe ->ContextID, NewElem -> Tab.T);
+ _cmsFree(mpe ->ContextID, NewElem);
+ return NULL;
}
@@ -636,7 +649,6 @@
for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
Dimensions[i] = nGridPoints;
-
return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table);
}
@@ -706,15 +718,12 @@
}
}
-
NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT);
if (NewElem ->Params == NULL) {
cmsStageFree(NewMPE);
return NULL;
}
-
-
return NewMPE;
}
@@ -772,7 +781,7 @@
int i, t, nTotalPoints, index, rest;
int nInputs, nOutputs;
cmsUInt32Number* nSamples;
- cmsUInt16Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
+ cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
_cmsStageCLutData* clut;
if (mpe == NULL) return FALSE;
@@ -785,7 +794,9 @@
nInputs = clut->Params ->nInputs;
nOutputs = clut->Params ->nOutputs;
- if (nInputs >= cmsMAXCHANNELS) return FALSE;
+ if (nInputs <= 0) return FALSE;
+ if (nOutputs <= 0) return FALSE;
+ if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
nTotalPoints = CubeSize(nSamples, nInputs);
@@ -832,14 +843,16 @@
int i, t, nTotalPoints, index, rest;
int nInputs, nOutputs;
cmsUInt32Number* nSamples;
- cmsFloat32Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
+ cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
_cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
nSamples = clut->Params ->nSamples;
nInputs = clut->Params ->nInputs;
nOutputs = clut->Params ->nOutputs;
- if (nInputs >= cmsMAXCHANNELS) return FALSE;
+ if (nInputs <= 0) return FALSE;
+ if (nOutputs <= 0) return FALSE;
+ if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
nTotalPoints = CubeSize(nSamples, nInputs);
@@ -1021,8 +1034,7 @@
mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
cmsFreeToneCurveTriple(LabTable);
- if (mpe == NULL) return mpe;
-
+ if (mpe == NULL) return NULL;
mpe ->Implements = cmsSigLabV2toV4;
return mpe;
}
@@ -1248,12 +1260,22 @@
NULL);
if (NewMPE == NULL) return NULL;
- NewMPE ->Implements = mpe ->Implements;
+ NewMPE ->Implements = mpe ->Implements;
+
+ if (mpe ->DupElemPtr) {
+
+ NewMPE ->Data = mpe ->DupElemPtr(mpe);
+
+ if (NewMPE->Data == NULL) {
- if (mpe ->DupElemPtr)
- NewMPE ->Data = mpe ->DupElemPtr(mpe);
- else
+ cmsStageFree(NewMPE);
+ return NULL;
+ }
+
+ } else {
+
NewMPE ->Data = NULL;
+ }
return NewMPE;
}
@@ -1266,7 +1288,7 @@
static
void BlessLUT(cmsPipeline* lut)
{
- // We can set the input/output channels only if we have elements.
+ // We can set the input/ouput channels only if we have elements.
if (lut ->Elements != NULL) {
cmsStage *First, *Last;
@@ -1466,12 +1488,12 @@
}
-void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
+int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
{
cmsStage* Anterior = NULL, *pt;
- _cmsAssert(lut != NULL);
- _cmsAssert(mpe != NULL);
+ if (lut == NULL || mpe == NULL)
+ return FALSE;
switch (loc) {
@@ -1495,9 +1517,11 @@
}
break;
default:;
+ return FALSE;
}
BlessLUT(lut);
+ return TRUE;
}
// Unlink an element and return the pointer to it
@@ -1559,7 +1583,7 @@
// Concatenate two LUT into a new single one
cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
{
- cmsStage* mpe, *NewMPE;
+ cmsStage* mpe;
// If both LUTS does not have elements, we need to inherit
// the number of channels
@@ -1574,17 +1598,12 @@
mpe = mpe ->Next) {
// We have to dup each element
- NewMPE = cmsStageDup(mpe);
-
- if (NewMPE == NULL) {
- return FALSE;
- }
-
- cmsPipelineInsertStage(l1, cmsAT_END, NewMPE);
+ if (!cmsPipelineInsertStage(l1, cmsAT_END, cmsStageDup(mpe)))
+ return FALSE;
}
- BlessLUT(l1);
- return TRUE;
+ BlessLUT(l1);
+ return TRUE;
}
@@ -1714,16 +1733,11 @@
cmsFloat32Number fx[4], x[4], xd[4], fxd[4];
cmsVEC3 tmp, tmp2;
cmsMAT3 Jacobian;
- cmsFloat64Number LastResult[4];
-
// Only 3->3 and 4->3 are supported
if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE;
if (lut ->OutputChannels != 3) return FALSE;
- // Mark result of -1
- LastResult[0] = LastResult[1] = LastResult[2] = -1.0f;
-
// Take the hint as starting point if specified
if (Hint == NULL) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c Wed Apr 16 10:53:10 2014 -0700
@@ -338,7 +338,7 @@
Error:
// Free resources as something went wrong
- if (MD5 != NULL) _cmsFree(ContextID, MD5);
+ // "MD5" cannot be other than NULL here, so no need to free it
if (Mem != NULL) _cmsFree(ContextID, Mem);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
return FALSE;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Wed Apr 16 10:53:10 2014 -0700
@@ -359,9 +359,9 @@
if (Best == -1)
Best = 0;
- v = mlu ->Entries + Best;
+ v = mlu ->Entries + Best;
- if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
+ if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (len != NULL) *len = v ->Len;
@@ -475,6 +475,35 @@
}
+
+// Get the number of translations in the MLU object
+cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
+{
+ if (mlu == NULL) return 0;
+ return mlu->UsedEntries;
+}
+
+// Get the language and country codes for a specific MLU index
+cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
+ cmsUInt32Number idx,
+ char LanguageCode[3],
+ char CountryCode[3])
+{
+ _cmsMLUentry *entry;
+
+ if (mlu == NULL) return FALSE;
+
+ if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
+
+ entry = &mlu->Entries[idx];
+
+ *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
+ *(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country);
+
+ return TRUE;
+}
+
+
// Named color lists --------------------------------------------------------------------------------------------
// Grow the list to keep at least NumElements
@@ -517,9 +546,9 @@
while (v -> Allocated < n)
GrowNamedColorList(v);
- strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix) - 1);
- strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix) - 1);
- v->Prefix[sizeof(v ->Prefix) - 1] = v->Suffix[sizeof(v ->Suffix) - 1] = 0;
+ strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
+ strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
+ v->Prefix[32] = v->Suffix[32] = 0;
v -> ColorantCount = ColorantCount;
@@ -529,8 +558,9 @@
// Free a list
void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v)
{
+ if (v == NULL) return;
if (v ->List) _cmsFree(v ->ContextID, v ->List);
- if (v) _cmsFree(v ->ContextID, v);
+ _cmsFree(v ->ContextID, v);
}
cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
@@ -576,11 +606,8 @@
if (Name != NULL) {
- strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name,
- sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1);
-
- NamedColorList ->List[NamedColorList ->nColors].
- Name[sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1] = 0;
+ strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH-1);
+ NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH-1] = 0;
}
else
@@ -891,7 +918,6 @@
{
_cmsDICT* old_dict = (_cmsDICT*) hDict;
cmsHANDLE hNew;
- _cmsDICT* new_dict;
cmsDICTentry *entry;
_cmsAssert(old_dict != NULL);
@@ -899,8 +925,6 @@
hNew = cmsDictAlloc(old_dict ->ContextID);
if (hNew == NULL) return NULL;
- new_dict = (_cmsDICT*) hNew;
-
// Walk the list freeing all nodes
entry = old_dict ->head;
while (entry != NULL) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c Wed Apr 16 10:53:10 2014 -0700
@@ -27,6 +27,7 @@
// However, the following notice accompanied the original version of this
// file:
//
+
//---------------------------------------------------------------------------------
//
// Little Color Management System
@@ -81,10 +82,6 @@
int nInputs;
int nOutputs;
- // Since there is no limitation of the output number of channels, this buffer holding the connexion CLUT-shaper
- // has to be dynamically allocated. This is not the case of first step shaper-CLUT, which is limited to max inputs
- cmsUInt16Number* StageDEF;
-
_cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance
cmsInterpParams* ParamsCurveIn16[MAX_INPUT_DIMENSIONS];
@@ -202,8 +199,6 @@
{
cmsBool AnyOpt = FALSE, Opt;
- AnyOpt = FALSE;
-
do {
Opt = FALSE;
@@ -253,6 +248,7 @@
{
Prelin16Data* p16 = (Prelin16Data*) D;
cmsUInt16Number StageABC[MAX_INPUT_DIMENSIONS];
+ cmsUInt16Number StageDEF[cmsMAXCHANNELS];
int i;
for (i=0; i < p16 ->nInputs; i++) {
@@ -260,11 +256,11 @@
p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]);
}
- p16 ->EvalCLUT(StageABC, p16 ->StageDEF, p16 ->CLUTparams);
+ p16 ->EvalCLUT(StageABC, StageDEF, p16 ->CLUTparams);
for (i=0; i < p16 ->nOutputs; i++) {
- p16 ->EvalCurveOut16[i](&p16->StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
+ p16 ->EvalCurveOut16[i](&StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
}
}
@@ -274,7 +270,6 @@
{
Prelin16Data* p16 = (Prelin16Data*) ptr;
- _cmsFree(ContextID, p16 ->StageDEF);
_cmsFree(ContextID, p16 ->EvalCurveOut16);
_cmsFree(ContextID, p16 ->ParamsCurveOut16);
@@ -289,7 +284,6 @@
if (Duped == NULL) return NULL;
- Duped ->StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
@@ -328,7 +322,6 @@
p16 ->EvalCLUT = ColorMap ->Interpolation.Lerp16;
- p16 -> StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
@@ -413,7 +406,7 @@
int i, index;
if (CLUT -> Type != cmsSigCLutElemType) {
- cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut MPE");
+ cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut stage");
return FALSE;
}
@@ -579,8 +572,8 @@
static
cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
- cmsPipeline* Src;
- cmsPipeline* Dest;
+ cmsPipeline* Src = NULL;
+ cmsPipeline* Dest = NULL;
cmsStage* mpe;
cmsStage* CLUT;
cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
@@ -593,7 +586,6 @@
cmsToneCurve** DataSetOut;
Prelin16Data* p16;
-
// This is a loosy optimization! does not apply in floating-point cases
if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
@@ -607,10 +599,10 @@
Src = *Lut;
- // Named color pipelines cannot be optimized either
- for (mpe = cmsPipelineGetPtrToFirstStage(Src);
- mpe != NULL;
- mpe = cmsStageNext(mpe)) {
+ // Named color pipelines cannot be optimized either
+ for (mpe = cmsPipelineGetPtrToFirstStage(Src);
+ mpe != NULL;
+ mpe = cmsStageNext(mpe)) {
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
}
@@ -632,7 +624,8 @@
// All seems ok, proceed.
NewPreLin = cmsStageDup(PreLin);
- cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin);
+ if(!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin))
+ goto Error;
// Remove prelinearization. Since we have duplicated the curve
// in destination LUT, the sampling shoud be applied after this stage.
@@ -646,7 +639,9 @@
if (CLUT == NULL) return FALSE;
// Add the CLUT to the destination LUT
- cmsPipelineInsertStage(Dest, cmsAT_END, CLUT);
+ if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
+ goto Error;
+ }
// Postlinearization tables are kept unless indicated by flags
if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {
@@ -662,7 +657,8 @@
// All seems ok, proceed.
NewPostLin = cmsStageDup(PostLin);
- cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin);
+ if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin))
+ goto Error;
// In destination LUT, the sampling shoud be applied after this stage.
cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
@@ -673,10 +669,18 @@
// Now its time to do the sampling. We have to ignore pre/post linearization
// The source LUT whithout pre/post curves is passed as parameter.
if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
-
+Error:
// Ops, something went wrong, Restore stages
- if (KeepPreLin != NULL) cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin);
- if (KeepPostLin != NULL) cmsPipelineInsertStage(Src, cmsAT_END, KeepPostLin);
+ if (KeepPreLin != NULL) {
+ if (!cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin)) {
+ _cmsAssert(0); // This never happens
+ }
+ }
+ if (KeepPostLin != NULL) {
+ if (!cmsPipelineInsertStage(Src, cmsAT_END, KeepPostLin)) {
+ _cmsAssert(0); // This never happens
+ }
+ }
cmsPipelineFree(Dest);
return FALSE;
}
@@ -703,12 +707,11 @@
else {
p16 = PrelinOpt16alloc(Dest ->ContextID,
- DataCLUT ->Params,
- Dest ->InputChannels,
- DataSetIn,
- Dest ->OutputChannels,
- DataSetOut);
-
+ DataCLUT ->Params,
+ Dest ->InputChannels,
+ DataSetIn,
+ Dest ->OutputChannels,
+ DataSetOut);
_cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
}
@@ -1062,7 +1065,8 @@
LutPlusCurves = cmsPipelineDup(OriginalLut);
if (LutPlusCurves == NULL) goto Error;
- cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse));
+ if (!cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse)))
+ goto Error;
// Create the result LUT
OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
@@ -1071,13 +1075,15 @@
OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);
// Create and insert the curves at the beginning
- cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe);
+ if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe))
+ goto Error;
// Allocate the CLUT for result
OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);
// Add the CLUT to the destination LUT
- cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe);
+ if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe))
+ goto Error;
// Resample the LUT
if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;
@@ -1205,13 +1211,14 @@
for (i=0; i < nCurves; i++) {
c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
+
if (c16->Curves[i] == NULL) {
+
for (j=0; j < i; j++) {
_cmsFree(ContextID, c16->Curves[j]);
}
_cmsFree(ContextID, c16->Curves);
_cmsFree(ContextID, c16);
-
return NULL;
}
@@ -1340,7 +1347,8 @@
// Maybe the curves are linear at the end
if (!AllCurvesAreLinear(ObtainedCurves)) {
- cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves);
+ if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves))
+ goto Error;
// If the curves are to be applied in 8 bits, we can save memory
if (_cmsFormatterIs8bit(*InputFormat)) {
@@ -1348,6 +1356,7 @@
_cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data;
Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves);
+ if (c16 == NULL) goto Error;
*dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup);
@@ -1357,6 +1366,7 @@
_cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves);
Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves);
+ if (c16 == NULL) goto Error;
*dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup);
}
@@ -1366,7 +1376,8 @@
// LUT optimizes to nothing. Set the identity LUT
cmsStageFree(ObtainedCurves);
- cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels));
+ if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
+ goto Error;
*dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL);
@@ -1596,10 +1607,14 @@
if (!Dest) return FALSE;
// Assamble the new LUT
- cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1));
+ if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
+ goto Error;
+
if (!IdentityMat)
- cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset));
- cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2));
+ if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)))
+ goto Error;
+ if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
+ goto Error;
// If identity on matrix, we can further optimize the curves, so call the join curves routine
if (IdentityMat) {
@@ -1621,6 +1636,10 @@
cmsPipelineFree(Src);
*Lut = Dest;
return TRUE;
+Error:
+ // Leave Src unchanged
+ cmsPipelineFree(Dest);
+ return FALSE;
}
@@ -1650,7 +1669,7 @@
static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
// Register new ways to optimize
-cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
_cmsOptimizationCollection* fl;
@@ -1664,7 +1683,7 @@
// Optimizer callback is required
if (Plugin ->OptimizePtr == NULL) return FALSE;
- fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(sizeof(_cmsOptimizationCollection));
+ fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Wed Apr 16 10:53:10 2014 -0700
@@ -317,6 +317,23 @@
}
static
+cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(register _cmsTRANSFORM* info,
+ register cmsUInt16Number wIn[],
+ register cmsUInt8Number* accum,
+ register cmsUInt32Number Stride)
+{
+ wIn[2] = FROM_8_TO_16(*accum); accum++; // B
+ wIn[1] = FROM_8_TO_16(*accum); accum++; // G
+ wIn[0] = FROM_8_TO_16(*accum); accum++; // R
+ accum++; // A
+
+ return accum;
+
+ cmsUNUSED_PARAMETER(info);
+ cmsUNUSED_PARAMETER(Stride);
+}
+
+static
cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info,
register cmsUInt16Number wIn[],
register cmsUInt8Number* accum,
@@ -2901,6 +2918,9 @@
{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap},
{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst},
+ { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
+ ANYSPACE, Unroll3BytesSkip1SwapSwapFirst},
+
{ CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes},
{ CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse},
{ CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst},
@@ -3166,7 +3186,7 @@
// Formatters management
-cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
cmsFormattersFactoryList* fl ;
@@ -3178,7 +3198,7 @@
return TRUE;
}
- fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(sizeof(cmsFormattersFactoryList));
+ fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList));
if (fl == NULL) return FALSE;
fl ->Factory = Plugin ->FormattersFactory;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Wed Apr 16 10:53:10 2014 -0700
@@ -898,9 +898,11 @@
{
switch (ColorSpace) {
+ case cmsSigMCH1Data:
case cmsSig1colorData:
case cmsSigGrayData: return 1;
+ case cmsSigMCH2Data:
case cmsSig2colorData: return 2;
case cmsSigXYZData:
@@ -912,10 +914,12 @@
case cmsSigHsvData:
case cmsSigHlsData:
case cmsSigCmyData:
+ case cmsSigMCH3Data:
case cmsSig3colorData: return 3;
case cmsSigLuvKData:
case cmsSigCmykData:
+ case cmsSigMCH4Data:
case cmsSig4colorData: return 4;
case cmsSigMCH5Data:
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c Wed Apr 16 10:53:10 2014 -0700
@@ -125,10 +125,14 @@
pOut[0] = pIn[7];
#else
-
_cmsAssert(Result != NULL);
+# ifdef CMS_DONT_USE_INT64
+ (*Result)[0] = QWord[0];
+ (*Result)[1] = QWord[1];
+# else
*Result = *QWord;
+# endif
#endif
}
@@ -543,10 +547,10 @@
static _cmsSubAllocator* PluginPool = NULL;
// Specialized malloc for plug-ins, that is freed upon exit.
-void* _cmsPluginMalloc(cmsUInt32Number size)
+void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size)
{
if (PluginPool == NULL)
- PluginPool = _cmsCreateSubAlloc(0, 4*1024);
+ PluginPool = _cmsCreateSubAlloc(id, 4*1024);
return _cmsSubAlloc(PluginPool, size);
}
@@ -555,6 +559,11 @@
// Main plug-in dispatcher
cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
{
+ return cmsPluginTHR(NULL, Plug_in);
+}
+
+cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
+{
cmsPluginBase* Plugin;
for (Plugin = (cmsPluginBase*) Plug_in;
@@ -583,35 +592,35 @@
break;
case cmsPluginTagTypeSig:
- if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTagSig:
- if (!_cmsRegisterTagPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginFormattersSig:
- if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginRenderingIntentSig:
- if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginParametricCurveSig:
- if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginMultiProcessElementSig:
- if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginOptimizationSig:
- if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTransformSig:
- if (!_cmsRegisterTransformPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
break;
default:
@@ -630,14 +639,14 @@
{
_cmsRegisterMemHandlerPlugin(NULL);
_cmsRegisterInterpPlugin(NULL);
- _cmsRegisterTagTypePlugin(NULL);
- _cmsRegisterTagPlugin(NULL);
- _cmsRegisterFormattersPlugin(NULL);
- _cmsRegisterRenderingIntentPlugin(NULL);
- _cmsRegisterParametricCurvesPlugin(NULL);
- _cmsRegisterMultiProcessElementPlugin(NULL);
- _cmsRegisterOptimizationPlugin(NULL);
- _cmsRegisterTransformPlugin(NULL);
+ _cmsRegisterTagTypePlugin(NULL, NULL);
+ _cmsRegisterTagPlugin(NULL, NULL);
+ _cmsRegisterFormattersPlugin(NULL, NULL);
+ _cmsRegisterRenderingIntentPlugin(NULL, NULL);
+ _cmsRegisterParametricCurvesPlugin(NULL, NULL);
+ _cmsRegisterMultiProcessElementPlugin(NULL, NULL);
+ _cmsRegisterOptimizationPlugin(NULL, NULL);
+ _cmsRegisterTransformPlugin(NULL, NULL);
if (PluginPool != NULL)
_cmsSubAllocDestroy(PluginPool);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Wed Apr 16 10:53:10 2014 -0700
@@ -806,7 +806,6 @@
mpe = Pipeline ->Elements;
-
switch (cmsStageInputChannels(mpe)) {
case 3:
@@ -838,8 +837,6 @@
mpe = mpe ->Next;
}
-
-
if (cmsStageType(mpe) == cmsSigCLutElemType) {
_cmsIOPrintf(m, "/Table ");
@@ -854,7 +851,6 @@
_cmsIOPrintf(m, " >>\n");
_cmsIOPrintf(m, "]\n");
-
return 1;
}
@@ -950,6 +946,7 @@
rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
cmsPipelineFree(DeviceLink);
+ if (rc == 0) return 0;
}
break;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Wed Apr 16 10:53:10 2014 -0700
@@ -56,6 +56,8 @@
#include "lcms2_internal.h"
+#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
+#define cmsmax(a, b) (((a) > (b)) ? (a) : (b))
// This file contains routines for resampling and LUT optimization, black point detection
// and black preservation.
@@ -67,13 +69,13 @@
static
cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent)
{
- cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
+ cmsContext ContextID = cmsGetProfileContextID(hProfile);
+ cmsHPROFILE hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
cmsHTRANSFORM xform;
cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE };
cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 };
cmsHPROFILE hProfiles[4];
cmsUInt32Number Intents[4];
- cmsContext ContextID = cmsGetProfileContextID(hProfile);
hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab;
Intents[0] = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC;
@@ -141,8 +143,8 @@
cmsCloseProfile(hLab);
if (xform == NULL) {
+
// Something went wrong. Get rid of open resources and return zero as black
-
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
@@ -173,7 +175,6 @@
// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
static
cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile)
-
{
cmsHTRANSFORM hRoundTrip;
cmsCIELab LabIn, LabOut;
@@ -218,17 +219,27 @@
// involves to turn BP to neutral and to use only L component.
cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
{
+ cmsProfileClassSignature devClass;
- // Zero for black point
- if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) {
+ // Make sure the device class is adequate
+ devClass = cmsGetDeviceClass(hProfile);
+ if (devClass == cmsSigLinkClass ||
+ devClass == cmsSigAbstractClass ||
+ devClass == cmsSigNamedColorClass) {
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
+ }
- BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
- return FALSE;
+ // Make sure intent is adequate
+ if (Intent != INTENT_PERCEPTUAL &&
+ Intent != INTENT_RELATIVE_COLORIMETRIC &&
+ Intent != INTENT_SATURATION) {
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
}
// v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it. Black point tag is deprecated in V4.
-
if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
(Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
@@ -303,7 +314,7 @@
{
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
double sum_y = 0, sum_yx = 0, sum_yx2 = 0;
- double disc;
+ double d, a, b, c;
int i;
cmsMAT3 m;
cmsVEC3 v, res;
@@ -333,14 +344,32 @@
if (!_cmsMAT3solve(&res, &m, &v)) return 0;
- // y = t x2 + u x + c
- // x = ( - u + Sqrt( u^2 - 4 t c ) ) / ( 2 t )
- disc = res.n[1]*res.n[1] - 4.0 * res.n[0] * res.n[2];
- if (disc < 0) return -1;
+
+ a = res.n[2];
+ b = res.n[1];
+ c = res.n[0];
+
+ if (fabs(a) < 1.0E-10) {
+
+ return cmsmin(0, cmsmax(50, -c/b ));
+ }
+ else {
- return ( -1.0 * res.n[1] + sqrt( disc )) / (2.0 * res.n[0]);
+ d = b*b - 4.0 * a * c;
+ if (d <= 0) {
+ return 0;
+ }
+ else {
+
+ double rt = (-b + sqrt(d)) / (2.0 * a);
+
+ return cmsmax(0, cmsmin(50, rt));
+ }
+ }
+
}
+/*
static
cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
{
@@ -361,6 +390,7 @@
return TRUE;
}
+*/
// Calculates the black point of a destination profile.
// This algorithm comes from the Adobe paper disclosing its black point compensation method.
@@ -369,21 +399,30 @@
cmsColorSpaceSignature ColorSpace;
cmsHTRANSFORM hRoundTrip = NULL;
cmsCIELab InitialLab, destLab, Lab;
-
+ cmsFloat64Number inRamp[256], outRamp[256];
cmsFloat64Number MinL, MaxL;
- cmsBool NearlyStraightMidRange = FALSE;
- cmsFloat64Number L;
- cmsFloat64Number x[101], y[101];
- cmsFloat64Number lo, hi, NonMonoMin;
- int n, l, i, NonMonoIndx;
+ cmsBool NearlyStraightMidrange = TRUE;
+ cmsFloat64Number yRamp[256];
+ cmsFloat64Number x[256], y[256];
+ cmsFloat64Number lo, hi;
+ int n, l;
+ cmsProfileClassSignature devClass;
+ // Make sure the device class is adequate
+ devClass = cmsGetDeviceClass(hProfile);
+ if (devClass == cmsSigLinkClass ||
+ devClass == cmsSigAbstractClass ||
+ devClass == cmsSigNamedColorClass) {
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
+ }
// Make sure intent is adequate
if (Intent != INTENT_PERCEPTUAL &&
Intent != INTENT_RELATIVE_COLORIMETRIC &&
Intent != INTENT_SATURATION) {
- BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
- return FALSE;
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
}
@@ -415,10 +454,8 @@
return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
}
- // It is one of the valid cases!, presto chargo hocus pocus, go for the Adobe magic
+ // It is one of the valid cases!, use Adobe algorithm
- // Step 1
- // ======
// Set a first guess, that should work on good profiles.
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
@@ -449,71 +486,68 @@
hRoundTrip = CreateRoundtripXForm(hProfile, Intent);
if (hRoundTrip == NULL) return FALSE;
- // Calculate Min L*
- Lab = InitialLab;
- Lab.L = 0;
- cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
- MinL = destLab.L;
+ // Compute ramps
- // Calculate Max L*
- Lab = InitialLab;
- Lab.L = 100;
- cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
- MaxL = destLab.L;
+ for (l=0; l < 256; l++) {
- // Step 3
- // ======
-
- // check if quadratic estimation needs to be done.
- if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
+ Lab.L = (cmsFloat64Number) (l * 100.0) / 255.0;
+ Lab.a = cmsmin(50, cmsmax(-50, InitialLab.a));
+ Lab.b = cmsmin(50, cmsmax(-50, InitialLab.b));
- // Conceptually, this code tests how close the source l and converted L are to one another in the mid-range
- // of the values. If the converted ramp of L values is close enough to a straight line y=x, then InitialLab
- // is good enough to be the DestinationBlackPoint,
- NearlyStraightMidRange = TRUE;
-
- for (l=0; l <= 100; l++) {
+ cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
- Lab.L = l;
- Lab.a = InitialLab.a;
- Lab.b = InitialLab.b;
-
- cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-
- L = destLab.L;
-
- // Check the mid range in 20% after MinL
- if (L > (MinL + 0.2 * (MaxL - MinL))) {
+ inRamp[l] = Lab.L;
+ outRamp[l] = destLab.L;
+ }
- // Is close enough?
- if (fabs(L - l) > 4.0) {
+ // Make monotonic
+ for (l = 254; l > 0; --l) {
+ outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
+ }
- // Too far away, profile is buggy!
- NearlyStraightMidRange = FALSE;
- break;
- }
- }
- }
- }
- else {
- // Check is always performed for perceptual and saturation intents
- NearlyStraightMidRange = FALSE;
+ // Check
+ if (! (outRamp[0] < outRamp[255])) {
+
+ cmsDeleteTransform(hRoundTrip);
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
}
- // If no furter checking is needed, we are done
- if (NearlyStraightMidRange) {
+ // Test for mid range straight (only on relative colorimetric)
+
+ NearlyStraightMidrange = TRUE;
+ MinL = outRamp[0]; MaxL = outRamp[255];
+ if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
+
+ for (l=0; l < 256; l++) {
- cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
- cmsDeleteTransform(hRoundTrip);
- return TRUE;
+ if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
+ (fabs(inRamp[l] - outRamp[l]) < 4.0 )))
+ NearlyStraightMidrange = FALSE;
+ }
+
+ // If the mid range is straight (as determined above) then the
+ // DestinationBlackPoint shall be the same as initialLab.
+ // Otherwise, the DestinationBlackPoint shall be determined
+ // using curve fitting.
+
+ if (NearlyStraightMidrange) {
+
+ cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
+ cmsDeleteTransform(hRoundTrip);
+ return TRUE;
+ }
}
- // The round-trip curve normally looks like a nearly constant section at the black point,
+
+ // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
// with a corner and a nearly straight line to the white point.
- // STEP 4
- // =======
+ for (l=0; l < 256; l++) {
+
+ yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
+ }
// find the black point using the least squares error quadratic curve fitting
@@ -528,62 +562,32 @@
hi = 0.25;
}
- // Capture points for the fitting.
+ // Capture shadow points for the fitting.
n = 0;
- for (l=0; l <= 100; l++) {
-
- cmsFloat64Number ff;
+ for (l=0; l < 256; l++) {
- Lab.L = (cmsFloat64Number) l;
- Lab.a = InitialLab.a;
- Lab.b = InitialLab.b;
-
- cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-
- ff = (destLab.L - MinL)/(MaxL - MinL);
+ cmsFloat64Number ff = yRamp[l];
if (ff >= lo && ff < hi) {
-
- x[n] = Lab.L;
- y[n] = ff;
+ x[n] = inRamp[l];
+ y[n] = yRamp[l];
n++;
}
-
- }
-
- // This part is not on the Adobe paper, but I found is necessary for getting any result.
-
- if (IsMonotonic(n, y)) {
-
- // Monotonic means lower point is stil valid
- cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
- cmsDeleteTransform(hRoundTrip);
- return TRUE;
- }
-
- // No suitable points, regret and use safer algorithm
- if (n == 0) {
- cmsDeleteTransform(hRoundTrip);
- return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
}
- NonMonoMin = 100;
- NonMonoIndx = 0;
- for (i=0; i < n; i++) {
-
- if (y[i] < NonMonoMin) {
- NonMonoIndx = i;
- NonMonoMin = y[i];
- }
+ // No suitable points
+ if (n < 3 ) {
+ cmsDeleteTransform(hRoundTrip);
+ BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+ return FALSE;
}
- Lab.L = x[NonMonoIndx];
// fit and get the vertex of quadratic curve
Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y);
- if (Lab.L < 0.0 || Lab.L > 50.0) { // clip to zero L* if the vertex is negative
+ if (Lab.L < 0.0) { // clip to zero L* if the vertex is negative
Lab.L = 0;
}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c Wed Apr 16 10:53:10 2014 -0700
@@ -91,7 +91,7 @@
// Register a new type handler. This routine is shared between normal types and MPE
static
-cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
+cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
{
cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
_cmsTagTypeLinkedList *pt, *Anterior = NULL;
@@ -118,7 +118,7 @@
}
// Registering happens in plug-in memory pool
- pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagTypeLinkedList));
+ pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
if (pt == NULL) return FALSE;
pt ->Handler = Plugin ->Handler;
@@ -208,10 +208,10 @@
cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
// Let's take the offsets to each element
- ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+ ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error;
- ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+ ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error;
for (i=0; i < Count; i++) {
@@ -257,10 +257,10 @@
cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
// Create table
- ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+ ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error;
- ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+ ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error;
// Keep starting position of curve offsets
@@ -456,6 +456,7 @@
void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
+
cmsUNUSED_PARAMETER(n);
}
@@ -1106,8 +1107,6 @@
{
cmsUInt32Number Count;
cmsToneCurve* NewGamma;
- cmsUInt16Number Linear[2] = { 0, 0xffff };
-
*nItems = 0;
if (!_cmsReadUInt32Number(io, &Count)) return NULL;
@@ -1115,11 +1114,14 @@
switch (Count) {
case 0: // Linear.
-
- NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, 2, Linear);
- if (!NewGamma) return NULL;
- *nItems = 1;
- return NewGamma;
+ {
+ cmsFloat64Number SingleGamma = 1.0;
+
+ NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
+ if (!NewGamma) return NULL;
+ *nItems = 1;
+ return NewGamma;
+ }
case 1: // Specified as the exponent of gamma function
{
@@ -1210,6 +1212,7 @@
if (ICCVersion < 4.0) return cmsSigCurveType;
if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric
if (Curve ->Segments[0].Type < 0) return cmsSigCurveType; // Only non-inverted curves
+ if (Curve ->Segments[0].Type > 5) return cmsSigCurveType; // Only ICC parametric curves
return cmsSigParametricCurveType;
}
@@ -1386,6 +1389,9 @@
{
cmsICCMeasurementConditions mc;
+
+ memset(&mc, 0, sizeof(mc));
+
if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
if (!_cmsReadXYZNumber(io, &mc.Backing)) return NULL;
if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
@@ -1640,7 +1646,6 @@
static
cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
{
- cmsStage* mpe;
cmsUInt8Number* Temp = NULL;
int i, j;
cmsToneCurve* Tables[cmsMAXCHANNELS];
@@ -1669,11 +1674,8 @@
_cmsFree(ContextID, Temp);
Temp = NULL;
-
- mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
- if (mpe == NULL) goto Error;
-
- cmsPipelineInsertStage(lut, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
+ goto Error;
for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]);
@@ -1701,21 +1703,30 @@
if (Tables) {
- if (Tables ->TheCurves[i]->nEntries != 256) {
- cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
- return FALSE;
+ // Usual case of identity curves
+ if ((Tables ->TheCurves[i]->nEntries == 2) &&
+ (Tables->TheCurves[i]->Table16[0] == 0) &&
+ (Tables->TheCurves[i]->Table16[1] == 65535)) {
+
+ for (j=0; j < 256; j++) {
+ if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE;
+ }
}
-
- }
-
- for (j=0; j < 256; j++) {
-
- if (Tables != NULL)
- val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
else
- val = (cmsUInt8Number) j;
-
- if (!_cmsWriteUInt8Number(io, val)) return FALSE;
+ if (Tables ->TheCurves[i]->nEntries != 256) {
+ cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
+ return FALSE;
+ }
+ else
+ for (j=0; j < 256; j++) {
+
+ if (Tables != NULL)
+ val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
+ else
+ val = (cmsUInt8Number) j;
+
+ if (!_cmsWriteUInt8Number(io, val)) return FALSE;
+ }
}
}
return TRUE;
@@ -1724,7 +1735,7 @@
// Check overflow
static
-size_t uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
+cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
{
cmsUInt32Number rv = 1, rc;
@@ -1736,13 +1747,13 @@
rv *= a;
// Check for overflow
- if (rv > UINT_MAX / a) return (size_t) -1;
+ if (rv > UINT_MAX / a) return (cmsUInt32Number) -1;
}
rc = rv * n;
- if (rv != rc / n) return (size_t) -1;
+ if (rv != rc / n) return (cmsUInt32Number) -1;
return rc;
}
@@ -1757,7 +1768,6 @@
cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
cmsUInt8Number* Temp = NULL;
cmsPipeline* NewLUT = NULL;
- cmsStage *mpemat, *mpeclut;
cmsUInt32Number nTabSize, i;
cmsFloat64Number Matrix[3*3];
@@ -1796,9 +1806,8 @@
// Only operates if not identity...
if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
- mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
- if (mpemat == NULL) goto Error;
- cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, mpemat);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
+ goto Error;
}
// Get input tables
@@ -1806,13 +1815,10 @@
// Get 3D CLUT. Check the overflow....
nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
- if (nTabSize == (size_t) -1) goto Error;
+ if (nTabSize == (cmsUInt32Number) -1) goto Error;
if (nTabSize > 0) {
cmsUInt16Number *PtrW, *T;
- cmsUInt32Number Tsize;
-
- Tsize = (cmsUInt32Number) nTabSize * sizeof(cmsUInt16Number);
PtrW = T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
if (T == NULL) goto Error;
@@ -1829,10 +1835,8 @@
_cmsFree(self ->ContextID, Temp);
Temp = NULL;
-
- mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
- if (mpeclut == NULL) goto Error;
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
+ goto Error;
_cmsFree(self ->ContextID, T);
}
@@ -1934,7 +1938,7 @@
if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
- if (nTabSize == (size_t) -1) return FALSE;
+ if (nTabSize == (cmsUInt32Number) -1) return FALSE;
if (nTabSize > 0) {
// The 3D CLUT.
@@ -1983,7 +1987,6 @@
static
cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
{
- cmsStage* mpe;
int i;
cmsToneCurve* Tables[cmsMAXCHANNELS];
@@ -2007,10 +2010,8 @@
// Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
- mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
- if (mpe == NULL) goto Error;
-
- cmsPipelineInsertStage(lut, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
+ goto Error;
for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]);
@@ -2031,7 +2032,9 @@
int j;
cmsUInt32Number i;
cmsUInt16Number val;
- int nEntries = 256;
+ int nEntries;
+
+ _cmsAssert(Tables != NULL);
nEntries = Tables->TheCurves[0]->nEntries;
@@ -2039,11 +2042,7 @@
for (j=0; j < nEntries; j++) {
- if (Tables != NULL)
- val = Tables->TheCurves[i]->Table16[j];
- else
- val = _cmsQuantizeVal(j, nEntries);
-
+ val = Tables->TheCurves[i]->Table16[j];
if (!_cmsWriteUInt16Number(io, val)) return FALSE;
}
}
@@ -2057,7 +2056,6 @@
{
cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
cmsPipeline* NewLUT = NULL;
- cmsStage *mpemat, *mpeclut;
cmsUInt32Number nTabSize;
cmsFloat64Number Matrix[3*3];
cmsUInt16Number InputEntries, OutputEntries;
@@ -2094,9 +2092,8 @@
// Only operates on 3 channels
if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
- mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
- if (mpemat == NULL) goto Error;
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpemat);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
+ goto Error;
}
if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error;
@@ -2110,7 +2107,7 @@
// Get 3D CLUT
nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
- if (nTabSize == (size_t) -1) goto Error;
+ if (nTabSize == (cmsUInt32Number) -1) goto Error;
if (nTabSize > 0) {
cmsUInt16Number *T;
@@ -2123,13 +2120,10 @@
goto Error;
}
- mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
- if (mpeclut == NULL) {
- _cmsFree(self ->ContextID, T);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
+ _cmsFree(self ->ContextID, T);
goto Error;
}
-
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
_cmsFree(self ->ContextID, T);
}
@@ -2159,7 +2153,7 @@
_cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
_cmsStageMatrixData* MatMPE = NULL;
_cmsStageCLutData* clut = NULL;
- int InputChannels, OutputChannels, clutPoints;
+ int i, InputChannels, OutputChannels, clutPoints;
// Disassemble the LUT into components.
mpe = NewLUT -> Elements;
@@ -2234,13 +2228,13 @@
if (PreMPE != NULL) {
if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
} else {
- if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+ if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
}
if (PostMPE != NULL) {
if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
} else {
- if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+ if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
}
@@ -2249,9 +2243,16 @@
if (PreMPE != NULL) {
if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
}
+ else {
+ for (i=0; i < InputChannels; i++) {
+
+ if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+ if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
+ }
+ }
nTabSize = uipow(OutputChannels, clutPoints, InputChannels);
- if (nTabSize == (size_t) -1) return FALSE;
+ if (nTabSize == (cmsUInt32Number) -1) return FALSE;
if (nTabSize > 0) {
// The 3D CLUT.
if (clut != NULL) {
@@ -2263,7 +2264,13 @@
if (PostMPE != NULL) {
if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
}
-
+ else {
+ for (i=0; i < OutputChannels; i++) {
+
+ if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+ if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
+ }
+ }
return TRUE;
@@ -2479,7 +2486,6 @@
cmsUInt32Number offsetM; // Offset to first "M" curve
cmsUInt32Number offsetC; // Offset to CLUT
cmsUInt32Number offsetA; // Offset to first "A" curve
- cmsStage* mpe;
cmsPipeline* NewLUT = NULL;
@@ -2501,37 +2507,35 @@
if (NewLUT == NULL) return NULL;
if (offsetA!= 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan)))
+ goto Error;
}
if (offsetC != 0) {
- mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
+ goto Error;
}
if (offsetM != 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
+ goto Error;
}
if (offsetMat != 0) {
- mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
+ goto Error;
}
if (offsetB != 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
+ goto Error;
}
*nItems = 1;
return NewLUT;
+Error:
+ cmsPipelineFree(NewLUT);
+ return NULL;
cmsUNUSED_PARAMETER(SizeOfTag);
}
@@ -2798,7 +2802,6 @@
cmsUInt32Number offsetM; // Offset to first "M" curve
cmsUInt32Number offsetC; // Offset to CLUT
cmsUInt32Number offsetA; // Offset to first "A" curve
- cmsStage* mpe;
cmsPipeline* NewLUT = NULL;
@@ -2821,37 +2824,35 @@
if (NewLUT == NULL) return NULL;
if (offsetB != 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan)))
+ goto Error;
}
if (offsetMat != 0) {
- mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
+ goto Error;
}
if (offsetM != 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
+ goto Error;
}
if (offsetC != 0) {
- mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
+ goto Error;
}
if (offsetA!= 0) {
- mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan);
- if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
+ goto Error;
}
*nItems = 1;
return NewLUT;
+Error:
+ cmsPipelineFree(NewLUT);
+ return NULL;
cmsUNUSED_PARAMETER(SizeOfTag);
}
@@ -3287,7 +3288,7 @@
SizeOfTag -= sizeof(cmsUInt32Number);
if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error;
- if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
+ if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error;
SizeOfTag -= sizeof(cmsUInt64Number);
if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error;
@@ -4292,6 +4293,9 @@
if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
+ if (InputChans == 0) goto Error;
+ if (OutputChans == 0) goto Error;
+
if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
goto Error;
@@ -4381,7 +4385,6 @@
{
cmsStageSignature ElementSig;
cmsTagTypeHandler* TypeHandler;
- cmsStage *mpe = NULL;
cmsUInt32Number nItems;
cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
@@ -4409,11 +4412,8 @@
if (TypeHandler ->ReadPtr != NULL) {
// This is a real element which should be read and processed
- mpe = (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag);
- if (mpe == NULL) return FALSE;
-
- // All seems ok, insert element
- cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+ if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
+ return FALSE;
}
return TRUE;
@@ -4479,10 +4479,10 @@
outputChan = cmsPipelineOutputChannels(Lut);
ElemCount = cmsPipelineStageCount(Lut);
- ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
+ ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error;
- ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
+ ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error;
// Write the head
@@ -4825,10 +4825,10 @@
static
cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count)
{
- e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+ e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
if (e->Offsets == NULL) return FALSE;
- e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+ e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
if (e->Sizes == NULL) {
_cmsFree(ContextID, e -> Offsets);
@@ -4844,7 +4844,7 @@
void FreeElem(_cmsDICelem* e)
{
if (e ->Offsets != NULL) _cmsFree(e -> ContextID, e -> Offsets);
- if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e ->Sizes);
+ if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e -> Sizes);
e->Offsets = e ->Sizes = NULL;
}
@@ -5084,7 +5084,7 @@
if (!_cmsReadUInt32Number(io, &Count)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
- // Get rec lenghth
+ // Get rec length
if (!_cmsReadUInt32Number(io, &Length)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
@@ -5118,14 +5118,22 @@
if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
}
+ if (NameWCS == NULL || ValueWCS == NULL) {
+
+ cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value");
+ rc = FALSE;
+ }
+ else {
+
rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
+ }
if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);
- if (!rc) return FALSE;
+ if (!rc) goto Error;
}
FreeArray(&a);
@@ -5277,14 +5285,14 @@
#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
// Both kind of plug-ins share same structure
-cmsBool _cmsRegisterTagTypePlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
}
-cmsBool _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
}
@@ -5391,7 +5399,9 @@
{ cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]},
{ cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]},
{ cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]},
- { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL}, NULL}
+ { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]},
+ { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}
+
};
@@ -5406,7 +5416,7 @@
#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
-cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginTag* Plugin = (cmsPluginTag*) Data;
_cmsTagLinkedList *pt, *Anterior;
@@ -5430,7 +5440,7 @@
pt = pt ->Next;
}
- pt = (_cmsTagLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagLinkedList));
+ pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
if (pt == NULL) return FALSE;
pt ->Signature = Plugin ->Signature;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Wed Apr 16 10:53:10 2014 -0700
@@ -208,9 +208,26 @@
if (TransferFunction) {
+ // Tries to minimize space. Thanks to Richard Hughes for this nice idea
if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error;
- if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
- if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
+
+ if (TransferFunction[1] == TransferFunction[0]) {
+
+ if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;
+
+ } else {
+
+ if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
+ }
+
+ if (TransferFunction[2] == TransferFunction[0]) {
+
+ if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;
+
+ } else {
+
+ if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
+ }
}
if (Primaries) {
@@ -303,7 +320,6 @@
{
cmsHPROFILE hICC;
cmsPipeline* Pipeline;
- cmsStage* Lin;
int nChannels;
hICC = cmsCreateProfilePlaceholder(ContextID);
@@ -327,10 +343,8 @@
// Copy tables to Pipeline
- Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions);
- if (Lin == NULL) goto Error;
-
- cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);
+ if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions)))
+ goto Error;
// Create tags
if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
@@ -344,6 +358,7 @@
return hICC;
Error:
+ cmsPipelineFree(Pipeline);
if (hICC)
cmsCloseProfile(hICC);
@@ -451,9 +466,10 @@
if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels));
- cmsPipelineInsertStage(LUT, cmsAT_END, CLUT);
- cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) ||
+ !cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) ||
+ !cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)))
+ goto Error;
// Create tags
if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;
@@ -504,7 +520,8 @@
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)))
+ goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -550,7 +567,8 @@
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
+ goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -595,7 +613,8 @@
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
+ goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -734,81 +753,83 @@
// contrast, Saturation and white point displacement
cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
- int nLUTPoints,
- cmsFloat64Number Bright,
- cmsFloat64Number Contrast,
- cmsFloat64Number Hue,
- cmsFloat64Number Saturation,
- int TempSrc,
- int TempDest)
+ int nLUTPoints,
+ cmsFloat64Number Bright,
+ cmsFloat64Number Contrast,
+ cmsFloat64Number Hue,
+ cmsFloat64Number Saturation,
+ int TempSrc,
+ int TempDest)
{
- cmsHPROFILE hICC;
- cmsPipeline* Pipeline;
- BCHSWADJUSTS bchsw;
- cmsCIExyY WhitePnt;
- cmsStage* CLUT;
- cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
- int i;
+ cmsHPROFILE hICC;
+ cmsPipeline* Pipeline;
+ BCHSWADJUSTS bchsw;
+ cmsCIExyY WhitePnt;
+ cmsStage* CLUT;
+ cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
+ int i;
-
- bchsw.Brightness = Bright;
- bchsw.Contrast = Contrast;
- bchsw.Hue = Hue;
- bchsw.Saturation = Saturation;
+ bchsw.Brightness = Bright;
+ bchsw.Contrast = Contrast;
+ bchsw.Hue = Hue;
+ bchsw.Saturation = Saturation;
- cmsWhitePointFromTemp(&WhitePnt, TempSrc );
- cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
+ cmsWhitePointFromTemp(&WhitePnt, TempSrc );
+ cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
- cmsWhitePointFromTemp(&WhitePnt, TempDest);
- cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
+ cmsWhitePointFromTemp(&WhitePnt, TempDest);
+ cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
- hICC = cmsCreateProfilePlaceholder(ContextID);
- if (!hICC) // can't allocate
- return NULL;
+ hICC = cmsCreateProfilePlaceholder(ContextID);
+ if (!hICC) // can't allocate
+ return NULL;
- cmsSetDeviceClass(hICC, cmsSigAbstractClass);
- cmsSetColorSpace(hICC, cmsSigLabData);
- cmsSetPCS(hICC, cmsSigLabData);
+ cmsSetDeviceClass(hICC, cmsSigAbstractClass);
+ cmsSetColorSpace(hICC, cmsSigLabData);
+ cmsSetPCS(hICC, cmsSigLabData);
- cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
-
+ cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
- // Creates a Pipeline with 3D grid only
- Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
- if (Pipeline == NULL) {
- cmsCloseProfile(hICC);
- return NULL;
- }
+ // Creates a Pipeline with 3D grid only
+ Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
+ if (Pipeline == NULL) {
+ cmsCloseProfile(hICC);
+ return NULL;
+ }
- for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
- CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
- if (CLUT == NULL) return NULL;
+ for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
+ CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
+ if (CLUT == NULL) return NULL;
- if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
+ if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
+
+ // Shouldn't reach here
+ goto Error;
+ }
- // Shouldn't reach here
- cmsPipelineFree(Pipeline);
- cmsCloseProfile(hICC);
- return NULL;
- }
+ if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) {
+ goto Error;
+ }
- cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT);
-
- // Create tags
+ // Create tags
+ if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
- if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
+ cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
- cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
+ cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
- cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
+ // Pipeline is already on virtual profile
+ cmsPipelineFree(Pipeline);
- // Pipeline is already on virtual profile
- cmsPipelineFree(Pipeline);
+ // Ok, done
+ return hICC;
- // Ok, done
- return hICC;
+Error:
+ cmsPipelineFree(Pipeline);
+ cmsCloseProfile(hICC);
+ return NULL;
}
@@ -856,7 +877,8 @@
PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
cmsFreeToneCurve(EmptyTab);
- cmsPipelineInsertStage(LUT, cmsAT_END, PostLin);
+ if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
+ goto Error;
if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
@@ -999,6 +1021,7 @@
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
+ { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
@@ -1059,6 +1082,7 @@
cmsContext ContextID = cmsGetTransformContextID(hTransform);
const cmsAllowedLUT* AllowedLUT;
cmsTagSignature DestinationTag;
+ cmsProfileClassSignature deviceClass;
_cmsAssert(hTransform != NULL);
@@ -1080,13 +1104,15 @@
// Time to fix the Lab2/Lab4 issue.
if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
+ goto Error;
}
// On the output side too
if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
- cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
+ goto Error;
}
@@ -1108,8 +1134,9 @@
FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);
+ deviceClass = cmsGetDeviceClass(hProfile);
- if (cmsGetDeviceClass(hProfile) == cmsSigOutputClass)
+ if (deviceClass == cmsSigOutputClass)
DestinationTag = cmsSigBToA0Tag;
else
DestinationTag = cmsSigAToB0Tag;
@@ -1136,10 +1163,12 @@
// Put identity curves if needed
if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
- cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
+ goto Error;
if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
- cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut));
+ if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
+ goto Error;
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
}
@@ -1168,10 +1197,22 @@
if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
}
- if (xform ->Sequence != NULL) {
+ if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
}
+ // Set the white point
+ if (deviceClass == cmsSigInputClass) {
+ if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
+ }
+ else {
+ if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
+ }
+
+
+ // Per 7.2.15 in spec 4.3
+ cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);
+
cmsPipelineFree(LUT);
return hProfile;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Wed Apr 16 10:53:10 2014 -0700
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2010 Marti Maria Saguer
+// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -76,48 +76,48 @@
// Obtains WhitePoint from Temperature
cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK)
{
- cmsFloat64Number x, y;
- cmsFloat64Number T, T2, T3;
- // cmsFloat64Number M1, M2;
+ cmsFloat64Number x, y;
+ cmsFloat64Number T, T2, T3;
+ // cmsFloat64Number M1, M2;
- _cmsAssert(WhitePoint != NULL);
+ _cmsAssert(WhitePoint != NULL);
- T = TempK;
- T2 = T*T; // Square
- T3 = T2*T; // Cube
+ T = TempK;
+ T2 = T*T; // Square
+ T3 = T2*T; // Cube
- // For correlated color temperature (T) between 4000K and 7000K:
+ // For correlated color temperature (T) between 4000K and 7000K:
- if (T >= 4000. && T <= 7000.)
- {
- x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
- }
- else
- // or for correlated color temperature (T) between 7000K and 25000K:
+ if (T >= 4000. && T <= 7000.)
+ {
+ x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
+ }
+ else
+ // or for correlated color temperature (T) between 7000K and 25000K:
- if (T > 7000.0 && T <= 25000.0)
- {
- x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
- }
- else {
- cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
- return FALSE;
- }
+ if (T > 7000.0 && T <= 25000.0)
+ {
+ x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
+ }
+ else {
+ cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
+ return FALSE;
+ }
- // Obtain y(x)
+ // Obtain y(x)
- y = -3.000*(x*x) + 2.870*x - 0.275;
+ y = -3.000*(x*x) + 2.870*x - 0.275;
- // wave factors (not used, but here for futures extensions)
+ // wave factors (not used, but here for futures extensions)
- // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
- // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
+ // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
+ // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
- WhitePoint -> x = x;
- WhitePoint -> y = y;
- WhitePoint -> Y = 1.0;
+ WhitePoint -> x = x;
+ WhitePoint -> y = y;
+ WhitePoint -> Y = 1.0;
- return TRUE;
+ return TRUE;
}
@@ -266,7 +266,7 @@
{{ 0.8951, 0.2664, -0.1614 }},
{{ -0.7502, 1.7135, 0.0367 }},
{{ 0.0389, -0.0685, 1.0296 }}
- }};
+ }};
if (ConeMatrix == NULL)
ConeMatrix = &LamRigg;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Wed Apr 16 10:53:10 2014 -0700
@@ -396,7 +396,7 @@
static _cmsTransformCollection* TransformCollection = NULL;
// Register new ways to transform
-cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data)
{
cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
_cmsTransformCollection* fl;
@@ -412,7 +412,7 @@
if (Plugin ->Factory == NULL) return FALSE;
- fl = (_cmsTransformCollection*) _cmsPluginMalloc(sizeof(_cmsTransformCollection));
+ fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
@@ -651,6 +651,22 @@
// ----------------------------------------------------------------------------------------------------------------
+static
+void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
+{
+ if (src == NULL) {
+ wtPt ->X = cmsD50X;
+ wtPt ->Y = cmsD50Y;
+ wtPt ->Z = cmsD50Z;
+ }
+ else {
+ wtPt ->X = src->X;
+ wtPt ->Y = src->Y;
+ wtPt ->Z = src->Z;
+ }
+
+}
+
// New to lcms 2.0 -- have all parameters available.
cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
@@ -664,7 +680,6 @@
cmsUInt32Number dwFlags)
{
_cmsTRANSFORM* xform;
- cmsBool FloatTransform;
cmsColorSpaceSignature EntryColorSpace;
cmsColorSpaceSignature ExitColorSpace;
cmsPipeline* Lut;
@@ -681,9 +696,7 @@
if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
}
- // On floating point transforms, inhibit optimizations
- FloatTransform = (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat));
-
+ // On floating point transforms, inhibit cache
if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
dwFlags |= cmsFLAGS_NOCACHE;
@@ -730,6 +743,10 @@
xform ->ExitColorSpace = ExitColorSpace;
xform ->RenderingIntent = Intents[nProfiles-1];
+ // Take white points
+ SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag));
+ SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
+
// Create a gamut check LUT if requested
if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h Wed Apr 16 10:53:10 2014 -0700
@@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2011 Marti Maria Saguer
+// Copyright (c) 1998-2013 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,7 @@
//
//---------------------------------------------------------------------------------
//
-// Version 2.4
+// Version 2.5
//
#ifndef _lcms2_H
@@ -101,7 +101,7 @@
#endif
// Version/release
-#define LCMS_VERSION 2040
+#define LCMS_VERSION 2050
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -367,6 +367,7 @@
cmsSigPreview1Tag = 0x70726531, // 'pre1'
cmsSigPreview2Tag = 0x70726532, // 'pre2'
cmsSigProfileDescriptionTag = 0x64657363, // 'desc'
+ cmsSigProfileDescriptionMLTag = 0x6473636d, // 'dscm'
cmsSigProfileSequenceDescTag = 0x70736571, // 'pseq'
cmsSigProfileSequenceIdTag = 0x70736964, // 'psid'
cmsSigPs2CRD0Tag = 0x70736430, // 'psd0'
@@ -1014,6 +1015,7 @@
// Plug-In registering ---------------------------------------------------------------------------------------------------
CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
+CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
CMSAPI void CMSEXPORT cmsUnregisterPlugins(void);
// Error logging ----------------------------------------------------------------------------------------------------------
@@ -1190,7 +1192,7 @@
// Where to place/locate the stages in the pipeline chain
typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
-CMSAPI void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
+CMSAPI int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
// This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
@@ -1274,6 +1276,13 @@
const char LanguageCode[3], const char CountryCode[3],
char ObtainedLanguage[3], char ObtainedCountry[3]);
+CMSAPI cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu);
+
+CMSAPI cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
+ cmsUInt32Number idx,
+ char LanguageCode[3],
+ char CountryCode[3]);
+
// Undercolorremoval & black generation -------------------------------------------------------------------------------------
typedef struct {
@@ -1424,6 +1433,7 @@
CMSAPI void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer);
+CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model);
CMSAPI void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h Wed Apr 16 10:53:10 2014 -0700
@@ -27,7 +27,7 @@
// However, the following notice accompanied the original version of this
// file:
//
-//---------------------------------------------------------------------------------
+
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
@@ -196,7 +196,7 @@
// Plug-In registering ---------------------------------------------------------------
// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
-void* _cmsPluginMalloc(cmsUInt32Number size);
+void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
// Memory management
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
@@ -205,28 +205,28 @@
cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
// Parametric curves
-cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Formatters management
-cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Tag type management
-cmsBool _cmsRegisterTagTypePlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterTagTypePlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Tag management
-cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterTagPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Intent management
-cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Multi Process elements
-cmsBool _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Optimization
-cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Transform
-cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// ---------------------------------------------------------------------------------------------------------
@@ -263,7 +263,7 @@
cmsUInt16Number Country;
cmsUInt32Number StrW; // Offset to current unicode string
- cmsUInt32Number Len; // Lenght in bytes
+ cmsUInt32Number Len; // Length in bytes
} _cmsMLUentry;
@@ -330,9 +330,11 @@
cmsColorSpaceSignature ColorSpace;
cmsColorSpaceSignature PCS;
cmsUInt32Number RenderingIntent;
+
cmsUInt32Number flags;
cmsUInt32Number manufacturer, model;
cmsUInt64Number attributes;
+ cmsUInt32Number creator;
cmsProfileID ProfileID;
@@ -585,6 +587,10 @@
cmsColorSpaceSignature EntryColorSpace;
cmsColorSpaceSignature ExitColorSpace;
+ // White points (informative only)
+ cmsCIEXYZ EntryWhitePoint;
+ cmsCIEXYZ ExitWhitePoint;
+
// Profiles used to create the transform
cmsSEQ* Sequence;
--- a/jdk/src/share/native/sun/management/Flag.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/management/Flag.c Wed Apr 16 10:53:10 2014 -0700
@@ -97,12 +97,12 @@
return 0;
}
- if (count == 0) {
+ if (count <= 0) {
JNU_ThrowIllegalArgumentException(env, 0);
return 0;
}
- gsize = count * sizeof(jmmVMGlobal);
+ gsize = (size_t)count * sizeof(jmmVMGlobal);
globals = (jmmVMGlobal*) malloc(gsize);
if (globals == NULL) {
JNU_ThrowOutOfMemoryError(env, 0);
--- a/jdk/src/share/native/sun/management/GcInfoBuilder.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/share/native/sun/management/GcInfoBuilder.c Wed Apr 16 10:53:10 2014 -0700
@@ -59,12 +59,12 @@
return;
}
- if (num_attributes == 0) {
+ if (num_attributes <= 0) {
JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes");
return;
}
- ext_att_info = (jmmExtAttributeInfo*) malloc(num_attributes *
+ ext_att_info = (jmmExtAttributeInfo*) malloc((size_t)num_attributes *
sizeof(jmmExtAttributeInfo));
if (ext_att_info == NULL) {
JNU_ThrowOutOfMemoryError(env, 0);
@@ -78,7 +78,7 @@
return;
}
- nativeTypes = (jchar*) malloc(num_attributes * sizeof(jchar));
+ nativeTypes = (jchar*) malloc((size_t)num_attributes * sizeof(jchar));
if (nativeTypes == NULL) {
free(ext_att_info);
JNU_ThrowOutOfMemoryError(env, 0);
@@ -188,11 +188,16 @@
return 0;
}
+ if (ext_att_count <= 0) {
+ JNU_ThrowIllegalArgumentException(env, "Invalid ext_att_count");
+ return 0;
+ }
+
gc_stat.usage_before_gc = usageBeforeGC;
gc_stat.usage_after_gc = usageAfterGC;
gc_stat.gc_ext_attribute_values_size = ext_att_count;
if (ext_att_count > 0) {
- gc_stat.gc_ext_attribute_values = (jvalue*) malloc(ext_att_count *
+ gc_stat.gc_ext_attribute_values = (jvalue*) malloc((size_t)ext_att_count *
sizeof(jvalue));
if (gc_stat.gc_ext_attribute_values == NULL) {
JNU_ThrowOutOfMemoryError(env, 0);
@@ -212,7 +217,7 @@
}
// convert the ext_att_types to native types
- nativeTypes = (jchar*) malloc(ext_att_count * sizeof(jchar));
+ nativeTypes = (jchar*) malloc((size_t)ext_att_count * sizeof(jchar));
if (nativeTypes == NULL) {
if (gc_stat.gc_ext_attribute_values != NULL) {
free(gc_stat.gc_ext_attribute_values);
--- a/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Wed Apr 16 10:53:10 2014 -0700
@@ -86,7 +86,7 @@
protected synchronized void setContentsNative(Transferable contents) {
SortedMap<Long,DataFlavor> formatMap =
DataTransferer.getInstance().getFormatsForTransferable
- (contents, DataTransferer.adaptFlavorMap(flavorMap));
+ (contents, DataTransferer.adaptFlavorMap(getDefaultFlavorTable()));
long[] formats = DataTransferer.keysToLongArray(formatMap);
if (!selection.setOwner(contents, formatMap, formats,
@@ -125,7 +125,7 @@
private void checkChangeHere(Transferable contents) {
if (areFlavorListenersRegistered()) {
checkChange(DataTransferer.getInstance().
- getFormatsForTransferableAsArray(contents, flavorMap));
+ getFormatsForTransferableAsArray(contents, getDefaultFlavorTable()));
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Apr 16 10:53:10 2014 -0700
@@ -50,7 +50,8 @@
import sun.awt.datatransfer.DataTransferer;
import sun.font.FontConfigManager;
import sun.java2d.SunGraphicsEnvironment;
-import sun.misc.PerformanceLogger;
+import sun.misc.*;
+import sun.misc.ThreadGroupUtils;
import sun.print.PrintJob2D;
import sun.security.action.GetPropertyAction;
import sun.security.action.GetBooleanAction;
@@ -254,33 +255,25 @@
} finally {
awtUnlock();
}
- PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
- public Void run() {
- ThreadGroup mainTG = Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = mainTG.getParent();
- while (parentTG != null) {
- mainTG = parentTG;
- parentTG = mainTG.getParent();
- }
- Thread shutdownThread = new Thread(mainTG, "XToolkt-Shutdown-Thread") {
- public void run() {
- XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
- if (peer != null) {
- peer.dispose();
- }
- if (xs != null) {
- ((XAWTXSettings)xs).dispose();
- }
- freeXKB();
- if (log.isLoggable(PlatformLogger.Level.FINE)) {
- dumpPeers();
- }
+ PrivilegedAction<Void> a = () -> {
+ Thread shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
+ public void run() {
+ XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
+ if (peer != null) {
+ peer.dispose();
+ }
+ if (xs != null) {
+ ((XAWTXSettings)xs).dispose();
}
- };
- shutdownThread.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(shutdownThread);
- return null;
- }
+ freeXKB();
+ if (log.isLoggable(PlatformLogger.Level.FINE)) {
+ dumpPeers();
+ }
+ }
+ };
+ shutdownThread.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(shutdownThread);
+ return null;
};
AccessController.doPrivileged(a);
}
@@ -322,21 +315,13 @@
init();
XWM.init();
- PrivilegedAction<Thread> action = new PrivilegedAction() {
- public Thread run() {
- ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = currentTG.getParent();
- while (parentTG != null) {
- currentTG = parentTG;
- parentTG = currentTG.getParent();
- }
- Thread thread = new Thread(currentTG, XToolkit.this, "AWT-XAWT");
- thread.setPriority(Thread.NORM_PRIORITY + 1);
- thread.setDaemon(true);
- return thread;
- }
- };
- toolkitThread = AccessController.doPrivileged(action);
+ toolkitThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
+ Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, "AWT-XAWT");
+ thread.setContextClassLoader(null);
+ thread.setPriority(Thread.NORM_PRIORITY + 1);
+ thread.setDaemon(true);
+ return thread;
+ });
toolkitThread.start();
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Wed Apr 16 10:53:10 2014 -0700
@@ -42,6 +42,8 @@
import sun.java2d.xr.XRGraphicsConfig;
import sun.java2d.loops.SurfaceType;
+import sun.misc.ThreadGroupUtils;
+
/**
* This is an implementation of a GraphicsDevice object for a single
* X11 screen.
@@ -423,28 +425,19 @@
// is already in the original DisplayMode at that time, this
// hook will have no effect)
shutdownHookRegistered = true;
- PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
- public Void run() {
- ThreadGroup mainTG = Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = mainTG.getParent();
- while (parentTG != null) {
- mainTG = parentTG;
- parentTG = mainTG.getParent();
+ PrivilegedAction<Void> a = () -> {
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ Runnable r = () -> {
+ Window old = getFullScreenWindow();
+ if (old != null) {
+ exitFullScreenExclusive(old);
+ setDisplayMode(origDisplayMode);
}
- Runnable r = new Runnable() {
- public void run() {
- Window old = getFullScreenWindow();
- if (old != null) {
- exitFullScreenExclusive(old);
- setDisplayMode(origDisplayMode);
- }
- }
- };
- Thread t = new Thread(mainTG, r,"Display-Change-Shutdown-Thread-"+screen);
- t.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(t);
- return null;
- }
+ };
+ Thread t = new Thread(rootTG, r,"Display-Change-Shutdown-Thread-"+screen);
+ t.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(t);
+ return null;
};
AccessController.doPrivileged(a);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/net/www/content-types.properties Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,280 @@
+#sun.net.www MIME content-types table
+#
+# Property fields:
+#
+# <description> ::= 'description' '=' <descriptive string>
+# <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
+# <image> ::= 'icon' '=' <filename of icon image>
+# <action> ::= 'browser' | 'application' | 'save' | 'unknown'
+# <application> ::= 'application' '=' <command line template>
+#
+
+#
+# The "we don't know anything about this data" type(s).
+# Used internally to mark unrecognized types.
+#
+content/unknown: description=Unknown Content
+unknown/unknown: description=Unknown Data Type
+
+#
+# The template we should use for temporary files when launching an application
+# to view a document of given type.
+#
+temp.file.template: /tmp/%s
+
+#
+# The "real" types.
+#
+application/octet-stream: \
+ description=Generic Binary Stream;\
+ file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
+
+application/oda: \
+ description=ODA Document;\
+ file_extensions=.oda
+
+application/pdf: \
+ description=Adobe PDF Format;\
+ file_extensions=.pdf
+
+application/postscript: \
+ description=Postscript File;\
+ file_extensions=.eps,.ai,.ps;\
+ icon=ps;\
+ action=application;\
+ application=imagetool %s
+
+application/x-dvi: \
+ description=TeX DVI File;\
+ file_extensions=.dvi;\
+ action=application;\
+ application=xdvi %s
+
+application/x-hdf: \
+ description=Hierarchical Data Format;\
+ file_extensions=.hdf;\
+ action=save
+
+application/x-latex: \
+ description=LaTeX Source;\
+ file_extensions=.latex
+
+application/x-netcdf: \
+ description=Unidata netCDF Data Format;\
+ file_extensions=.nc,.cdf;\
+ action=save
+
+application/x-tex: \
+ description=TeX Source;\
+ file_extensions=.tex
+
+application/x-texinfo: \
+ description=Gnu Texinfo;\
+ file_extensions=.texinfo,.texi
+
+application/x-troff: \
+ description=Troff Source;\
+ file_extensions=.t,.tr,.roff;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
+
+application/x-troff-man: \
+ description=Troff Manpage Source;\
+ file_extensions=.man;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
+
+application/x-troff-me: \
+ description=Troff ME Macros;\
+ file_extensions=.me;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
+
+application/x-troff-ms: \
+ description=Troff MS Macros;\
+ file_extensions=.ms;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
+
+application/x-wais-source: \
+ description=Wais Source;\
+ file_extensions=.src,.wsrc
+
+application/zip: \
+ description=Zip File;\
+ file_extensions=.zip;\
+ icon=zip;\
+ action=save
+
+application/x-bcpio: \
+ description=Old Binary CPIO Archive;\
+ file_extensions=.bcpio; action=save
+
+application/x-cpio: \
+ description=Unix CPIO Archive;\
+ file_extensions=.cpio; action=save
+
+application/x-gtar: \
+ description=Gnu Tar Archive;\
+ file_extensions=.gtar;\
+ icon=tar;\
+ action=save
+
+application/x-shar: \
+ description=Shell Archive;\
+ file_extensions=.sh,.shar;\
+ action=save
+
+application/x-sv4cpio: \
+ description=SVR4 CPIO Archive;\
+ file_extensions=.sv4cpio; action=save
+
+application/x-sv4crc: \
+ description=SVR4 CPIO with CRC;\
+ file_extensions=.sv4crc; action=save
+
+application/x-tar: \
+ description=Tar Archive;\
+ file_extensions=.tar;\
+ icon=tar;\
+ action=save
+
+application/x-ustar: \
+ description=US Tar Archive;\
+ file_extensions=.ustar;\
+ action=save
+
+audio/basic: \
+ description=Basic Audio;\
+ file_extensions=.snd,.au;\
+ icon=audio;\
+ action=application;\
+ application=audiotool %s
+
+audio/x-aiff: \
+ description=Audio Interchange Format File;\
+ file_extensions=.aifc,.aif,.aiff;\
+ icon=aiff
+
+audio/x-wav: \
+ description=Wav Audio;\
+ file_extensions=.wav;\
+ icon=wav
+
+image/gif: \
+ description=GIF Image;\
+ file_extensions=.gif;\
+ icon=gif;\
+ action=browser
+
+image/ief: \
+ description=Image Exchange Format;\
+ file_extensions=.ief
+
+image/jpeg: \
+ description=JPEG Image;\
+ file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+ icon=jpeg;\
+ action=browser;\
+ application=imagetool %s
+
+image/tiff: \
+ description=TIFF Image;\
+ file_extensions=.tif,.tiff;\
+ icon=tiff
+
+image/vnd.fpx: \
+ description=FlashPix Image;\
+ file_extensions=.fpx,.fpix
+
+image/x-cmu-rast: \
+ description=CMU Raster Image;\
+ file_extensions=.ras
+
+image/x-portable-anymap: \
+ description=PBM Anymap Format;\
+ file_extensions=.pnm
+
+image/x-portable-bitmap: \
+ description=PBM Bitmap Format;\
+ file_extensions=.pbm
+
+image/x-portable-graymap: \
+ description=PBM Graymap Format;\
+ file_extensions=.pgm
+
+image/x-portable-pixmap: \
+ description=PBM Pixmap Format;\
+ file_extensions=.ppm
+
+image/x-rgb: \
+ description=RGB Image;\
+ file_extensions=.rgb
+
+image/x-xbitmap: \
+ description=X Bitmap Image;\
+ file_extensions=.xbm,.xpm
+
+image/x-xwindowdump: \
+ description=X Window Dump Image;\
+ file_extensions=.xwd
+
+image/png: \
+ description=PNG Image;\
+ file_extensions=.png;\
+ icon=png;\
+ action=browser
+
+image/bmp: \
+ description=Bitmap Image;\
+ file_extensions=.bmp;
+
+text/html: \
+ description=HTML Document;\
+ file_extensions=.htm,.html;\
+ icon=html
+
+text/plain: \
+ description=Plain Text;\
+ file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
+ icon=text;\
+ action=browser
+
+text/tab-separated-values: \
+ description=Tab Separated Values Text;\
+ file_extensions=.tsv
+
+text/x-setext: \
+ description=Structure Enhanced Text;\
+ file_extensions=.etx
+
+video/mpeg: \
+ description=MPEG Video Clip;\
+ file_extensions=.mpg,.mpe,.mpeg;\
+ icon=mpeg;\
+ action=application;\
+ application=mpeg_play %s
+
+video/quicktime: \
+ description=QuickTime Video Clip;\
+ file_extensions=.mov,.qt
+
+application/x-troff-msvideo: \
+ description=AVI Video;\
+ file_extensions=.avi;\
+ icon=avi
+
+video/x-sgi-movie: \
+ description=SGI Movie;\
+ file_extensions=.movie,.mv
+
+message/rfc822: \
+ description=Internet Email Message;\
+ file_extensions=.mime
+
+application/xml: \
+ description=XML document;\
+ file_extensions=.xml
+
+
+
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java Wed Apr 16 10:53:10 2014 -0700
@@ -77,7 +77,7 @@
}
private static native int fgetxattr0(int filedes, long nameAddress,
- long valueAdddress, int valueLen) throws UnixException;
+ long valueAddress, int valueLen) throws UnixException;
/**
* fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags);
@@ -94,7 +94,7 @@
}
private static native void fsetxattr0(int filedes, long nameAddress,
- long valueAdddress, int valueLen) throws UnixException;
+ long valueAddress, int valueLen) throws UnixException;
/**
* fremovexattr(int filedes, const char *name);
--- a/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java Wed Apr 16 10:53:10 2014 -0700
@@ -36,7 +36,7 @@
class MagicFileTypeDetector extends AbstractFileTypeDetector {
- private static final String UNKNOW_MIME_TYPE = "application/octet-stream";
+ private static final String UNKNOWN_MIME_TYPE = "application/octet-stream";
// true if libmagic is available and successfully loaded
private final boolean libmagicAvailable;
@@ -57,7 +57,7 @@
try {
byte[] type = probe0(buffer.address());
String mimeType = (type == null) ? null : new String(type);
- return UNKNOW_MIME_TYPE.equals(mimeType) ? null : mimeType;
+ return UNKNOWN_MIME_TYPE.equals(mimeType) ? null : mimeType;
} finally {
buffer.release();
}
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Wed Apr 16 10:53:10 2014 -0700
@@ -290,7 +290,7 @@
return acl;
}
- // Retrns true if NFSv4 ACLs not enabled on file system
+ // Returns true if NFSv4 ACLs not enabled on file system
private static boolean isAclsEnabled(int fd) {
try {
long enabled = fpathconf(fd, _PC_ACL_ENABLED);
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Wed Apr 16 10:53:10 2014 -0700
@@ -627,14 +627,14 @@
/**
* Update watch key's events. If ENTRY_MODIFY changes to be enabled
- * then register each file in the direcory; If ENTRY_MODIFY changed to
+ * then register each file in the directory; If ENTRY_MODIFY changed to
* be disabled then unregister each file.
*/
void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
throws UnixException
{
- // update events, rembering if ENTRY_MODIFY was previously
+ // update events, remembering if ENTRY_MODIFY was previously
// enabled or disabled.
boolean oldModifyEnabled = key.events()
.contains(StandardWatchEventKinds.ENTRY_MODIFY);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Wed Apr 16 10:53:10 2014 -0700
@@ -48,7 +48,7 @@
// filter (may be null)
private final DirectoryStream.Filter<? super Path> filter;
- // used to coorindate closing of directory stream
+ // used to coordinate closing of directory stream
private final ReentrantReadWriteLock streamLock =
new ReentrantReadWriteLock(true);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Wed Apr 16 10:53:10 2014 -0700
@@ -133,7 +133,7 @@
private static final String OWNER_NAME = "owner";
private static final String GROUP_NAME = "group";
- // the names of the posix attributes (incudes basic)
+ // the names of the posix attributes (includes basic)
static final Set<String> posixAttributeNames =
Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Wed Apr 16 10:53:10 2014 -0700
@@ -339,7 +339,7 @@
};
}
- // Override if the platform has different path match requrement, such as
+ // Override if the platform has different path match requirement, such as
// case insensitive or Unicode canonical equal on MacOSX
Pattern compilePathMatchPattern(String expr) {
return Pattern.compile(expr);
--- a/jdk/src/solaris/demo/jni/Poller/Poller.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/demo/jni/Poller/Poller.c Wed Apr 16 10:53:10 2014 -0700
@@ -318,7 +318,7 @@
ioevent_t *ioeh;
- if (handle < 0 || handle > MAX_HANDLES)
+ if (handle < 0 || handle >= MAX_HANDLES)
{
STATE_EXCEPTION("DestroyPoller - handle out of range");
return;
@@ -366,7 +366,7 @@
int retval;
ioevent_t *ioeh;
- if (handle < 0 || handle > MAX_HANDLES)
+ if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("AddFd - handle out of range");
ioeh = &IOE_handles[handle];
@@ -459,7 +459,7 @@
return fd;
}
-/*
+/*
* Class: Poller
* Method: nativeRemoveFd
* Signature: (II)I
@@ -469,7 +469,7 @@
{
ioevent_t *ioeh;
- if (handle < 0 || handle > MAX_HANDLES)
+ if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("RemoveFd - handle out of range");
ioeh = &IOE_handles[handle];
@@ -576,7 +576,7 @@
int i;
ioevent_t *ioeh;
- if (handle < 0 || handle > MAX_HANDLES)
+ if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("IsMember - handle out of range");
ioeh = &IOE_handles[handle];
@@ -629,7 +629,7 @@
ioevent_t *ioeh;
jboolean isCopy1,isCopy2;
- if (handle < 0 || handle > MAX_HANDLES)
+ if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("nativeWait - handle out of range");
ioeh = &IOE_handles[handle];
--- a/jdk/src/solaris/lib/content-types.properties Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-# <description> ::= 'description' '=' <descriptive string>
-# <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-# <image> ::= 'icon' '=' <filename of icon image>
-# <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-# <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: /tmp/%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
- description=Generic Binary Stream;\
- file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
-
-application/oda: \
- description=ODA Document;\
- file_extensions=.oda
-
-application/pdf: \
- description=Adobe PDF Format;\
- file_extensions=.pdf
-
-application/postscript: \
- description=Postscript File;\
- file_extensions=.eps,.ai,.ps;\
- icon=ps;\
- action=application;\
- application=imagetool %s
-
-application/x-dvi: \
- description=TeX DVI File;\
- file_extensions=.dvi;\
- action=application;\
- application=xdvi %s
-
-application/x-hdf: \
- description=Hierarchical Data Format;\
- file_extensions=.hdf;\
- action=save
-
-application/x-latex: \
- description=LaTeX Source;\
- file_extensions=.latex
-
-application/x-netcdf: \
- description=Unidata netCDF Data Format;\
- file_extensions=.nc,.cdf;\
- action=save
-
-application/x-tex: \
- description=TeX Source;\
- file_extensions=.tex
-
-application/x-texinfo: \
- description=Gnu Texinfo;\
- file_extensions=.texinfo,.texi
-
-application/x-troff: \
- description=Troff Source;\
- file_extensions=.t,.tr,.roff;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
-
-application/x-troff-man: \
- description=Troff Manpage Source;\
- file_extensions=.man;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
-
-application/x-troff-me: \
- description=Troff ME Macros;\
- file_extensions=.me;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
-
-application/x-troff-ms: \
- description=Troff MS Macros;\
- file_extensions=.ms;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
-
-application/x-wais-source: \
- description=Wais Source;\
- file_extensions=.src,.wsrc
-
-application/zip: \
- description=Zip File;\
- file_extensions=.zip;\
- icon=zip;\
- action=save
-
-application/x-bcpio: \
- description=Old Binary CPIO Archive;\
- file_extensions=.bcpio; action=save
-
-application/x-cpio: \
- description=Unix CPIO Archive;\
- file_extensions=.cpio; action=save
-
-application/x-gtar: \
- description=Gnu Tar Archive;\
- file_extensions=.gtar;\
- icon=tar;\
- action=save
-
-application/x-shar: \
- description=Shell Archive;\
- file_extensions=.sh,.shar;\
- action=save
-
-application/x-sv4cpio: \
- description=SVR4 CPIO Archive;\
- file_extensions=.sv4cpio; action=save
-
-application/x-sv4crc: \
- description=SVR4 CPIO with CRC;\
- file_extensions=.sv4crc; action=save
-
-application/x-tar: \
- description=Tar Archive;\
- file_extensions=.tar;\
- icon=tar;\
- action=save
-
-application/x-ustar: \
- description=US Tar Archive;\
- file_extensions=.ustar;\
- action=save
-
-audio/basic: \
- description=Basic Audio;\
- file_extensions=.snd,.au;\
- icon=audio;\
- action=application;\
- application=audiotool %s
-
-audio/x-aiff: \
- description=Audio Interchange Format File;\
- file_extensions=.aifc,.aif,.aiff;\
- icon=aiff
-
-audio/x-wav: \
- description=Wav Audio;\
- file_extensions=.wav;\
- icon=wav
-
-image/gif: \
- description=GIF Image;\
- file_extensions=.gif;\
- icon=gif;\
- action=browser
-
-image/ief: \
- description=Image Exchange Format;\
- file_extensions=.ief
-
-image/jpeg: \
- description=JPEG Image;\
- file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
- icon=jpeg;\
- action=browser;\
- application=imagetool %s
-
-image/tiff: \
- description=TIFF Image;\
- file_extensions=.tif,.tiff;\
- icon=tiff
-
-image/vnd.fpx: \
- description=FlashPix Image;\
- file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
- description=CMU Raster Image;\
- file_extensions=.ras
-
-image/x-portable-anymap: \
- description=PBM Anymap Format;\
- file_extensions=.pnm
-
-image/x-portable-bitmap: \
- description=PBM Bitmap Format;\
- file_extensions=.pbm
-
-image/x-portable-graymap: \
- description=PBM Graymap Format;\
- file_extensions=.pgm
-
-image/x-portable-pixmap: \
- description=PBM Pixmap Format;\
- file_extensions=.ppm
-
-image/x-rgb: \
- description=RGB Image;\
- file_extensions=.rgb
-
-image/x-xbitmap: \
- description=X Bitmap Image;\
- file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
- description=X Window Dump Image;\
- file_extensions=.xwd
-
-image/png: \
- description=PNG Image;\
- file_extensions=.png;\
- icon=png;\
- action=browser
-
-image/bmp: \
- description=Bitmap Image;\
- file_extensions=.bmp;
-
-text/html: \
- description=HTML Document;\
- file_extensions=.htm,.html;\
- icon=html
-
-text/plain: \
- description=Plain Text;\
- file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
- icon=text;\
- action=browser
-
-text/tab-separated-values: \
- description=Tab Separated Values Text;\
- file_extensions=.tsv
-
-text/x-setext: \
- description=Structure Enhanced Text;\
- file_extensions=.etx
-
-video/mpeg: \
- description=MPEG Video Clip;\
- file_extensions=.mpg,.mpe,.mpeg;\
- icon=mpeg;\
- action=application;\
- application=mpeg_play %s
-
-video/quicktime: \
- description=QuickTime Video Clip;\
- file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
- description=AVI Video;\
- file_extensions=.avi;\
- icon=avi
-
-video/x-sgi-movie: \
- description=SGI Movie;\
- file_extensions=.movie,.mv
-
-message/rfc822: \
- description=Internet Email Message;\
- file_extensions=.mime
-
-application/xml: \
- description=XML document;\
- file_extensions=.xml
-
-
-
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c Wed Apr 16 10:53:10 2014 -0700
@@ -76,7 +76,7 @@
adPath[*count].st_ino = statBuf.st_ino;
adPath[*count].st_dev = statBuf.st_dev;
strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
- adPath[*count].path[MAX_NAME_LENGTH] = 0;
+ adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
(*count)++;
TRACE1("Added audio device %s\n", path);
}
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Apr 16 10:53:10 2014 -0700
@@ -39,6 +39,7 @@
import static sun.awt.shell.Win32ShellFolder2.*;
import sun.awt.OSInfo;
+import sun.misc.ThreadGroupUtils;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
@@ -503,23 +504,16 @@
}
}
};
- comThread =
- AccessController.doPrivileged(
- new PrivilegedAction<Thread>() {
- public Thread run() {
+ comThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
/* The thread must be a member of a thread group
* which will not get GCed before VM exit.
* Make its parent the top-level thread group.
*/
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- Thread thread = new Thread(tg, comRun, "Swing-Shell");
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ Thread thread = new Thread(rootTG, comRun, "Swing-Shell");
thread.setDaemon(true);
return thread;
}
- }
);
return comThread;
}
--- a/jdk/src/windows/classes/sun/awt/windows/WClipboard.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WClipboard.java Wed Apr 16 10:53:10 2014 -0700
@@ -62,7 +62,6 @@
@Override
protected void setContentsNative(Transferable contents) {
-
// Don't use delayed Clipboard rendering for the Transferable's data.
// If we did that, we would call Transferable.getTransferData on
// the Toolkit thread, which is a security hole.
@@ -71,7 +70,7 @@
// translated. Then, for each format, translate the data and post
// it to the Clipboard.
Map <Long, DataFlavor> formatMap = WDataTransferer.getInstance().
- getFormatsForTransferable(contents, flavorMap);
+ getFormatsForTransferable(contents, getDefaultFlavorTable());
openClipboard(this);
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed Apr 16 10:53:10 2014 -0700
@@ -40,6 +40,7 @@
import sun.awt.AWTPermissions;
import sun.awt.LightweightFrame;
import sun.awt.SunToolkit;
+import sun.misc.ThreadGroupUtils;
import sun.awt.Win32GraphicsDevice;
import sun.awt.Win32GraphicsEnvironment;
import sun.awt.datatransfer.DataTransferer;
@@ -224,7 +225,7 @@
private static native void postDispose();
- private static native boolean startToolkitThread(Runnable thread);
+ private static native boolean startToolkitThread(Runnable thread, ThreadGroup rootThreadGroup);
public WToolkit() {
// Startup toolkit threads
@@ -241,8 +242,11 @@
*/
AWTAutoShutdown.notifyToolkitThreadBusy();
- if (!startToolkitThread(this)) {
- Thread toolkitThread = new Thread(this, "AWT-Windows");
+ // Find a root TG and attach Appkit thread to it
+ ThreadGroup rootTG = AccessController.doPrivileged(
+ (PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);
+ if (!startToolkitThread(this, rootTG)) {
+ Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows");
toolkitThread.setDaemon(true);
toolkitThread.start();
}
@@ -268,32 +272,21 @@
}
private final void registerShutdownHook() {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- ThreadGroup currentTG =
- Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = currentTG.getParent();
- while (parentTG != null) {
- currentTG = parentTG;
- parentTG = currentTG.getParent();
- }
- Thread shutdown = new Thread(currentTG, new Runnable() {
- @Override
- public void run() {
- shutdown();
- }
- });
- shutdown.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(shutdown);
- return null;
- }
- });
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ Thread shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), this::shutdown);
+ shutdown.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(shutdown);
+ return null;
+ });
}
@Override
public void run() {
- Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ Thread.currentThread().setContextClassLoader(null);
+ return null;
+ });
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
boolean startPump = init();
if (startPump) {
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, 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
@@ -36,8 +36,9 @@
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
-import sun.awt.SunToolkit;
+
import sun.awt.AWTAccessor;
+import sun.misc.ThreadGroupUtils;
import sun.awt.Win32GraphicsConfig;
import sun.awt.windows.WComponentPeer;
import sun.java2d.InvalidPipeException;
@@ -92,21 +93,12 @@
public D3DScreenUpdateManager() {
done = false;
AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
- ThreadGroup currentTG =
- Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = currentTG.getParent();
- while (parentTG != null) {
- currentTG = parentTG;
- parentTG = currentTG.getParent();
- }
- Thread shutdown = new Thread(currentTG, new Runnable() {
- public void run() {
- done = true;
- wakeUpUpdateThread();
- }
- });
+ (PrivilegedAction<Void>) () -> {
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ Thread shutdown = new Thread(rootTG, () -> {
+ done = true;
+ wakeUpUpdateThread();
+ });
shutdown.setContextClassLoader(null);
try {
Runtime.getRuntime().addShutdownHook(shutdown);
@@ -115,7 +107,6 @@
}
return null;
}
- }
);
}
@@ -354,21 +345,17 @@
*/
private synchronized void startUpdateThread() {
if (screenUpdater == null) {
- screenUpdater = (Thread)java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
- ThreadGroup tg =
- Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null; tg = tgn, tgn = tg.getParent());
- Thread t = new Thread(tg, D3DScreenUpdateManager.this,
- "D3D Screen Updater");
+ screenUpdater = AccessController.doPrivileged(
+ (PrivilegedAction<Thread>) () -> {
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ Thread t = new Thread(rootTG,
+ D3DScreenUpdateManager.this,
+ "D3D Screen Updater");
// REMIND: should it be higher?
t.setPriority(Thread.NORM_PRIORITY + 2);
t.setDaemon(true);
return t;
- }
- });
+ });
screenUpdater.start();
} else {
wakeUpUpdateThread();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/net/www/content-types.properties Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,276 @@
+#sun.net.www MIME content-types table
+#
+# Property fields:
+#
+# <description> ::= 'description' '=' <descriptive string>
+# <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
+# <image> ::= 'icon' '=' <filename of icon image>
+# <action> ::= 'browser' | 'application' | 'save' | 'unknown'
+# <application> ::= 'application' '=' <command line template>
+#
+
+#
+# The "we don't know anything about this data" type(s).
+# Used internally to mark unrecognized types.
+#
+content/unknown: description=Unknown Content
+unknown/unknown: description=Unknown Data Type
+
+#
+# The template we should use for temporary files when launching an application
+# to view a document of given type.
+#
+temp.file.template: c:\\temp\\%s
+
+#
+# The "real" types.
+#
+application/octet-stream: \
+ description=Generic Binary Stream;\
+ file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe,.zip,.gz
+
+application/oda: \
+ description=ODA Document;\
+ file_extensions=.oda
+
+application/pdf: \
+ description=Adobe PDF Format;\
+ file_extensions=.pdf
+
+application/postscript: \
+ description=Postscript File;\
+ file_extensions=.eps,.ai,.ps;\
+ icon=ps
+
+application/rtf: \
+ description=Wordpad Document;\
+ file_extensions=.rtf;\
+ action=application;\
+ application=wordpad.exe %s
+
+application/x-dvi: \
+ description=TeX DVI File;\
+ file_extensions=.dvi
+
+application/x-hdf: \
+ description=Hierarchical Data Format;\
+ file_extensions=.hdf;\
+ action=save
+
+application/x-latex: \
+ description=LaTeX Source;\
+ file_extensions=.latex
+
+application/x-netcdf: \
+ description=Unidata netCDF Data Format;\
+ file_extensions=.nc,.cdf;\
+ action=save
+
+application/x-tex: \
+ description=TeX Source;\
+ file_extensions=.tex
+
+application/x-texinfo: \
+ description=Gnu Texinfo;\
+ file_extensions=.texinfo,.texi
+
+application/x-troff: \
+ description=Troff Source;\
+ file_extensions=.t,.tr,.roff
+
+application/x-troff-man: \
+ description=Troff Manpage Source;\
+ file_extensions=.man
+
+application/x-troff-me: \
+ description=Troff ME Macros;\
+ file_extensions=.me
+
+application/x-troff-ms: \
+ description=Troff MS Macros;\
+ file_extensions=.ms
+
+application/x-wais-source: \
+ description=Wais Source;\
+ file_extensions=.src,.wsrc
+
+application/zip: \
+ description=Zip File;\
+ file_extensions=.zip;\
+ icon=zip;\
+ action=save
+
+application/x-bcpio: \
+ description=Old Binary CPIO Archive;\
+ file_extensions=.bcpio;\
+ action=save
+
+application/x-cpio: \
+ description=Unix CPIO Archive;\
+ file_extensions=.cpio;\
+ action=save
+
+application/x-gtar: \
+ description=Gnu Tar Archive;\
+ file_extensions=.gtar;\
+ icon=tar;\
+ action=save
+
+application/x-shar: \
+ description=Shell Archive;\
+ file_extensions=.sh,.shar;\
+ action=save
+
+application/x-sv4cpio: \
+ description=SVR4 CPIO Archive;\
+ file_extensions=.sv4cpio;\
+ action=save
+
+application/x-sv4crc: \
+ description=SVR4 CPIO with CRC;\
+ file_extensions=.sv4crc;\
+ action=save
+
+application/x-tar: \
+ description=Tar Archive;\
+ file_extensions=.tar;\
+ icon=tar;\
+ action=save
+
+application/x-ustar: \
+ description=US Tar Archive;\
+ file_extensions=.ustar;\
+ action=save
+
+audio/basic: \
+ description=Basic Audio;\
+ file_extensions=.snd,.au;\
+ icon=audio
+
+audio/x-aiff: \
+ description=Audio Interchange Format File;\
+ file_extensions=.aifc,.aif,.aiff;\
+ icon=aiff
+
+audio/x-wav: \
+ description=Wav Audio;\
+ file_extensions=.wav;\
+ icon=wav;\
+ action=application;\
+ application=mplayer.exe %s
+
+image/gif: \
+ description=GIF Image;\
+ file_extensions=.gif;\
+ icon=gif;\
+ action=browser
+
+image/ief: \
+ description=Image Exchange Format;\
+ file_extensions=.ief
+
+image/jpeg: \
+ description=JPEG Image;\
+ file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+ icon=jpeg;\
+ action=browser
+
+image/tiff: \
+ description=TIFF Image;\
+ file_extensions=.tif,.tiff;\
+ icon=tiff
+
+image/vnd.fpx: \
+ description=FlashPix Image;\
+ file_extensions=.fpx,.fpix
+
+image/x-cmu-rast: \
+ description=CMU Raster Image;\
+ file_extensions=.ras
+
+image/x-portable-anymap: \
+ description=PBM Anymap Image;\
+ file_extensions=.pnm
+
+image/x-portable-bitmap: \
+ description=PBM Bitmap Image;\
+ file_extensions=.pbm
+
+image/x-portable-graymap: \
+ description=PBM Graymap Image;\
+ file_extensions=.pgm
+
+image/x-portable-pixmap: \
+ description=PBM Pixmap Image;\
+ file_extensions=.ppm
+
+image/x-rgb: \
+ description=RGB Image;\
+ file_extensions=.rgb
+
+image/x-xbitmap: \
+ description=X Bitmap Image;\
+ file_extensions=.xbm,.xpm
+
+image/x-xwindowdump: \
+ description=X Window Dump Image;\
+ file_extensions=.xwd
+
+image/png: \
+ description=PNG Image;\
+ file_extensions=.png;\
+ icon=png;\
+ action=browser
+
+image/bmp: \
+ description=Bitmap Image;\
+ file_extensions=.bmp;
+
+text/html: \
+ description=HTML Document;\
+ file_extensions=.htm,.html;\
+ icon=html
+
+text/plain: \
+ description=Plain Text;\
+ file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
+ icon=text;\
+ action=browser
+
+text/tab-separated-values: \
+ description=Tab Separated Values Text;\
+ file_extensions=.tsv
+
+text/x-setext: \
+ description=Structure Enhanced Text;\
+ file_extensions=.etx
+
+video/mpeg: \
+ description=MPEG Video Clip;\
+ file_extensions=.mpg,.mpe,.mpeg;\
+ icon=mpeg
+
+video/quicktime: \
+ description=QuickTime Video Clip;\
+ file_extensions=.mov,.qt
+
+application/x-troff-msvideo: \
+ description=AVI Video;\
+ file_extensions=.avi;\
+ icon=avi;\
+ action=application;\
+ application=mplayer.exe %s
+
+video/x-sgi-movie: \
+ description=SGI Movie;\
+ file_extensions=.movie,.mv
+
+message/rfc822: \
+ description=Internet Email Message;\
+ file_extensions=.mime
+
+application/xml: \
+ description=XML document;\
+ file_extensions=.xml
+
+
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Wed Apr 16 10:53:10 2014 -0700
@@ -61,7 +61,7 @@
this.followLinks = followLinks;
}
- // permision check
+ // permission check
private void checkAccess(WindowsPath file,
boolean checkRead,
boolean checkWrite)
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Wed Apr 16 10:53:10 2014 -0700
@@ -94,7 +94,7 @@
public static final int ERROR_NOT_READY = 21;
public static final int ERROR_SHARING_VIOLATION = 32;
public static final int ERROR_FILE_EXISTS = 80;
- public static final int ERROR_INVALID_PARAMATER = 87;
+ public static final int ERROR_INVALID_PARAMETER = 87;
public static final int ERROR_DISK_FULL = 112;
public static final int ERROR_INSUFFICIENT_BUFFER = 122;
public static final int ERROR_INVALID_LEVEL = 124;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Wed Apr 16 10:53:10 2014 -0700
@@ -98,9 +98,9 @@
lastAccessTime,
lastWriteTime);
} catch (WindowsException x) {
- // If ERROR_INVALID_PARAMATER is returned and the volume is
+ // If ERROR_INVALID_PARAMETER is returned and the volume is
// FAT then adjust to the FAT epoch and retry.
- if (followLinks && x.lastError() == ERROR_INVALID_PARAMATER) {
+ if (followLinks && x.lastError() == ERROR_INVALID_PARAMETER) {
try {
if (WindowsFileStore.create(file).type().equals("FAT")) {
SetFileTime(handle,
@@ -157,7 +157,7 @@
private static final String HIDDEN_NAME = "hidden";
private static final String ATTRIBUTES_NAME = "attributes";
- // the names of the DOS attribtues (includes basic)
+ // the names of the DOS attributes (includes basic)
static final Set<String> dosAttributeNames =
Util.newSet(basicAttributeNames,
READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME, ATTRIBUTES_NAME);
@@ -223,7 +223,7 @@
{
file.checkWrite();
- // GetFileAttribtues & SetFileAttributes do not follow links so when
+ // GetFileAttributes & SetFileAttributes do not follow links so when
// following links we need the final target
String path = WindowsLinkSupport.getFinalPath(file, followLinks);
try {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Wed Apr 16 10:53:10 2014 -0700
@@ -384,7 +384,7 @@
file.getPathForExceptionMessage(), null,
"Permissions does not allow requested access");
- // for write access we neeed to check if the DOS readonly attribute
+ // for write access we need to check if the DOS readonly attribute
// and if the volume is read-only
if (w) {
try {
@@ -553,7 +553,7 @@
}
/*
- * Windows treates symbolic links to directories differently than it
+ * Windows treats symbolic links to directories differently than it
* does to other file types. For that reason we need to check if the
* target is a directory (or a directory junction).
*/
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Wed Apr 16 10:53:10 2014 -0700
@@ -917,7 +917,7 @@
}
}
private static native void CreateHardLink0(long newFileBuffer,
- long existingFiletBuffer) throws WindowsException;
+ long existingFileBuffer) throws WindowsException;
/**
* GetFullPathName(
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Wed Apr 16 10:53:10 2014 -0700
@@ -133,7 +133,7 @@
/**
* Special implementation with attached/cached attributes (used to quicken
- * file tree traveral)
+ * file tree traversal)
*/
private static class WindowsPathWithAttributes
extends WindowsPath implements BasicFileAttributesHolder
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java Wed Apr 16 10:53:10 2014 -0700
@@ -129,11 +129,11 @@
int genericRead, int genericWrite, int genericExecute, int genericAll)
throws WindowsException
{
- int privilegies = TOKEN_QUERY;
- long hToken = OpenThreadToken(GetCurrentThread(), privilegies, false);
+ int privileges = TOKEN_QUERY;
+ long hToken = OpenThreadToken(GetCurrentThread(), privileges, false);
if (hToken == 0L && processTokenWithDuplicateAccess != 0L)
hToken = DuplicateTokenEx(processTokenWithDuplicateAccess,
- privilegies);
+ privileges);
boolean hasRight = false;
if (hToken != 0L) {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java Wed Apr 16 10:53:10 2014 -0700
@@ -200,7 +200,7 @@
public List<String> list() throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), true, false);
- // use stream APIs on Windwos Server 2003 and newer
+ // use stream APIs on Windows Server 2003 and newer
if (file.getFileSystem().supportsStreamEnumeration()) {
return listUsingStreamEnumeration();
} else {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Wed Apr 16 10:53:10 2014 -0700
@@ -556,7 +556,7 @@
// ReadDirectoryChangesW failed
criticalError = true;
} else {
- // ERROR_MORE_DATA is a warning about incomplite
+ // ERROR_MORE_DATA is a warning about incomplete
// data transfer over TCP/UDP stack. For the case
// [messageSize] is zero in the most of cases.
--- a/jdk/src/windows/lib/content-types.properties Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-# <description> ::= 'description' '=' <descriptive string>
-# <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-# <image> ::= 'icon' '=' <filename of icon image>
-# <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-# <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: c:\\temp\\%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
- description=Generic Binary Stream;\
- file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe,.zip,.gz
-
-application/oda: \
- description=ODA Document;\
- file_extensions=.oda
-
-application/pdf: \
- description=Adobe PDF Format;\
- file_extensions=.pdf
-
-application/postscript: \
- description=Postscript File;\
- file_extensions=.eps,.ai,.ps;\
- icon=ps
-
-application/rtf: \
- description=Wordpad Document;\
- file_extensions=.rtf;\
- action=application;\
- application=wordpad.exe %s
-
-application/x-dvi: \
- description=TeX DVI File;\
- file_extensions=.dvi
-
-application/x-hdf: \
- description=Hierarchical Data Format;\
- file_extensions=.hdf;\
- action=save
-
-application/x-latex: \
- description=LaTeX Source;\
- file_extensions=.latex
-
-application/x-netcdf: \
- description=Unidata netCDF Data Format;\
- file_extensions=.nc,.cdf;\
- action=save
-
-application/x-tex: \
- description=TeX Source;\
- file_extensions=.tex
-
-application/x-texinfo: \
- description=Gnu Texinfo;\
- file_extensions=.texinfo,.texi
-
-application/x-troff: \
- description=Troff Source;\
- file_extensions=.t,.tr,.roff
-
-application/x-troff-man: \
- description=Troff Manpage Source;\
- file_extensions=.man
-
-application/x-troff-me: \
- description=Troff ME Macros;\
- file_extensions=.me
-
-application/x-troff-ms: \
- description=Troff MS Macros;\
- file_extensions=.ms
-
-application/x-wais-source: \
- description=Wais Source;\
- file_extensions=.src,.wsrc
-
-application/zip: \
- description=Zip File;\
- file_extensions=.zip;\
- icon=zip;\
- action=save
-
-application/x-bcpio: \
- description=Old Binary CPIO Archive;\
- file_extensions=.bcpio;\
- action=save
-
-application/x-cpio: \
- description=Unix CPIO Archive;\
- file_extensions=.cpio;\
- action=save
-
-application/x-gtar: \
- description=Gnu Tar Archive;\
- file_extensions=.gtar;\
- icon=tar;\
- action=save
-
-application/x-shar: \
- description=Shell Archive;\
- file_extensions=.sh,.shar;\
- action=save
-
-application/x-sv4cpio: \
- description=SVR4 CPIO Archive;\
- file_extensions=.sv4cpio;\
- action=save
-
-application/x-sv4crc: \
- description=SVR4 CPIO with CRC;\
- file_extensions=.sv4crc;\
- action=save
-
-application/x-tar: \
- description=Tar Archive;\
- file_extensions=.tar;\
- icon=tar;\
- action=save
-
-application/x-ustar: \
- description=US Tar Archive;\
- file_extensions=.ustar;\
- action=save
-
-audio/basic: \
- description=Basic Audio;\
- file_extensions=.snd,.au;\
- icon=audio
-
-audio/x-aiff: \
- description=Audio Interchange Format File;\
- file_extensions=.aifc,.aif,.aiff;\
- icon=aiff
-
-audio/x-wav: \
- description=Wav Audio;\
- file_extensions=.wav;\
- icon=wav;\
- action=application;\
- application=mplayer.exe %s
-
-image/gif: \
- description=GIF Image;\
- file_extensions=.gif;\
- icon=gif;\
- action=browser
-
-image/ief: \
- description=Image Exchange Format;\
- file_extensions=.ief
-
-image/jpeg: \
- description=JPEG Image;\
- file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
- icon=jpeg;\
- action=browser
-
-image/tiff: \
- description=TIFF Image;\
- file_extensions=.tif,.tiff;\
- icon=tiff
-
-image/vnd.fpx: \
- description=FlashPix Image;\
- file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
- description=CMU Raster Image;\
- file_extensions=.ras
-
-image/x-portable-anymap: \
- description=PBM Anymap Image;\
- file_extensions=.pnm
-
-image/x-portable-bitmap: \
- description=PBM Bitmap Image;\
- file_extensions=.pbm
-
-image/x-portable-graymap: \
- description=PBM Graymap Image;\
- file_extensions=.pgm
-
-image/x-portable-pixmap: \
- description=PBM Pixmap Image;\
- file_extensions=.ppm
-
-image/x-rgb: \
- description=RGB Image;\
- file_extensions=.rgb
-
-image/x-xbitmap: \
- description=X Bitmap Image;\
- file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
- description=X Window Dump Image;\
- file_extensions=.xwd
-
-image/png: \
- description=PNG Image;\
- file_extensions=.png;\
- icon=png;\
- action=browser
-
-image/bmp: \
- description=Bitmap Image;\
- file_extensions=.bmp;
-
-text/html: \
- description=HTML Document;\
- file_extensions=.htm,.html;\
- icon=html
-
-text/plain: \
- description=Plain Text;\
- file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
- icon=text;\
- action=browser
-
-text/tab-separated-values: \
- description=Tab Separated Values Text;\
- file_extensions=.tsv
-
-text/x-setext: \
- description=Structure Enhanced Text;\
- file_extensions=.etx
-
-video/mpeg: \
- description=MPEG Video Clip;\
- file_extensions=.mpg,.mpe,.mpeg;\
- icon=mpeg
-
-video/quicktime: \
- description=QuickTime Video Clip;\
- file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
- description=AVI Video;\
- file_extensions=.avi;\
- icon=avi;\
- action=application;\
- application=mplayer.exe %s
-
-video/x-sgi-movie: \
- description=SGI Movie;\
- file_extensions=.movie,.mv
-
-message/rfc822: \
- description=Internet Email Message;\
- file_extensions=.mime
-
-application/xml: \
- description=XML document;\
- file_extensions=.xml
-
-
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -320,13 +320,18 @@
// current language ID (returned from 'getJavaIDFromLangID') is in
// ASCII encoding, so we use 'GetStringUTFChars' to retrieve requested
// language ID from the 'localeString' object.
- const char * current = getJavaIDFromLangID(AwtComponent::GetInputLanguage());
jboolean isCopy;
const char * requested = env->GetStringUTFChars(localeString, &isCopy);
- if ((current != NULL) && (strcmp(current, requested) == 0)) {
- env->ReleaseStringUTFChars(localeString, requested);
+ CHECK_NULL_RETURN(requested, JNI_FALSE);
+
+ const char * current = getJavaIDFromLangID(AwtComponent::GetInputLanguage());
+ if (current != NULL) {
+ if (strcmp(current, requested) == 0) {
+ env->ReleaseStringUTFChars(localeString, requested);
+ free((void *)current);
+ return JNI_TRUE;
+ }
free((void *)current);
- return JNI_TRUE;
}
// get list of available HKLs. Adding the user's preferred layout on top of the layout
@@ -334,7 +339,10 @@
// looking up suitable layout.
int layoutCount = ::GetKeyboardLayoutList(0, NULL) + 1; // +1 for user's preferred HKL
HKL FAR * hKLList = (HKL FAR *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(HKL), layoutCount);
- DASSERT(!safe_ExceptionOccurred(env));
+ if (hKLList == NULL) {
+ env->ReleaseStringUTFChars(localeString, requested);
+ return JNI_FALSE;
+ }
::GetKeyboardLayoutList(layoutCount - 1, &(hKLList[1]));
hKLList[0] = getDefaultKeyboardLayout(); // put user's preferred layout on top of the list
@@ -342,20 +350,23 @@
jboolean retValue = JNI_FALSE;
for (int i = 0; i < layoutCount; i++) {
const char * supported = getJavaIDFromLangID(LOWORD(hKLList[i]));
- if ((supported != NULL) && (strcmp(supported, requested) == 0)) {
- // use special message to call ActivateKeyboardLayout() in main thread.
- if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) {
- //also need to change the same keyboard layout for the Java AWT-EventQueue thread
- AwtToolkit::activateKeyboardLayout(hKLList[i]);
- retValue = JNI_TRUE;
+ if (supported != NULL) {
+ if (strcmp(supported, requested) == 0) {
+ // use special message to call ActivateKeyboardLayout() in main thread.
+ if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) {
+ //also need to change the same keyboard layout for the Java AWT-EventQueue thread
+ AwtToolkit::activateKeyboardLayout(hKLList[i]);
+ retValue = JNI_TRUE;
+ }
+ free((void *)supported);
+ break;
}
- break;
+ free((void *)supported);
}
}
env->ReleaseStringUTFChars(localeString, requested);
free(hKLList);
- free((void *)current);
return retValue;
CATCH_BAD_ALLOC_RET(JNI_FALSE);
@@ -445,7 +456,7 @@
// get list of available HKLs
int layoutCount = ::GetKeyboardLayoutList(0, NULL);
HKL FAR * hKLList = (HKL FAR *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(HKL), layoutCount);
- DASSERT(!safe_ExceptionOccurred(env));
+ CHECK_NULL_RETURN(hKLList, NULL);
::GetKeyboardLayoutList(layoutCount, hKLList);
// get list of Java locale names while getting rid of duplicates
@@ -453,8 +464,13 @@
int destIndex = 0;
int javaLocaleNameCount = 0;
int current = 0;
+
const char ** javaLocaleNames = (const char **)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(char *), layoutCount);
- DASSERT(!safe_ExceptionOccurred(env));
+ if (javaLocaleNames == NULL) {
+ free(hKLList);
+ return NULL;
+ }
+
for (; srcIndex < layoutCount; srcIndex++) {
const char * srcLocaleName = getJavaIDFromLangID(LOWORD(hKLList[srcIndex]));
@@ -477,18 +493,33 @@
}
}
+ jobjectArray locales = NULL;
// convert it to an array of Java locale objects
jclass localeClass = env->FindClass("java/util/Locale");
- jobjectArray locales = env->NewObjectArray(javaLocaleNameCount, localeClass, NULL);
+ if (localeClass != NULL) {
+ locales = env->NewObjectArray(javaLocaleNameCount, localeClass, NULL);
+ if (locales != NULL) {
+
+ for (current = 0; current < javaLocaleNameCount; current++) {
+ jobject obj = CreateLocaleObject(env, javaLocaleNames[current]);
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(locales);
+ locales = NULL;
+ break;
+ }
+ env->SetObjectArrayElement(locales,
+ current,
+ obj);
+ }
+
+ }
+ env->DeleteLocalRef(localeClass);
+ }
+
for (current = 0; current < javaLocaleNameCount; current++) {
- env->SetObjectArrayElement(locales,
- current,
- CreateLocaleObject(env, javaLocaleNames[current]));
free((void *)javaLocaleNames[current]);
}
- DASSERT(!safe_ExceptionOccurred(env));
- env->DeleteLocalRef(localeClass);
free(hKLList);
free(javaLocaleNames);
return locales;
@@ -542,6 +573,7 @@
// create Locale object
jobject langtagObj = env->NewStringUTF(name);
+ CHECK_NULL_RETURN(langtagObj, NULL);
jobject localeObj = JNU_CallStaticMethodByName(env,
NULL,
"java/util/Locale",
--- a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, 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
@@ -152,6 +152,9 @@
if (dw == ERROR_OUTOFMEMORY)
{
jstring errorMsg = JNU_NewStringPlatform(env, L"too many menu handles");
+ if (errorMsg == NULL) {
+ throw std::bad_alloc();
+ }
createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
"(Ljava/lang/String;)V",
errorMsg);
@@ -164,16 +167,19 @@
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&buf, 0, NULL);
jstring s = JNU_NewStringPlatform(env, buf);
+ if (s == NULL) {
+ throw std::bad_alloc();
+ }
createError = JNU_NewObjectByName(env, "java/lang/InternalError",
"(Ljava/lang/String;)V", s);
LocalFree(buf);
env->DeleteLocalRef(s);
}
+ if (createError == NULL) {
+ throw std::bad_alloc();
+ }
env->SetObjectField(self, AwtObject::createErrorID, createError);
- if (createError != NULL)
- {
- env->DeleteLocalRef(createError);
- }
+ env->DeleteLocalRef(createError);
return FALSE;
}
return TRUE;
@@ -238,12 +244,18 @@
jobject self = GetPeer(env);
jobject target = env->GetObjectField(self, AwtObject::targetID);
jobject font = JNU_CallMethodByName(env, 0, target, "getFont_NoClientCode", "()Ljava/awt/Font;").l;
+ env->DeleteLocalRef(target);
+ if (env->ExceptionCheck()) {
+ throw std::bad_alloc();
+ }
if (font == NULL) {
font = env->NewLocalRef(GetDefaultFont(env));
+ if (env->ExceptionCheck()) {
+ throw std::bad_alloc();
+ }
}
- env->DeleteLocalRef(target);
return font;
}
@@ -251,13 +263,22 @@
AwtMenuItem::GetDefaultFont(JNIEnv *env) {
if (AwtMenuItem::systemFont == NULL) {
jclass cls = env->FindClass("sun/awt/windows/WMenuItemPeer");
- DASSERT(cls != NULL);
+ if (cls == NULL) {
+ throw std::bad_alloc();
+ }
AwtMenuItem::systemFont =
env->CallStaticObjectMethod(cls, AwtMenuItem::getDefaultFontMID);
- DASSERT(AwtMenuItem::systemFont);
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(cls);
+ throw std::bad_alloc();
+ }
AwtMenuItem::systemFont = env->NewGlobalRef(AwtMenuItem::systemFont);
+ if (systemFont == NULL) {
+ env->DeleteLocalRef(cls);
+ throw std::bad_alloc();
+ }
}
return AwtMenuItem::systemFont;
}
@@ -284,8 +305,19 @@
DWORD crBack,crText;
HBRUSH hbrBack;
- jobject font = GetFont(env);
+ jobject font;
+ try {
+ font = GetFont(env);
+ } catch (std::bad_alloc&) {
+ env->DeleteLocalRef(target);
+ throw;
+ }
+
jstring text = GetJavaString(env);
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(target);
+ throw std::bad_alloc();
+ }
size = AwtFont::getMFStringSize(hDC, font, text);
/* 4700350: If the font size is taller than the menubar, change to the
@@ -294,7 +326,13 @@
*/
if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) {
env->DeleteLocalRef(font);
- font = env->NewLocalRef(GetDefaultFont(env));
+ try {
+ font = env->NewLocalRef(GetDefaultFont(env));
+ } catch (std::bad_alloc&) {
+ env->DeleteLocalRef(target);
+ env->DeleteLocalRef(text);
+ throw;
+ }
size = AwtFont::getMFStringSize(hDC, font, text);
}
@@ -452,6 +490,10 @@
/* font is a java.awt.Font */
jobject font = GetFont(env);
jstring text = GetJavaString(env);
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(font);
+ throw std::bad_alloc();
+ }
SIZE size = AwtFont::getMFStringSize(hDC, font, text);
/* 4700350: If the font size is taller than the menubar, change to the
@@ -459,7 +501,14 @@
* client area. -bchristi
*/
if (IsTopMenu() && size.cy > ::GetSystemMetrics(SM_CYMENU)) {
- jobject defFont = GetDefaultFont(env);
+ jobject defFont;
+ try {
+ defFont = GetDefaultFont(env);
+ } catch (std::bad_alloc&) {
+ env->DeleteLocalRef(text);
+ env->DeleteLocalRef(font);
+ throw;
+ }
env->DeleteLocalRef(font);
font = env->NewLocalRef(defFont);
size = AwtFont::getMFStringSize(hDC, font, text);
@@ -468,13 +517,31 @@
jstring fontName =
(jstring)JNU_CallMethodByName(env, 0,font, "getName",
"()Ljava/lang/String;").l;
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(text);
+ env->DeleteLocalRef(font);
+ throw std::bad_alloc();
+ }
+
/* fontMetrics is a Hsun_awt_windows_WFontMetrics */
jobject fontMetrics = GetFontMetrics(env, font);
-
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(text);
+ env->DeleteLocalRef(font);
+ env->DeleteLocalRef(fontName);
+ throw std::bad_alloc();
+ }
// int height = env->GetIntField(fontMetrics, AwtFont::heightID);
int height = (jint)JNU_CallMethodByName(env, 0, fontMetrics, "getHeight",
"()I").i;
+ if (env->ExceptionCheck()) {
+ env->DeleteLocalRef(text);
+ env->DeleteLocalRef(font);
+ env->DeleteLocalRef(fontName);
+ env->DeleteLocalRef(fontMetrics);
+ throw std::bad_alloc();
+ }
measureInfo.itemHeight = height;
measureInfo.itemHeight += measureInfo.itemHeight/3;
@@ -520,10 +587,14 @@
if (env->PushLocalFrame(2) < 0)
return NULL;
jclass cls = env->FindClass("java/awt/Toolkit");
+ CHECK_NULL_RETURN(cls, NULL);
jobject toolkitLocal =
env->CallStaticObjectMethod(cls, AwtToolkit::getDefaultToolkitMID);
+ env->DeleteLocalRef(cls);
+ CHECK_NULL_RETURN(toolkitLocal, NULL);
toolkit = env->NewGlobalRef(toolkitLocal);
- DASSERT(!safe_ExceptionOccurred(env));
+ env->DeleteLocalRef(toolkitLocal);
+ CHECK_NULL_RETURN(toolkit, NULL);
env->PopLocalFrame(0);
}
/*
@@ -739,6 +810,10 @@
{
empty = JNU_NewStringPlatform(env, TEXT(""));
}
+ if (env->ExceptionCheck()) {
+ badAlloc = 1;
+ goto ret;
+ }
LPCTSTR labelPtr;
if (empty != NULL)
{
@@ -846,10 +921,9 @@
TRY;
AwtMenuItem::fontID = env->GetFieldID(cls, "font", "Ljava/awt/Font;");
+ CHECK_NULL(AwtMenuItem::fontID);
AwtMenuItem::appContextID = env->GetFieldID(cls, "appContext", "Lsun/awt/AppContext;");
- DASSERT(AwtMenuItem::fontID != NULL);
-
CATCH_BAD_ALLOC;
}
@@ -868,11 +942,9 @@
TRY;
AwtMenuItem::labelID = env->GetFieldID(cls, "label", "Ljava/lang/String;");
+ CHECK_NULL(AwtMenuItem::labelID);
AwtMenuItem::enabledID = env->GetFieldID(cls, "enabled", "Z");
- DASSERT(AwtMenuItem::labelID != NULL);
- DASSERT(AwtMenuItem::enabledID != NULL);
-
CATCH_BAD_ALLOC;
}
@@ -892,8 +964,6 @@
AwtMenuItem::stateID = env->GetFieldID(cls, "state", "Z");
- DASSERT(AwtMenuItem::stateID != NULL);
-
CATCH_BAD_ALLOC;
}
@@ -917,15 +987,13 @@
TRY;
AwtMenuItem::isCheckboxID = env->GetFieldID(cls, "isCheckbox", "Z");
+ CHECK_NULL(AwtMenuItem::isCheckboxID);
AwtMenuItem::shortcutLabelID = env->GetFieldID(cls, "shortcutLabel",
"Ljava/lang/String;");
+ CHECK_NULL(AwtMenuItem::shortcutLabelID);
AwtMenuItem::getDefaultFontMID =
env->GetStaticMethodID(cls, "getDefaultFont", "()Ljava/awt/Font;");
- DASSERT(AwtMenuItem::isCheckboxID != NULL);
- DASSERT(AwtMenuItem::shortcutLabelID != NULL);
- DASSERT(AwtMenuItem::getDefaultFontMID != NULL);
-
CATCH_BAD_ALLOC;
}
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Apr 16 10:53:10 2014 -0700
@@ -351,6 +351,7 @@
HANDLE hCompleted;
jobject thread;
+ jobject threadGroup;
};
void ToolkitThreadProc(void *param)
@@ -363,7 +364,7 @@
JavaVMAttachArgs attachArgs;
attachArgs.version = JNI_VERSION_1_2;
attachArgs.name = "AWT-Windows";
- attachArgs.group = NULL;
+ attachArgs.group = data->threadGroup;
jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
if (res < 0) {
@@ -402,17 +403,18 @@
/*
* Class: sun_awt_windows_WToolkit
* Method: startToolkitThread
- * Signature: (Ljava/lang/Runnable;)Z
+ * Signature: (Ljava/lang/Runnable;Ljava/lang/ThreadGroup)Z
*/
JNIEXPORT jboolean JNICALL
-Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread)
+Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread, jobject threadGroup)
{
AwtToolkit& tk = AwtToolkit::GetInstance();
ToolkitThreadProc_Data data;
data.result = false;
data.thread = env->NewGlobalRef(thread);
- if (data.thread == NULL) {
+ data.threadGroup = env->NewGlobalRef(threadGroup);
+ if (data.thread == NULL || data.threadGroup == NULL) {
return JNI_FALSE;
}
data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -430,6 +432,7 @@
::CloseHandle(data.hCompleted);
env->DeleteGlobalRef(data.thread);
+ env->DeleteGlobalRef(data.threadGroup);
return result ? JNI_TRUE : JNI_FALSE;
}
--- a/jdk/test/demo/zipfs/Basic.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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("jar")) {
- found = true;
- break;
- }
- }
- if (!found)
- throw new RuntimeException("'jar' provider not installed");
-
- // Test: FileSystems#newFileSystem(Path)
- Map<String,?> env = new HashMap<String,Object>();
- FileSystems.newFileSystem(zipfile, null).close();
-
- // Test: FileSystems#newFileSystem(URI)
- URI uri = new URI("jar", zipfile.toUri().toString(), null);
- 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;
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
- for (Path entry: stream) {
- found = entry.toString().equals("/META-INF/");
- if (found) break;
- }
- }
-
- 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 (Files.exists(source)) {
- Path target = Paths.get(source.getFileName().toString());
- Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
- try {
- long s1 = Files.readAttributes(source, BasicFileAttributes.class).size();
- long s2 = Files.readAttributes(target, BasicFileAttributes.class).size();
- if (s2 != s1)
- throw new RuntimeException("target size != source size");
- } finally {
- Files.delete(target);
- }
- }
-
- // Test: FileStore
- FileStore store = Files.getFileStore(fs.getPath("/"));
- 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.provider().checkAccess(fs.getPath("/missing"), 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.getFileName() != null) {
- indent();
- System.out.println(dir.getFileName() + "/");
- indent++;
- }
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult visitFile(Path file,
- BasicFileAttributes attrs)
- {
- indent();
- System.out.print(file.getFileName());
- 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.getFileName() != null)
- indent--;
- return FileVisitResult.CONTINUE;
- }
- }
-}
--- a/jdk/test/demo/zipfs/PathOps.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.getFileName(), 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 isSameFile(String target) {
- try {
- out.println("check two paths are same");
- checkPath();
- check(Files.isSameFile(path, test(target).path()), true);
- } catch (IOException ioe) {
- fail();
- }
- 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("/");
- test("/")
- .starts("/")
- .notStarts("/foo");
- test("/foo")
- .starts("/")
- .starts("/foo")
- .notStarts("/f")
- .notStarts("");
- test("/foo/bar")
- .starts("/")
- .starts("/foo")
- .starts("/foo/")
- .starts("/foo/bar")
- .notStarts("/f")
- .notStarts("foo")
- .notStarts("foo/bar")
- .notStarts("");
- test("foo")
- .starts("foo")
- .notStarts("f");
- test("foo/bar")
- .starts("foo")
- .starts("foo/")
- .starts("foo/bar")
- .notStarts("f")
- .notStarts("/foo")
- .notStarts("/foo/bar");
-
- // endsWith
- test("")
- .ends("")
- .notEnds("/");
- test("/")
- .ends("/")
- .notEnds("foo")
- .notEnds("/foo");
- test("/foo")
- .ends("foo")
- .ends("/foo")
- .notEnds("/");
- test("/foo/bar")
- .ends("bar")
- .ends("foo/bar")
- .ends("foo/bar/")
- .ends("/foo/bar")
- .notEnds("/bar");
- test("/foo/bar/")
- .ends("bar")
- .ends("foo/bar")
- .ends("foo/bar/")
- .ends("/foo/bar")
- .notEnds("/bar");
- test("foo")
- .ends("foo");
- test("foo/bar")
- .ends("bar")
- .ends("bar/")
- .ends("foo/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();
- test("")
- .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", "")
- .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("");
- test("..")
- .normalize("..");
- test("/..")
- .normalize("/");
- test("/../..")
- .normalize("/");
- test("foo/.")
- .normalize("foo");
- test("./foo")
- .normalize("foo");
- test("foo/..")
- .normalize("");
- 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");
- test("/./.")
- .normalize("/");
- test("/.")
- .normalize("/");
- test("/./abc")
- .normalize("/abc");
- // 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");
-
- // isSameFile
- test("/fileDoesNotExist")
- .isSameFile("/fileDoesNotExist");
- }
-
- 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((Path)null);
- throw new RuntimeException("NullPointerException not thrown");
- } catch (NullPointerException npe) {
- }
-
- try {
- path.endsWith((Path)null);
- throw new RuntimeException("NullPointerException not thrown");
- } catch (NullPointerException npe) {
- }
-
- }
-
- public static void main(String[] args) throws Throwable {
-
- Path zipfile = Paths.get(args[0]);
- fs = FileSystems.newFileSystem(zipfile, null);
- npes();
- doPathOpTests();
- fs.close();
- }
-}
--- a/jdk/test/demo/zipfs/ZFSTests.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 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 7156873
- @summary ZipFileSystem regression tests
- */
-
-
-import java.net.URI;
-import java.nio.file.*;
-import java.util.Map;
-import java.util.HashMap;
-
-public class ZFSTests {
-
- public static void main(String[] args) throws Throwable {
- test7156873();
- }
-
- static void test7156873() throws Throwable {
- String DIRWITHSPACE = "testdir with spaces";
- Path dir = Paths.get(DIRWITHSPACE);
- Path path = Paths.get(DIRWITHSPACE, "file.zip");
- try {
- Files.createDirectory(dir);
- URI uri = URI.create("jar:" + path.toUri());
- Map<String, Object> env = new HashMap<String, Object>();
- env.put("create", "true");
- try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {}
- } finally {
- Files.deleteIfExists(path);
- Files.deleteIfExists(dir);
- }
- }
-}
--- a/jdk/test/demo/zipfs/ZipFSTester.java Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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.spi.*;
-import java.nio.file.attribute.*;
-import java.net.*;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.zip.*;
-
-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 {
-
- try (FileSystem fs = newZipFileSystem(Paths.get(args[0]),
- new HashMap<String, Object>()))
- {
- test0(fs);
- test1(fs);
- test2(fs); // more tests
- testTime(Paths.get(args[0]));
- }
- }
-
- static void test0(FileSystem fs)
- throws Exception
- {
- List<String> list = new LinkedList<>();
- try (ZipFile zf = new ZipFile(fs.toString())) {
- Enumeration<? extends ZipEntry> zes = zf.entries();
- while (zes.hasMoreElements()) {
- list.add(zes.nextElement().getName());
- }
- for (String pname : list) {
- Path path = fs.getPath(pname);
- if (!Files.exists(path))
- throw new RuntimeException("path existence check failed!");
- while ((path = path.getParent()) != null) {
- if (!Files.exists(path))
- throw new RuntimeException("parent existence check failed!");
- }
- }
- }
- }
-
- static void test1(FileSystem fs0)
- 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("create", "true");
- try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
- z2zcopy(fs0, copy, "/", 0);
- }
-
- try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
-
- FileSystemProvider provider = fs.provider();
- // newFileSystem(path...) should not throw exception
- try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){}
- try (FileSystem fsUri = provider.newFileSystem(
- new URI("jar", tmpfsPath.toUri().toString(), null),
- new HashMap<String, Object>()))
- {
- throw new RuntimeException("newFileSystem(uri...) does not throw exception");
- } catch (FileSystemAlreadyExistsException fsaee) {}
-
- // prepare a src
- Path src = getTempPath();
- String tmpName = src.toString();
- OutputStream os = Files.newOutputStream(src);
- byte[] bits = new byte[12345];
- rdm.nextBytes(bits);
- os.write(bits);
- os.close();
-
- try {
- provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
- new HashMap<String, Object>());
- throw new RuntimeException("newFileSystem() opens a directory as zipfs");
- } catch (UnsupportedOperationException uoe) {}
-
- try {
- provider.newFileSystem(src, new HashMap<String, Object>());
- throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
- } catch (UnsupportedOperationException uoe) {}
-
-
- // copyin
- Path dst = getPathWithParents(fs, tmpName);
- Files.copy(src, dst);
- checkEqual(src, dst);
-
- // copy
- Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
- "/efg" + rdm.nextInt(100) + "/foo.class");
- Files.copy(dst, dst2);
- //dst.moveTo(dst2);
- checkEqual(src, dst2);
-
- // delete
- Files.delete(dst);
- if (Files.exists(dst))
- throw new RuntimeException("Failed!");
-
- // moveout
- Path dst3 = Paths.get(tmpName + "_Tmp");
- Files.move(dst2, dst3);
- checkEqual(src, dst3);
- if (Files.exists(dst2))
- throw new RuntimeException("Failed!");
-
- // copyback + move
- Files.copy(dst3, dst);
- Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
- Files.move(dst, dst4);
- checkEqual(src, dst4);
-
- // delete
- Files.delete(dst4);
- if (Files.exists(dst4))
- throw new RuntimeException("Failed!");
- Files.delete(dst3);
- if (Files.exists(dst3))
- throw new RuntimeException("Failed!");
-
- // move (existing entry)
- Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
- if (Files.exists(dst5)) {
- Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
- Files.move(dst5, dst6);
- walk(fs.getPath("/"));
- }
-
- // newInputStream on dir
- Path parent = dst2.getParent();
- try {
- Files.newInputStream(parent);
- 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);
- Files.delete(tmp);
-
- // test channels
- channel(fs, dst);
- Files.delete(dst);
- Files.delete(src);
- } finally {
- if (Files.exists(tmpfsPath))
- Files.delete(tmpfsPath);
- }
- }
-
- static void test2(FileSystem fs) throws Exception {
-
- Path fs1Path = getTempPath();
- Path fs2Path = getTempPath();
- Path fs3Path = getTempPath();
-
- // create a new filesystem, copy everything from fs
- Map<String, Object> env = new HashMap<String, Object>();
- env.put("create", "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 (Files.exists(fs2.getPath(path))) {
- 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);
-
- Files.delete(fs1Path);
- Files.delete(fs2Path);
- Files.delete(fs3Path);
- }
-
- // test file stamp
- static void testTime(Path src) throws Exception {
- BasicFileAttributes attrs = Files
- .getFileAttributeView(src, BasicFileAttributeView.class)
- .readAttributes();
- // create a new filesystem, copy this file into it
- Map<String, Object> env = new HashMap<String, Object>();
- env.put("create", "true");
- Path fsPath = getTempPath();
- FileSystem fs = newZipFileSystem(fsPath, env);
-
- System.out.println("test copy with timestamps...");
- // copyin
- Path dst = getPathWithParents(fs, "me");
- Files.copy(src, dst, COPY_ATTRIBUTES);
- checkEqual(src, dst);
- System.out.println("mtime: " + attrs.lastModifiedTime());
- System.out.println("ctime: " + attrs.creationTime());
- System.out.println("atime: " + attrs.lastAccessTime());
- System.out.println(" ==============>");
- BasicFileAttributes dstAttrs = Files
- .getFileAttributeView(dst, BasicFileAttributeView.class)
- .readAttributes();
- System.out.println("mtime: " + dstAttrs.lastModifiedTime());
- System.out.println("ctime: " + dstAttrs.creationTime());
- System.out.println("atime: " + dstAttrs.lastAccessTime());
-
- // 1-second granularity
- if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) !=
- dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) ||
- attrs.lastAccessTime().to(TimeUnit.SECONDS) !=
- dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
- attrs.creationTime().to(TimeUnit.SECONDS) !=
- dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
- throw new RuntimeException("Timestamp Copy Failed!");
- }
- Files.delete(fsPath);
- }
-
- private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
- throws Exception
- {
- return FileSystems.newFileSystem(
- new URI("jar", path.toUri().toString(), null), 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 (Files.isDirectory(path)) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
- for (Path child : ds)
- list(child, files, dirs);
- }
- 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 (Files.isDirectory(srcPath)) {
- if (!Files.exists(dstPath)) {
- try {
- mkdirs(dstPath);
- } catch (FileAlreadyExistsException x) {}
- }
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
- for (Path child : ds) {
- z2zcopy(src, dst,
- path + (path.endsWith("/")?"":"/") + child.getFileName(),
- method);
- }
- }
- } else {
- try {
- if (Files.exists(dstPath))
- return;
- switch (method) {
- case 0:
- Files.copy(srcPath, 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 (Files.isDirectory(srcPath)) {
- if (!Files.exists(dstPath))
- mkdirs(dstPath);
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
- for (Path child : ds) {
- z2zmove(src, dst,
- path + (path.endsWith("/")?"":"/") + child.getFileName());
- }
- }
- } else {
- //System.out.println("moving..." + path);
- Path parent = dstPath.getParent();
- if (parent != null && Files.notExists(parent))
- mkdirs(parent);
- Files.move(srcPath, 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.getFileName().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 {
- if (Files.exists(path))
- return;
- path = path.toAbsolutePath();
- Path parent = path.getParent();
- if (parent != null) {
- if (Files.notExists(parent))
- mkdirs(parent);
- }
- Files.createDirectory(path);
- }
-
- private static void rmdirs(Path path) throws IOException {
- while (path != null && path.getNameCount() != 0) {
- Files.delete(path);
- 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
- byte[] bufSrc = new byte[8192];
- byte[] bufDst = new byte[8192];
- try (InputStream isSrc = Files.newInputStream(src);
- InputStream isDst = Files.newInputStream(dst))
- {
- 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--;
- }
- }
- }
-
- // channels
- try (SeekableByteChannel chSrc = Files.newByteChannel(src);
- SeekableByteChannel chDst = Files.newByteChannel(dst))
- {
- 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);
-
- 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();
- }
-
- // Check if source read position is at the end
- if (chSrc.position() != chSrc.size()) {
- System.out.printf("src[%s]: size=%d, position=%d%n",
- chSrc.toString(), chSrc.size(), chSrc.position());
- throw new RuntimeException("CHECK FAILED!");
- }
-
- // Check if destination read position is at the end
- if (chDst.position() != chDst.size()) {
- System.out.printf("dst[%s]: size=%d, position=%d%n",
- chDst.toString(), chDst.size(), chDst.position());
- throw new RuntimeException("CHECK FAILED!");
- }
- } catch (IOException x) {
- x.printStackTrace();
- }
- }
-
- 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);
-
- try (FileChannel srcFc = src.getFileSystem()
- .provider()
- .newFileChannel(src, read);
- FileChannel dstFc = dst.getFileSystem()
- .provider()
- .newFileChannel(dst, openwrite))
- {
- ByteBuffer bb = ByteBuffer.allocate(8192);
- while (srcFc.read(bb) >= 0) {
- bb.flip();
- dstFc.write(bb);
- bb.clear();
- }
- }
- }
-
- 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);
-
- try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
- SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
- {
-
- ByteBuffer bb = ByteBuffer.allocate(8192);
- while (srcCh.read(bb) >= 0) {
- bb.flip();
- dstCh.write(bb);
- bb.clear();
- }
-
- // Check if source read position is at the end
- if (srcCh.position() != srcCh.size()) {
- System.out.printf("src[%s]: size=%d, position=%d%n",
- srcCh.toString(), srcCh.size(), srcCh.position());
- throw new RuntimeException("CHECK FAILED!");
- }
-
- // Check if destination write position is at the end
- if (dstCh.position() != dstCh.size()) {
- System.out.printf("dst[%s]: size=%d, position=%d%n",
- dstCh.toString(), dstCh.size(), dstCh.position());
- throw new RuntimeException("CHECK FAILED!");
- }
- }
- }
-
- private static void streamCopy(Path src, Path dst) throws IOException
- {
- byte[] buf = new byte[8192];
- try (InputStream isSrc = Files.newInputStream(src);
- OutputStream osDst = Files.newOutputStream(dst))
- {
- int n = 0;
- while ((n = isSrc.read(buf)) != -1) {
- osDst.write(buf, 0, n);
- }
- }
- }
-
- static void channel(FileSystem fs, Path path)
- throws Exception
- {
- System.out.println("test ByteChannel...");
- Set<OpenOption> read = new HashSet<>();
- read.add(READ);
- int n = 0;
- ByteBuffer bb = null;
- ByteBuffer bb2 = null;
- int N = 120;
-
- try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
- System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
- if (sbc.position() != 0) {
- throw new RuntimeException("CHECK FAILED!");
- }
-
- bb = ByteBuffer.allocate((int)sbc.size());
- n = sbc.read(bb);
- System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n",
- n, sbc.position(), sbc.size());
- if (sbc.position() != sbc.size()) {
- throw new RuntimeException("CHECK FAILED!");
- }
- bb2 = ByteBuffer.allocate((int)sbc.size());
- }
-
- // sbc.position(pos) is not supported in current version
- // try the FileChannel
- try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) {
- sbc.position(N);
- System.out.printf(" sbc[2]: pos=%d, size=%d%n",
- sbc.position(), sbc.size());
- if (sbc.position() != N) {
- throw new RuntimeException("CHECK FAILED!");
- }
- bb2.limit(100);
- n = sbc.read(bb2);
- System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n",
- n, sbc.position(), sbc.size());
- if (n < 0 || sbc.position() != (N + n)) {
- throw new RuntimeException("CHECK FAILED!");
- }
- System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
- N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
- }
- }
-
- // 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 && Files.notExists(parent))
- mkdirs(parent);
- return path;
- }
-}
--- a/jdk/test/demo/zipfs/basic.sh Tue Apr 15 15:28:01 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#
-# Copyright (c) 2009, 2013, 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 7009092 7009085 7015391 7014948 7005986 7017840 7007596
-# 7157656 8002390 7012868 7012856 8015728
-# @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_* | CYGWIN* )
- CLASSPATH="${TESTCLASSES};${ZIPFS}"
- ;;
- * )
- CLASSPATH="${TESTCLASSES}:${ZIPFS}"
- ;;
-esac
-export CLASSPATH
-
-failures=0
-
-go() {
- echo ""
- ${TESTJAVA}/bin/java ${TESTVMOPTS} $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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Toolkit/LoadAWTCrashTest/LoadAWTCrashTest.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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 8031477
+ @summary Crash while awt starting
+ @author Petr Pchelko
+ @run main/othervm LoadAWTCrashTest
+*/
+
+public class LoadAWTCrashTest {
+ public static void main(String[] args) {
+ System.loadLibrary("awt");
+ // If the bug is present JVM would crash or deadlock
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/TextLayout/TestAATMorxFont.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 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
+ * @summary verify rendering of MORX fonts on OS X.
+ * @bug 8031462
+ */
+
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+
+public class TestAATMorxFont extends JComponent {
+ public static void main(String[] args) {
+ String osName = System.getProperty("os.name");
+ System.out.println("OS is " + osName);
+ osName = osName.toLowerCase();
+ if (!osName.startsWith("mac")) {
+ return;
+ }
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ JFrame frame = new JFrame("Test Morx");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ TestAATMorxFont panel = new TestAATMorxFont();
+ frame.add(panel);
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(1200, 400);
+ }
+
+ public void paintComponent(Graphics g) {
+ Graphics2D g2d = (Graphics2D)g;
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ int y = 50;
+ g.setFont(new Font("Gujarati MT", Font.PLAIN, 40));
+ System.out.println(g.getFont());
+ g.drawString("\u0A95\u0ACD \u0A95\u0A95\u0A95 \u0A95\u0ACD\u0A95\u0ACD\u0A95", 20, y);
+ y += 50;
+ g.setFont(new Font("Tamil Sangam MN", Font.PLAIN, 40));
+ System.out.println(g.getFont());
+ g.drawString("\u0b95\u0bCD \u0b95\u0b95\u0b95 \u0b95\u0bCD\u0b95\u0bCD\u0b95", 20, y);
+ y += 50;
+ g.setFont(new Font("Telugu Sangam MN", Font.PLAIN, 40));
+ System.out.println(g.getFont());
+ g.drawString("\u0c15\u0c4D \u0c15\u0c15\u0c15 \u0c15\u0c4D\u0c15\u0c4D\u0c15", 20, y);
+ y += 50;
+ g.setFont(new Font("Devanagari Sangam MN", Font.PLAIN, 40));
+ System.out.println(g.getFont());
+ g.drawString("\u0915\u0940 \u0915\u0947 \u0915\u0942", 20, y);
+ y += 50;
+ g.drawString("\u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y);
+ y += 50;
+ g.drawString("\u0930\u093F\u0935\u094D\u092F\u0942 \u0915\u0947 \u092C\u093E\u0926 \u0935\u093F\u0915\u093E\u0938 \u0913\u0932\u0902\u092A\u093F\u0915 \u0938\u0947 \u092C\u093E\u0939\u0930 (\u0926\u0947\u0935\u0928\u093E\u0917\u0930\u0940) (\u0939\u093F\u0928\u094D\u0926\u0940) \u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y);
+
+ }
+}
+
--- a/jdk/test/java/net/URLPermission/nstest/lookup.sh Tue Apr 15 15:28:01 2014 -0700
+++ b/jdk/test/java/net/URLPermission/nstest/lookup.sh Wed Apr 16 10:53:10 2014 -0700
@@ -26,6 +26,7 @@
# @library /lib/testlibrary
# @compile -XDignore.symbol.file=true SimpleNameService.java
# LookupTest.java SimpleNameServiceDescriptor.java
+# @build jdk.testlibrary.Utils
# @run shell/timeout=50 lookup.sh
#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Provider/NewInstance.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 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 8039853
+ * @summary Provider.Service.newInstance() does not work with current
+ JDK JGSS Mechanisms
+ */
+
+import java.security.*;
+import java.util.*;
+
+public class NewInstance {
+
+ public static void main(String[] args) throws Exception {
+ for (Provider p : Security.getProviders()) {
+ System.out.println("---------");
+ System.out.println(p.getName() + ":" + p.getInfo());
+ if (p.getName().equals("SunPCSC")) {
+ System.out.println("A smartcard might not be installed. Skip test.");
+ continue;
+ }
+ Set<Provider.Service> set = p.getServices();
+ Iterator<Provider.Service> i = set.iterator();
+
+ while (i.hasNext()) {
+ Provider.Service s = i.next();
+ System.out.println(s.getType() + "." + s.getAlgorithm());
+ try {
+ s.newInstance(null);
+ } catch (NoSuchAlgorithmException e) {
+ System.out.println(" check");
+ Throwable t = e.getCause();
+ if (!(t instanceof InvalidAlgorithmParameterException)) {
+ throw e;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/jpeg/TruncatedImageWarningTest.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 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 8032370
+ *
+ * @summary Test verifies that Image I/O jpeg reader correctly handles
+ * and warns of a truncated image stream.
+ *
+ * @run main TruncatedImageWarningTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.event.IIOReadWarningListener;
+import javax.imageio.stream.ImageInputStream;
+
+public class TruncatedImageWarningTest implements IIOReadWarningListener {
+
+ private static String fileName = "truncated.jpg";
+ boolean receivedWarning = false;
+
+ public static void main(String[] args) throws IOException {
+
+ String sep = System.getProperty("file.separator");
+ String dir = System.getProperty("test.src", ".");
+ String filePath = dir+sep+fileName;
+ System.out.println("Test file: " + filePath);
+ File f = new File(filePath);
+ ImageInputStream in = ImageIO.createImageInputStream(f);
+ ImageReader reader = ImageIO.getImageReaders(in).next();
+ TruncatedImageWarningTest twt = new TruncatedImageWarningTest();
+ reader.addIIOReadWarningListener(twt);
+ reader.setInput(in);
+ reader.read(0);
+ if (!twt.receivedWarning) {
+ throw new RuntimeException("No expected warning");
+ }
+ }
+
+ public void warningOccurred(ImageReader source, String warning) {
+ System.out.println("Expected warning: " + warning);
+ receivedWarning = true;
+ }
+}
Binary file jdk/test/javax/imageio/plugins/jpeg/truncated.jpg has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/8032874/bug8032874.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, 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 8032874
+ * @summary Test whether ArrayIndexOutOfBoundsException is thrown or not,
+ * once selected row is removed from JTable with Sorter and Filter
+ * @author Dmitry Markov
+ * @run main bug8032874
+ */
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableRowSorter;
+
+import sun.awt.SunToolkit;
+
+public class bug8032874 {
+ private static final int ROW_COUNT = 5;
+ private static JTable table;
+ private static TestTableModel tableModel;
+
+ public static void main(String args[]) throws Exception {
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ createAndShowUI();
+ }
+ });
+ toolkit.realSync();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ table.getRowSorter().toggleSortOrder(0);
+ table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
+ table.setRowSelectionInterval(1, 2);
+ }
+ });
+ toolkit.realSync();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < ROW_COUNT; i++) {
+ tableModel.remove(0);
+ table.getRowSorter().toggleSortOrder(0);
+ }
+ }
+ });
+ }
+
+ public static void createAndShowUI() {
+ try {
+ UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ JFrame frame = new JFrame("bug8032874");
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+ tableModel = new TestTableModel();
+ table = new JTable(tableModel);
+ table.setSurrendersFocusOnKeystroke(true);
+
+ final TableRowSorter<TestTableModel> rowSorter = new TableRowSorter<TestTableModel>(tableModel);
+ rowSorter.setRowFilter(new RowFilter<TestTableModel, Integer>() {
+ @Override
+ public boolean include(Entry<? extends TestTableModel, ? extends Integer> entry) {
+ return entry.getIdentifier() % 2 == 0;
+ }
+ });
+ table.setRowSorter(rowSorter);
+
+ JScrollPane jScrollPane = new JScrollPane(table);
+ panel.add(jScrollPane);
+
+ frame.setContentPane(panel);
+ frame.setSize(new Dimension(800, 600));
+ frame.setVisible(true);
+ }
+
+ private static class TestTableModel extends AbstractTableModel {
+ private final List<Integer> data;
+
+ public TestTableModel() {
+ data = new ArrayList<Integer>();
+
+ for (int i = 0; i < ROW_COUNT; i++) {
+ data.add(i);
+ }
+ }
+
+ @Override
+ public int getRowCount() {
+ return data.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 1;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return data.get(rowIndex);
+ }
+
+ public void remove(int row) {
+ data.remove(row);
+ fireTableRowsDeleted(row, row);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/Basic.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009, 2011, 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;
+
+/**
+ *
+ * @test
+ * @bug 8038500
+ * @summary Basic test for zip provider
+ */
+
+public class Basic {
+ public static void main(String[] args) throws Exception {
+ Path zipfile = Paths.get(System.getProperty("test.jdk"),
+ "jre/lib/ext/zipfs.jar");
+ // Test: zip should should be returned in provider list
+ boolean found = false;
+
+ for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+ if (provider.getScheme().equalsIgnoreCase("jar")) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ throw new RuntimeException("'jar' provider not installed");
+
+ // Test: FileSystems#newFileSystem(Path)
+ Map<String,?> env = new HashMap<String,Object>();
+ FileSystems.newFileSystem(zipfile, null).close();
+
+ // Test: FileSystems#newFileSystem(URI)
+ URI uri = new URI("jar", zipfile.toUri().toString(), null);
+ 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;
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
+ for (Path entry: stream) {
+ found = entry.toString().equals("/META-INF/");
+ if (found) break;
+ }
+ }
+
+ 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 (Files.exists(source)) {
+ Path target = Paths.get(source.getFileName().toString());
+ Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+ try {
+ long s1 = Files.readAttributes(source, BasicFileAttributes.class).size();
+ long s2 = Files.readAttributes(target, BasicFileAttributes.class).size();
+ if (s2 != s1)
+ throw new RuntimeException("target size != source size");
+ } finally {
+ Files.delete(target);
+ }
+ }
+
+ // Test: FileStore
+ FileStore store = Files.getFileStore(fs.getPath("/"));
+ 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.provider().checkAccess(fs.getPath("/missing"), 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.getFileName() != null) {
+ indent();
+ System.out.println(dir.getFileName() + "/");
+ indent++;
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file,
+ BasicFileAttributes attrs)
+ {
+ indent();
+ System.out.print(file.getFileName());
+ 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.getFileName() != null)
+ indent--;
+ return FileVisitResult.CONTINUE;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/Demo.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 2010, 2014, 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.spi.*;
+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 Demo action ZipfileName [...]
+ *
+ * @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
+
+ copyin_attrs, // <java Demo copyin_attrs zipfile src dst>
+ // copy an external src file into zipfile
+ // as entry dst, with attributes (timestamp)
+
+ copyout, // <java Demo copyout zipfile src dst>
+ // copy zipfile entry src" out to file dst
+
+ copyout_attrs, // <java Demo copyout_attrs zipfile src 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
+
+ setatime, // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
+ setctime, // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" 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
+
+ prof,
+ }
+
+ public static void main(String[] args) throws Throwable {
+ FileSystemProvider provider = getZipFSProvider();
+ if (provider == null) {
+ System.err.println("ZIP filesystem provider is not installed");
+ System.exit(1);
+ }
+
+ Action action = Action.valueOf(args[0]);
+ Map<String, Object> env = env = new HashMap<>();
+ if (action == Action.create)
+ env.put("create", "true");
+ try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
+ Path path, src, dst;
+ switch (action) {
+ case rename:
+ src = fs.getPath(args[2]);
+ dst = fs.getPath(args[3]);
+ Files.move(src, dst);
+ break;
+ case moveout:
+ src = fs.getPath(args[2]);
+ dst = Paths.get(args[3]);
+ Files.move(src, dst);
+ break;
+ case movein:
+ src = Paths.get(args[2]);
+ dst = fs.getPath(args[3]);
+ Files.move(src, dst);
+ break;
+ case copy:
+ src = fs.getPath(args[2]);
+ dst = fs.getPath(args[3]);
+ Files.copy(src, dst);
+ break;
+ case copyout:
+ src = fs.getPath(args[2]);
+ dst = Paths.get(args[3]);
+ Files.copy(src, dst);
+ break;
+ case copyin:
+ src = Paths.get(args[2]);
+ dst = fs.getPath(args[3]);
+ Files.copy(src, dst);
+ break;
+ case copyin_attrs:
+ src = Paths.get(args[2]);
+ dst = fs.getPath(args[3]);
+ Files.copy(src, dst, COPY_ATTRIBUTES);
+ break;
+ case copyout_attrs:
+ src = fs.getPath(args[2]);
+ dst = Paths.get(args[3]);
+ Files.copy(src, dst, COPY_ATTRIBUTES);
+ break;
+ case zzmove:
+ try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
+ z2zmove(fs, fs2, args[3]);
+ }
+ break;
+ case zzcopy:
+ try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
+ z2zcopy(fs, fs2, args[3]);
+ }
+ break;
+ case attrs:
+ for (int i = 2; i < args.length; i++) {
+ path = fs.getPath(args[i]);
+ System.out.println(path);
+ System.out.println(
+ Files.readAttributes(path, BasicFileAttributes.class).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]);
+ Files.setAttribute(path, "lastModifiedTime",
+ FileTime.fromMillis(newDatetime.getTime()));
+ System.out.println(
+ Files.readAttributes(path, BasicFileAttributes.class).toString());
+ }
+ break;
+ case setctime:
+ df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+ newDatetime = df.parse(args[2]);
+ for (int i = 3; i < args.length; i++) {
+ path = fs.getPath(args[i]);
+ Files.setAttribute(path, "creationTime",
+ FileTime.fromMillis(newDatetime.getTime()));
+ System.out.println(
+ Files.readAttributes(path, BasicFileAttributes.class).toString());
+ }
+ break;
+ case setatime:
+ df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+ newDatetime = df.parse(args[2]);
+ for (int i = 3; i < args.length; i++) {
+ path = fs.getPath(args[i]);
+ Files.setAttribute(path, "lastAccessTime",
+ FileTime.fromMillis(newDatetime.getTime()));
+ System.out.println(
+ Files.readAttributes(path, BasicFileAttributes.class).toString());
+ }
+ break;
+ case attrsspace:
+ path = fs.getPath("/");
+ FileStore fstore = Files.getFileStore(path);
+ System.out.printf("filestore[%s]%n", fstore.name());
+ System.out.printf(" totalSpace: %d%n",
+ (Long)fstore.getAttribute("totalSpace"));
+ System.out.printf(" usableSpace: %d%n",
+ (Long)fstore.getAttribute("usableSpace"));
+ System.out.printf(" unallocSpace: %d%n",
+ (Long)fstore.getAttribute("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++)
+ Files.delete(fs.getPath(args[i]));
+ 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]:"";
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(path,
+ new DirectoryStream.Filter<Path>() {
+ @Override
+ public boolean accept(Path path) {
+ return path.toString().contains(fStr);
+ }
+ }))
+ {
+ for (Path p : ds)
+ System.out.println(p);
+ }
+ break;
+ case mkdir:
+ Files.createDirectory(fs.getPath(args[2]));
+ 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.printf("%n%s%n", path);
+ System.out.println("-------(1)---------");
+ System.out.println(
+ Files.readAttributes(path, BasicFileAttributes.class).toString());
+ System.out.println("-------(2)---------");
+ Map<String, Object> map = Files.readAttributes(path, "zip:*");
+ for (Map.Entry<String, Object> e : map.entrySet()) {
+ System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
+ }
+ System.out.println("-------(3)---------");
+ map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory");
+ for (Map.Entry<String, ?> e : map.entrySet()) {
+ System.out.printf(" %s : %s%n", e.getKey(), e.getValue());
+ }
+ }
+ break;
+ case prof:
+ list(fs.getPath("/"), false);
+ while (true) {
+ Thread.sleep(10000);
+ //list(fs.getPath("/"), true);
+ System.out.println("sleeping...");
+ }
+ }
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ }
+
+ private static FileSystemProvider getZipFSProvider() {
+ for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
+ if ("jar".equals(provider.getScheme()))
+ return provider;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ /**
+ * Not used in demo, but included for demonstrational purposes.
+ */
+ private static byte[] getBytes(String name) {
+ return name.getBytes();
+ }
+
+ @SuppressWarnings("unused")
+ /**
+ * Not used in demo, but included for demonstrational purposes.
+ */
+ 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.getFileName().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 (Files.isDirectory(src)) {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
+ for (Path child : ds)
+ update(fs, child.toString());
+ }
+ } else {
+ Path dst = fs.getPath(path);
+ Path parent = dst.getParent();
+ if (parent != null && Files.notExists(parent))
+ mkdirs(parent);
+ Files.copy(src, dst, REPLACE_EXISTING);
+ }
+ }
+
+ private static void extract(FileSystem fs, String path) throws Throwable{
+ Path src = fs.getPath(path);
+ if (Files.isDirectory(src)) {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
+ for (Path child : ds)
+ extract(fs, child.toString());
+ }
+ } else {
+ if (path.startsWith("/"))
+ path = path.substring(1);
+ Path dst = FileSystems.getDefault().getPath(path);
+ Path parent = dst.getParent();
+ if (Files.notExists(parent))
+ mkdirs(parent);
+ Files.copy(src, 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 (Files.isDirectory(srcPath)) {
+ if (!Files.exists(dstPath)) {
+ try {
+ mkdirs(dstPath);
+ } catch (FileAlreadyExistsException x) {}
+ }
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+ for (Path child : ds) {
+ z2zcopy(src, dst,
+ path + (path.endsWith("/")?"":"/") + child.getFileName());
+ }
+ }
+ } else {
+ //System.out.println("copying..." + path);
+ Files.copy(srcPath, 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 && Files.notExists(parent))
+ mkdirs(parent);
+ Files.move(file, 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 (Files.notExists(dst))
+ mkdirs(dst);
+ } catch (IOException x) {
+ x.printStackTrace();
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir,
+ IOException ioe)
+ throws IOException
+ {
+ try {
+ Files.delete(dir);
+ } 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 (Files.notExists(parent))
+ mkdirs(parent);
+ }
+ Files.createDirectory(path);
+ }
+
+ @SuppressWarnings("unused")
+ /**
+ * Not used in demo, but included for demonstrational purposes.
+ */
+ private static void rmdirs(Path path) throws IOException {
+ while (path != null && path.getNameCount() != 0) {
+ Files.delete(path);
+ path = path.getParent();
+ }
+ }
+
+ private static void list(Path path, boolean verbose ) throws IOException {
+ if (!"/".equals(path.toString())) {
+ System.out.printf(" %s%n", path.toString());
+ if (verbose)
+ System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString());
+ }
+ if (Files.notExists(path))
+ return;
+ if (Files.isDirectory(path)) {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
+ for (Path child : ds)
+ list(child, verbose);
+ }
+ }
+ }
+
+ @SuppressWarnings("unused")
+ /**
+ * Checks that the content of two paths are equal.
+ * Not used in demo, but included for demonstrational purposes.
+ */
+ private static void checkEqual(Path src, Path dst) throws IOException
+ {
+ //System.out.printf("checking <%s> vs <%s>...%n",
+ // src.toString(), dst.toString());
+
+ //streams
+ byte[] bufSrc = new byte[8192];
+ byte[] bufDst = new byte[8192];
+ try (InputStream isSrc = Files.newInputStream(src);
+ InputStream isDst = Files.newInputStream(dst))
+ {
+ 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--;
+ }
+ }
+ }
+
+ // channels
+
+ try (SeekableByteChannel chSrc = Files.newByteChannel(src);
+ SeekableByteChannel chDst = Files.newByteChannel(dst))
+ {
+ 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);
+
+ 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();
+ }
+ }
+
+ 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);
+
+ try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read);
+ FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite))
+ {
+ ByteBuffer bb = ByteBuffer.allocate(8192);
+ while (srcFc.read(bb) >= 0) {
+ bb.flip();
+ dstFc.write(bb);
+ bb.clear();
+ }
+ }
+ }
+
+ 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);
+
+ try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
+ SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
+ {
+ ByteBuffer bb = ByteBuffer.allocate(8192);
+ while (srcCh.read(bb) >= 0) {
+ bb.flip();
+ dstCh.write(bb);
+ bb.clear();
+ }
+ }
+ }
+
+ private static void streamCopy(Path src, Path dst) throws IOException
+ {
+ byte[] buf = new byte[8192];
+ try (InputStream isSrc = Files.newInputStream(src);
+ OutputStream osDst = Files.newOutputStream(dst))
+ {
+ int n = 0;
+ while ((n = isSrc.read(buf)) != -1) {
+ osDst.write(buf, 0, n);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/PathOps.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2009, 2011, 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;
+
+/**
+ *
+ * @test
+ * @bug 8038500
+ * @summary 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.getFileName(), 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 isSameFile(String target) {
+ try {
+ out.println("check two paths are same");
+ checkPath();
+ check(Files.isSameFile(path, test(target).path()), true);
+ } catch (IOException ioe) {
+ fail();
+ }
+ 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("/");
+ test("/")
+ .starts("/")
+ .notStarts("/foo");
+ test("/foo")
+ .starts("/")
+ .starts("/foo")
+ .notStarts("/f")
+ .notStarts("");
+ test("/foo/bar")
+ .starts("/")
+ .starts("/foo")
+ .starts("/foo/")
+ .starts("/foo/bar")
+ .notStarts("/f")
+ .notStarts("foo")
+ .notStarts("foo/bar")
+ .notStarts("");
+ test("foo")
+ .starts("foo")
+ .notStarts("f");
+ test("foo/bar")
+ .starts("foo")
+ .starts("foo/")
+ .starts("foo/bar")
+ .notStarts("f")
+ .notStarts("/foo")
+ .notStarts("/foo/bar");
+
+ // endsWith
+ test("")
+ .ends("")
+ .notEnds("/");
+ test("/")
+ .ends("/")
+ .notEnds("foo")
+ .notEnds("/foo");
+ test("/foo")
+ .ends("foo")
+ .ends("/foo")
+ .notEnds("/");
+ test("/foo/bar")
+ .ends("bar")
+ .ends("foo/bar")
+ .ends("foo/bar/")
+ .ends("/foo/bar")
+ .notEnds("/bar");
+ test("/foo/bar/")
+ .ends("bar")
+ .ends("foo/bar")
+ .ends("foo/bar/")
+ .ends("/foo/bar")
+ .notEnds("/bar");
+ test("foo")
+ .ends("foo");
+ test("foo/bar")
+ .ends("bar")
+ .ends("bar/")
+ .ends("foo/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();
+ test("")
+ .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", "")
+ .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("");
+ test("..")
+ .normalize("..");
+ test("/..")
+ .normalize("/");
+ test("/../..")
+ .normalize("/");
+ test("foo/.")
+ .normalize("foo");
+ test("./foo")
+ .normalize("foo");
+ test("foo/..")
+ .normalize("");
+ 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");
+ test("/./.")
+ .normalize("/");
+ test("/.")
+ .normalize("/");
+ test("/./abc")
+ .normalize("/abc");
+ // 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");
+
+ // isSameFile
+ test("/fileDoesNotExist")
+ .isSameFile("/fileDoesNotExist");
+ }
+
+ 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((Path)null);
+ throw new RuntimeException("NullPointerException not thrown");
+ } catch (NullPointerException npe) {
+ }
+
+ try {
+ path.endsWith((Path)null);
+ throw new RuntimeException("NullPointerException not thrown");
+ } catch (NullPointerException npe) {
+ }
+
+ }
+
+ public static void main(String[] args) throws Throwable {
+ Path zipfile = Paths.get(System.getProperty("test.jdk"),
+ "jre/lib/ext/zipfs.jar");
+ fs = FileSystems.newFileSystem(zipfile, null);
+ npes();
+ doPathOpTests();
+ fs.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 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 7156873
+ @summary ZipFileSystem regression tests
+ */
+
+
+import java.net.URI;
+import java.nio.file.*;
+import java.util.Map;
+import java.util.HashMap;
+
+public class ZFSTests {
+
+ public static void main(String[] args) throws Throwable {
+ test7156873();
+ }
+
+ static void test7156873() throws Throwable {
+ String DIRWITHSPACE = "testdir with spaces";
+ Path dir = Paths.get(DIRWITHSPACE);
+ Path path = Paths.get(DIRWITHSPACE, "file.zip");
+ try {
+ Files.createDirectory(dir);
+ URI uri = URI.create("jar:" + path.toUri());
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "true");
+ try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {}
+ } finally {
+ Files.deleteIfExists(path);
+ Files.deleteIfExists(dir);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java Wed Apr 16 10:53:10 2014 -0700
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2010, 2013, 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.spi.*;
+import java.nio.file.attribute.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.*;
+
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/*
+ * Tests various zipfs operations.
+ *
+ * @test
+ * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
+ * 7157656 8002390 7012868 7012856 8015728 8038500
+ * @summary Test Zip filesystem provider
+ */
+
+public class ZipFSTester {
+
+ public static void main(String[] args) throws Throwable {
+ try (FileSystem fs = newZipFileSystem(
+ Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"),
+ new HashMap<String, Object>()))
+ {
+ test0(fs);
+ test1(fs);
+ test2(fs); // more tests
+ }
+ testTime(Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"));
+ }
+
+ static void test0(FileSystem fs)
+ throws Exception
+ {
+ List<String> list = new LinkedList<>();
+ try (ZipFile zf = new ZipFile(fs.toString())) {
+ Enumeration<? extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ list.add(zes.nextElement().getName());
+ }
+ for (String pname : list) {
+ Path path = fs.getPath(pname);
+ if (!Files.exists(path))
+ throw new RuntimeException("path existence check failed!");
+ while ((path = path.getParent()) != null) {
+ if (!Files.exists(path))
+ throw new RuntimeException("parent existence check failed!");
+ }
+ }
+ }
+ }
+
+ static void test1(FileSystem fs0)
+ 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("create", "true");
+ try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
+ z2zcopy(fs0, copy, "/", 0);
+ }
+
+ try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
+
+ FileSystemProvider provider = fs.provider();
+ // newFileSystem(path...) should not throw exception
+ try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){}
+ try (FileSystem fsUri = provider.newFileSystem(
+ new URI("jar", tmpfsPath.toUri().toString(), null),
+ new HashMap<String, Object>()))
+ {
+ throw new RuntimeException("newFileSystem(uri...) does not throw exception");
+ } catch (FileSystemAlreadyExistsException fsaee) {}
+
+ // prepare a src
+ Path src = getTempPath();
+ String tmpName = src.toString();
+ OutputStream os = Files.newOutputStream(src);
+ byte[] bits = new byte[12345];
+ rdm.nextBytes(bits);
+ os.write(bits);
+ os.close();
+
+ try {
+ provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
+ new HashMap<String, Object>());
+ throw new RuntimeException("newFileSystem() opens a directory as zipfs");
+ } catch (UnsupportedOperationException uoe) {}
+
+ try {
+ provider.newFileSystem(src, new HashMap<String, Object>());
+ throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
+ } catch (UnsupportedOperationException uoe) {}
+
+
+ // copyin
+ Path dst = getPathWithParents(fs, tmpName);
+ Files.copy(src, dst);
+ checkEqual(src, dst);
+
+ // copy
+ Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
+ "/efg" + rdm.nextInt(100) + "/foo.class");
+ Files.copy(dst, dst2);
+ //dst.moveTo(dst2);
+ checkEqual(src, dst2);
+
+ // delete
+ Files.delete(dst);
+ if (Files.exists(dst))
+ throw new RuntimeException("Failed!");
+
+ // moveout
+ Path dst3 = Paths.get(tmpName + "_Tmp");
+ Files.move(dst2, dst3);
+ checkEqual(src, dst3);
+ if (Files.exists(dst2))
+ throw new RuntimeException("Failed!");
+
+ // copyback + move
+ Files.copy(dst3, dst);
+ Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
+ Files.move(dst, dst4);
+ checkEqual(src, dst4);
+
+ // delete
+ Files.delete(dst4);
+ if (Files.exists(dst4))
+ throw new RuntimeException("Failed!");
+ Files.delete(dst3);
+ if (Files.exists(dst3))
+ throw new RuntimeException("Failed!");
+
+ // move (existing entry)
+ Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
+ if (Files.exists(dst5)) {
+ Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
+ Files.move(dst5, dst6);
+ walk(fs.getPath("/"));
+ }
+
+ // newInputStream on dir
+ Path parent = dst2.getParent();
+ try {
+ Files.newInputStream(parent);
+ 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);
+ Files.delete(tmp);
+
+ // test channels
+ channel(fs, dst);
+ Files.delete(dst);
+ Files.delete(src);
+ } finally {
+ if (Files.exists(tmpfsPath))
+ Files.delete(tmpfsPath);
+ }
+ }
+
+ static void test2(FileSystem fs) throws Exception {
+
+ Path fs1Path = getTempPath();
+ Path fs2Path = getTempPath();
+ Path fs3Path = getTempPath();
+
+ // create a new filesystem, copy everything from fs
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "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 (Files.exists(fs2.getPath(path))) {
+ 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);
+
+ Files.delete(fs1Path);
+ Files.delete(fs2Path);
+ Files.delete(fs3Path);
+ }
+
+ // test file stamp
+ static void testTime(Path src) throws Exception {
+ BasicFileAttributes attrs = Files
+ .getFileAttributeView(src, BasicFileAttributeView.class)
+ .readAttributes();
+ // create a new filesystem, copy this file into it
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "true");
+ Path fsPath = getTempPath();
+ FileSystem fs = newZipFileSystem(fsPath, env);
+
+ System.out.println("test copy with timestamps...");
+ // copyin
+ Path dst = getPathWithParents(fs, "me");
+ Files.copy(src, dst, COPY_ATTRIBUTES);
+ checkEqual(src, dst);
+ System.out.println("mtime: " + attrs.lastModifiedTime());
+ System.out.println("ctime: " + attrs.creationTime());
+ System.out.println("atime: " + attrs.lastAccessTime());
+ System.out.println(" ==============>");
+ BasicFileAttributes dstAttrs = Files
+ .getFileAttributeView(dst, BasicFileAttributeView.class)
+ .readAttributes();
+ System.out.println("mtime: " + dstAttrs.lastModifiedTime());
+ System.out.println("ctime: " + dstAttrs.creationTime());
+ System.out.println("atime: " + dstAttrs.lastAccessTime());
+
+ // 1-second granularity
+ if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) !=
+ dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) ||
+ attrs.lastAccessTime().to(TimeUnit.SECONDS) !=
+ dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
+ attrs.creationTime().to(TimeUnit.SECONDS) !=
+ dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
+ throw new RuntimeException("Timestamp Copy Failed!");
+ }
+ Files.delete(fsPath);
+ }
+
+ private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
+ throws Exception
+ {
+ return FileSystems.newFileSystem(
+ new URI("jar", path.toUri().toString(), null), 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 (Files.isDirectory(path)) {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
+ for (Path child : ds)
+ list(child, files, dirs);
+ }
+ 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 (Files.isDirectory(srcPath)) {
+ if (!Files.exists(dstPath)) {
+ try {
+ mkdirs(dstPath);
+ } catch (FileAlreadyExistsException x) {}
+ }
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+ for (Path child : ds) {
+ z2zcopy(src, dst,
+ path + (path.endsWith("/")?"":"/") + child.getFileName(),
+ method);
+ }
+ }
+ } else {
+ try {
+ if (Files.exists(dstPath))
+ return;
+ switch (method) {
+ case 0:
+ Files.copy(srcPath, 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 (Files.isDirectory(srcPath)) {
+ if (!Files.exists(dstPath))
+ mkdirs(dstPath);
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+ for (Path child : ds) {
+ z2zmove(src, dst,
+ path + (path.endsWith("/")?"":"/") + child.getFileName());
+ }
+ }
+ } else {
+ //System.out.println("moving..." + path);
+ Path parent = dstPath.getParent();
+ if (parent != null && Files.notExists(parent))
+ mkdirs(parent);
+ Files.move(srcPath, 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.getFileName().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 {
+ if (Files.exists(path))
+ return;
+ path = path.toAbsolutePath();
+ Path parent = path.getParent();
+ if (parent != null) {
+ if (Files.notExists(parent))
+ mkdirs(parent);
+ }
+ Files.createDirectory(path);
+ }
+
+ private static void rmdirs(Path path) throws IOException {
+ while (path != null && path.getNameCount() != 0) {
+ Files.delete(path);
+ 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
+ byte[] bufSrc = new byte[8192];
+ byte[] bufDst = new byte[8192];
+ try (InputStream isSrc = Files.newInputStream(src);
+ InputStream isDst = Files.newInputStream(dst))
+ {
+ 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--;
+ }
+ }
+ }
+
+ // channels
+ try (SeekableByteChannel chSrc = Files.newByteChannel(src);
+ SeekableByteChannel chDst = Files.newByteChannel(dst))
+ {
+ 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);
+
+ 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();
+ }
+
+ // Check if source read position is at the end
+ if (chSrc.position() != chSrc.size()) {
+ System.out.printf("src[%s]: size=%d, position=%d%n",
+ chSrc.toString(), chSrc.size(), chSrc.position());
+ throw new RuntimeException("CHECK FAILED!");
+ }
+
+ // Check if destination read position is at the end
+ if (chDst.position() != chDst.size()) {
+ System.out.printf("dst[%s]: size=%d, position=%d%n",
+ chDst.toString(), chDst.size(), chDst.position());
+ throw new RuntimeException("CHECK FAILED!");
+ }
+ } catch (IOException x) {
+ x.printStackTrace();
+ }
+ }
+
+ 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);
+
+ try (FileChannel srcFc = src.getFileSystem()
+ .provider()
+ .newFileChannel(src, read);
+ FileChannel dstFc = dst.getFileSystem()
+ .provider()
+ .newFileChannel(dst, openwrite))
+ {
+ ByteBuffer bb = ByteBuffer.allocate(8192);
+ while (srcFc.read(bb) >= 0) {
+ bb.flip();
+ dstFc.write(bb);
+ bb.clear();
+ }
+ }
+ }
+
+ 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);
+
+ try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
+ SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
+ {
+
+ ByteBuffer bb = ByteBuffer.allocate(8192);
+ while (srcCh.read(bb) >= 0) {
+ bb.flip();
+ dstCh.write(bb);
+ bb.clear();
+ }
+
+ // Check if source read position is at the end
+ if (srcCh.position() != srcCh.size()) {
+ System.out.printf("src[%s]: size=%d, position=%d%n",
+ srcCh.toString(), srcCh.size(), srcCh.position());
+ throw new RuntimeException("CHECK FAILED!");
+ }
+
+ // Check if destination write position is at the end
+ if (dstCh.position() != dstCh.size()) {
+ System.out.printf("dst[%s]: size=%d, position=%d%n",
+ dstCh.toString(), dstCh.size(), dstCh.position());
+ throw new RuntimeException("CHECK FAILED!");
+ }
+ }
+ }
+
+ private static void streamCopy(Path src, Path dst) throws IOException
+ {
+ byte[] buf = new byte[8192];
+ try (InputStream isSrc = Files.newInputStream(src);
+ OutputStream osDst = Files.newOutputStream(dst))
+ {
+ int n = 0;
+ while ((n = isSrc.read(buf)) != -1) {
+ osDst.write(buf, 0, n);
+ }
+ }
+ }
+
+ static void channel(FileSystem fs, Path path)
+ throws Exception
+ {
+ System.out.println("test ByteChannel...");
+ Set<OpenOption> read = new HashSet<>();
+ read.add(READ);
+ int n = 0;
+ ByteBuffer bb = null;
+ ByteBuffer bb2 = null;
+ int N = 120;
+
+ try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
+ System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
+ if (sbc.position() != 0) {
+ throw new RuntimeException("CHECK FAILED!");
+ }
+
+ bb = ByteBuffer.allocate((int)sbc.size());
+ n = sbc.read(bb);
+ System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n",
+ n, sbc.position(), sbc.size());
+ if (sbc.position() != sbc.size()) {
+ throw new RuntimeException("CHECK FAILED!");
+ }
+ bb2 = ByteBuffer.allocate((int)sbc.size());
+ }
+
+ // sbc.position(pos) is not supported in current version
+ // try the FileChannel
+ try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) {
+ sbc.position(N);
+ System.out.printf(" sbc[2]: pos=%d, size=%d%n",
+ sbc.position(), sbc.size());
+ if (sbc.position() != N) {
+ throw new RuntimeException("CHECK FAILED!");
+ }
+ bb2.limit(100);
+ n = sbc.read(bb2);
+ System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n",
+ n, sbc.position(), sbc.size());
+ if (n < 0 || sbc.position() != (N + n)) {
+ throw new RuntimeException("CHECK FAILED!");
+ }
+ System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
+ N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
+ }
+ }
+
+ // 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 && Files.notExists(parent))
+ mkdirs(parent);
+ return path;
+ }
+}