# HG changeset patch # User duke # Date 1499276263 -7200 # Node ID cb2cf6e2958a83a1cfb0401bb9cbc5695dd9672e # Parent 16ec7c58cdead4cb2b6392081a2c72b7db68b7c4# Parent 65b2502dbd2d4afc93182a6f4506868f4967ffdd Merge diff -r 16ec7c58cdea -r cb2cf6e2958a .hgtags-top-repo --- a/.hgtags-top-repo Thu Apr 17 15:23:23 2014 -0700 +++ b/.hgtags-top-repo Wed Jul 05 19:37:43 2017 +0200 @@ -251,3 +251,4 @@ d0b525cd31b87abeb6d5b7e3516953eeb13b323c jdk9-b06 0ea015c298b201c07fa33990f2445b6d0ef3566d jdk9-b07 db045d8faa0924b7378102d24a1a0d850c1e3834 jdk9-b08 +4a21dc7d57d1069a01f68e7182c074cb37349dfb jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a common/src/fixpath.c --- a/common/src/fixpath.c Thu Apr 17 15:23:23 2014 -0700 +++ b/common/src/fixpath.c Wed Jul 05 19:37:43 2017 +0200 @@ -109,7 +109,7 @@ void append(char **b, size_t *bl, size_t *u, char *add, size_t addlen) { - while ( (addlen+*u+1) > *bl) { + while ((addlen+*u+1) > *bl) { *bl *= 2; *b = (char*) realloc(*b, *bl); } @@ -118,7 +118,7 @@ } /* - * Creates a new string from in where the first occurance of sub is + * Creates a new string from in where the first occurrence of sub is * replaced by rep. */ char *replace_substring(char *in, char *sub, char *rep) @@ -246,7 +246,7 @@ } buffer = (char*) malloc(buflen); - while((blocklen = fread(block,1,sizeof(block),atin)) > 0) { + while ((blocklen = fread(block, 1, sizeof(block), atin)) > 0) { append(&buffer, &buflen, &used, block, blocklen); } buffer[used] = 0; @@ -280,16 +280,21 @@ char *current = quoted; int pass; - if(strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) { + if (strlen(in_arg) == 0) { + // empty string? explicitly quote it. + return _strdup("\"\""); + } + + if (strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) { return _strdup(in_arg); } // process the arg twice. Once to calculate the size and then to copy it. - for(pass=1; pass<=2; pass++) { + for (pass=1; pass<=2; pass++) { char const *arg = in_arg; // initial " - if(pass == 2) { + if (pass == 2) { *current = '\"'; } current++; @@ -328,7 +333,7 @@ *current = *arg; } current++; - } while( *arg++ != '\0'); + } while (*arg++ != '\0'); // allocate the buffer if (pass == 1) { @@ -362,7 +367,7 @@ if (getenv("DEBUG_FIXPATH") != NULL) { char const * cmdline = GetCommandLine(); - fprintf(stderr, "fixpath input line >%s<\n", strstr( cmdline , argv[1])); + fprintf(stderr, "fixpath input line >%s<\n", strstr(cmdline, argv[1])); } if (argv[1][1] == 'c' && argv[1][2] == '\0') { @@ -399,7 +404,7 @@ } rc = SetEnvironmentVariable(var, val); - if(!rc) { + if (!rc) { // Could not set var for some reason. Try to report why. const int msg_len = 80 + var_len + strlen(val); char * msg = (char *) alloca(msg_len); @@ -422,7 +427,7 @@ // handle command and it's args. while (i < argc) { char const *replaced = replace_cygdrive(argv[i]); - if(replaced[0] == '@') { + if (replaced[0] == '@') { // Found at-file! Fix it! replaced = fix_at_file(replaced); } @@ -433,7 +438,7 @@ // determine the length of the line line = NULL; // args - for(i = cmd; i < argc; i++) { + for (i = cmd; i < argc; i++) { line += (ptrdiff_t) strlen(argv[i]); } // spaces and null @@ -443,7 +448,7 @@ // copy in args. current = line; - for(i = cmd; i < argc; i++) { + for (i = cmd; i < argc; i++) { ptrdiff_t len = strlen(argv[i]); if (i != cmd) { *current++ = ' '; @@ -457,16 +462,16 @@ fprintf(stderr, "fixpath converted line >%s<\n", line); } - if(cmd == argc) { + if (cmd == argc) { if (getenv("DEBUG_FIXPATH") != NULL) { fprintf(stderr, "fixpath no command provided!\n"); } exit(0); } - ZeroMemory(&si,sizeof(si)); + ZeroMemory(&si, sizeof(si)); si.cb=sizeof(si); - ZeroMemory(&pi,sizeof(pi)); + ZeroMemory(&pi, sizeof(pi)); fflush(stderr); fflush(stdout); @@ -481,14 +486,14 @@ NULL, &si, &pi); - if(!rc) { + if (!rc) { // Could not start process for some reason. Try to report why: report_error("Could not start process!"); exit(126); } - WaitForSingleObject(pi.hProcess,INFINITE); - GetExitCodeProcess(pi.hProcess,&exitCode); + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &exitCode); if (getenv("DEBUG_FIXPATH") != NULL) { for (i=0; i noTypesList[] = {}; /** true if represents enum type */ private boolean isEnum; private static final Bridge bridge = - (Bridge)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged( + new PrivilegedAction() { + public Bridge run() { return Bridge.get() ; } } @@ -98,7 +99,7 @@ * is returned if the specified class does not implement * java.io.Serializable or java.io.Externalizable. */ - static final ObjectStreamClass lookup(Class cl) + static final ObjectStreamClass lookup(Class cl) { ObjectStreamClass desc = lookupInternal(cl); if (desc.isSerializable() || desc.isExternalizable()) @@ -110,7 +111,7 @@ * Find the class descriptor for the specified class. * Package access only so it can be called from ObjectIn/OutStream. */ - static ObjectStreamClass lookupInternal(Class cl) + static ObjectStreamClass lookupInternal(Class cl) { /* Synchronize on the hashtable so no two threads will do * this at the same time. @@ -121,14 +122,14 @@ desc = findDescriptorFor(cl); if (desc == null) { /* Check if it's serializable */ - boolean serializable = classSerializable.isAssignableFrom(cl); + boolean serializable = Serializable.class.isAssignableFrom(cl); /* If the class is only Serializable, * lookup the descriptor for the superclass. */ ObjectStreamClass superdesc = null; if (serializable) { - Class superclass = cl.getSuperclass(); + Class superclass = cl.getSuperclass(); if (superclass != null) superdesc = lookup(superclass); } @@ -141,7 +142,7 @@ if (serializable) { externalizable = ((superdesc != null) && superdesc.isExternalizable()) || - classExternalizable.isAssignableFrom(cl); + Externalizable.class.isAssignableFrom(cl); if (externalizable) { serializable = false; } @@ -185,7 +186,7 @@ * that have evolved from a common root class and agree to be serialized * and deserialized using a common format. */ - public static final long getSerialVersionUID( java.lang.Class clazz) { + public static final long getSerialVersionUID( java.lang.Class clazz) { ObjectStreamClass theosc = ObjectStreamClass.lookup( clazz ); if( theosc != null ) { @@ -219,7 +220,7 @@ /** * Return the actual (computed) serialVersionUID for this class. */ - public static final long getActualSerialVersionUID( java.lang.Class clazz ) + public static final long getActualSerialVersionUID( java.lang.Class clazz ) { ObjectStreamClass theosc = ObjectStreamClass.lookup( clazz ); if( theosc != null ) @@ -249,7 +250,7 @@ * Return the class in the local VM that this version is mapped to. * Null is returned if there is no corresponding local class. */ - public final Class forClass() { + public final Class forClass() { return ofClass; } @@ -349,7 +350,7 @@ * Create a new ObjectStreamClass from a loaded class. * Don't call this directly, call lookup instead. */ - private ObjectStreamClass(java.lang.Class cl, ObjectStreamClass superdesc, + private ObjectStreamClass(java.lang.Class cl, ObjectStreamClass superdesc, boolean serial, boolean extern) { ofClass = cl; /* created from this class */ @@ -433,7 +434,7 @@ if (initialized) return; - final Class cl = ofClass; + final Class cl = ofClass; if (!serializable || externalizable || @@ -561,9 +562,9 @@ * will call it as necessary. */ writeObjectMethod = getPrivateMethod( cl, "writeObject", - new Class[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ; + new Class[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ; readObjectMethod = getPrivateMethod( cl, "readObject", - new Class[] { java.io.ObjectInputStream.class }, Void.TYPE ) ; + new Class[] { java.io.ObjectInputStream.class }, Void.TYPE ) ; } return null; } @@ -589,9 +590,9 @@ * class, or null if none found. Access checks are disabled on the * returned method (if any). */ - private static Method getPrivateMethod(Class cl, String name, - Class[] argTypes, - Class returnType) + private static Method getPrivateMethod(Class cl, String name, + Class[] argTypes, + Class returnType) { try { Method meth = cl.getDeclaredMethod(name, argTypes); @@ -653,7 +654,7 @@ * Fill in the reflected Fields that will be used * for reading. */ - final void setClass(Class cl) throws InvalidClassException { + final void setClass(Class cl) throws InvalidClassException { if (cl == null) { localClassDesc = null; @@ -920,9 +921,9 @@ * Access checks are disabled on the returned constructor (if any), since * the defining class may still be non-public. */ - private static Constructor getExternalizableConstructor(Class cl) { + private static Constructor getExternalizableConstructor(Class cl) { try { - Constructor cons = cl.getDeclaredConstructor(new Class[0]); + Constructor cons = cl.getDeclaredConstructor(new Class[0]); cons.setAccessible(true); return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ? cons : null; @@ -936,15 +937,15 @@ * superclass, or null if none found. Access checks are disabled on the * returned constructor (if any). */ - private static Constructor getSerializableConstructor(Class cl) { - Class initCl = cl; + private static Constructor getSerializableConstructor(Class cl) { + Class initCl = cl; while (Serializable.class.isAssignableFrom(initCl)) { if ((initCl = initCl.getSuperclass()) == null) { return null; } } try { - Constructor cons = initCl.getDeclaredConstructor(new Class[0]); + Constructor cons = initCl.getDeclaredConstructor(new Class[0]); int mods = cons.getModifiers(); if ((mods & Modifier.PRIVATE) != 0 || ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && @@ -1049,7 +1050,7 @@ * items to the hash accumulating in the digest stream. * Fold the hash into a long. Use the SHA secure hash function. */ - private static long _computeSerialVersionUID(Class cl) { + private static long _computeSerialVersionUID(Class cl) { if (DEBUG_SVUID) msg( "Computing SerialVersionUID for " + cl ) ; ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); @@ -1103,7 +1104,7 @@ * them from its computation. */ - Class interfaces[] = cl.getInterfaces(); + Class interfaces[] = cl.getInterfaces(); Arrays.sort(interfaces, compareClassByName); for (int i = 0; i < interfaces.length; i++) { @@ -1233,7 +1234,7 @@ return h; } - private static long computeStructuralUID(com.sun.corba.se.impl.io.ObjectStreamClass osc, Class cl) { + private static long computeStructuralUID(com.sun.corba.se.impl.io.ObjectStreamClass osc, Class cl) { ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); long h = 0; @@ -1253,7 +1254,7 @@ DataOutputStream data = new DataOutputStream(mdo); // Get SUID of parent - Class parent = cl.getSuperclass(); + Class parent = cl.getSuperclass(); if ((parent != null)) // SerialBug 1; acc. to spec the one for // java.lang.object @@ -1309,10 +1310,10 @@ /** * Compute the JVM signature for the class. */ - static String getSignature(Class clazz) { + static String getSignature(Class clazz) { String type = null; if (clazz.isArray()) { - Class cl = clazz; + Class cl = clazz; int dimensions = 0; while (cl.isArray()) { dimensions++; @@ -1358,7 +1359,7 @@ sb.append("("); - Class[] params = meth.getParameterTypes(); // avoid clone + Class[] params = meth.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } @@ -1375,7 +1376,7 @@ sb.append("("); - Class[] params = cons.getParameterTypes(); // avoid clone + Class[] params = cons.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } @@ -1395,7 +1396,7 @@ * The entries are extended from java.lang.ref.SoftReference so the * gc will be able to free them if needed. */ - private static ObjectStreamClass findDescriptorFor(Class cl) { + private static ObjectStreamClass findDescriptorFor(Class cl) { int hash = cl.hashCode(); int index = (hash & 0x7FFFFFFF) % descriptorFor.length; @@ -1442,7 +1443,7 @@ descriptorFor[index] = e; } - private static Field[] getDeclaredFields(final Class clz) { + private static Field[] getDeclaredFields(final Class clz) { return (Field[]) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return clz.getDeclaredFields(); @@ -1476,7 +1477,7 @@ /* * Class that is a descriptor for in this virtual machine. */ - private Class ofClass; + private Class ofClass; /* * True if descriptor for a proxy class. @@ -1548,30 +1549,17 @@ * Returns true if the given class defines a static initializer method, * false otherwise. */ - private static boolean hasStaticInitializer(Class cl) { + private static boolean hasStaticInitializer(Class cl) { if (hasStaticInitializerMethod == null) { - Class classWithThisMethod = null; + Class classWithThisMethod = null; try { - try { - // When using rip-int with Merlin or when this is a Merlin - // workspace, the method we want is in sun.misc.ClassReflector - // and absent from java.io.ObjectStreamClass. - // - // When compiling rip-int with JDK 1.3.x, we have to get it - // from java.io.ObjectStreamClass. - classWithThisMethod = Class.forName("sun.misc.ClassReflector"); - } catch (ClassNotFoundException cnfe) { - // Do nothing. This is either not a Merlin workspace, - // or rip-int is being compiled with something other than - // Merlin, probably JDK 1.3. Fall back on java.io.ObjectStreaClass. - } if (classWithThisMethod == null) classWithThisMethod = java.io.ObjectStreamClass.class; hasStaticInitializerMethod = classWithThisMethod.getDeclaredMethod("hasStaticInitializer", - new Class[] { Class.class }); + new Class[] { Class.class }); } catch (NoSuchMethodException ex) { } @@ -1596,22 +1584,6 @@ } - /* The Class Object for java.io.Serializable */ - private static Class classSerializable = null; - private static Class classExternalizable = null; - - /* - * Resolve java.io.Serializable at load time. - */ - static { - try { - classSerializable = Class.forName("java.io.Serializable"); - classExternalizable = Class.forName("java.io.Externalizable"); - } catch (Throwable e) { - System.err.println("Could not load java.io.Serializable or java.io.Externalizable."); - } - } - /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -6120832682080437368L; @@ -1649,8 +1621,8 @@ private static class CompareClassByName implements Comparator { public int compare(Object o1, Object o2) { - Class c1 = (Class)o1; - Class c2 = (Class)o2; + Class c1 = (Class)o1; + Class c2 = (Class)o2; return (c1.getName()).compareTo(c2.getName()); } } @@ -1764,12 +1736,12 @@ * * Copied from the Merlin java.io.ObjectStreamClass. */ - private static Method getInheritableMethod(Class cl, String name, - Class[] argTypes, - Class returnType) + private static Method getInheritableMethod(Class cl, String name, + Class[] argTypes, + Class returnType) { Method meth = null; - Class defCl = cl; + Class defCl = cl; while (defCl != null) { try { meth = defCl.getDeclaredMethod(name, argTypes); @@ -1801,7 +1773,7 @@ * * Copied from the Merlin java.io.ObjectStreamClass. */ - private static boolean packageEquals(Class cl1, Class cl2) { + private static boolean packageEquals(Class cl1, Class cl2) { Package pkg1 = cl1.getPackage(), pkg2 = cl2.getPackage(); return ((pkg1 == pkg2) || ((pkg1 != null) && (pkg1.equals(pkg2)))); } diff -r 16ec7c58cdea -r cb2cf6e2958a corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java --- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java Thu Apr 17 15:23:23 2014 -0700 +++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -94,7 +94,7 @@ }); } - public static long computeStructuralUID(boolean hasWriteObject, Class cl) { + public static long computeStructuralUID(boolean hasWriteObject, Class cl) { ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); long h = 0; @@ -119,7 +119,7 @@ // Object method in there // Get SUID of parent - Class parent = cl.getSuperclass(); + Class parent = cl.getSuperclass(); if ((parent != null) && (parent != java.lang.Object.class)) { boolean hasWriteObjectFlag = false; Class [] args = {java.io.ObjectOutputStream.class}; @@ -503,19 +503,6 @@ Class classWithThisMethod = null; try { - try { - // When using rip-int with Merlin or when this is a Merlin - // workspace, the method we want is in sun.misc.ClassReflector - // and absent from java.io.ObjectStreamClass. - // - // When compiling rip-int with JDK 1.3.x, we have to get it - // from java.io.ObjectStreamClass. - classWithThisMethod = Class.forName("sun.misc.ClassReflector"); - } catch (ClassNotFoundException cnfe) { - // Do nothing. This is either not a Merlin workspace, - // or rip-int is being compiled with something other than - // Merlin, probably JDK 1.3. Fall back on java.io.ObjectStreaClass. - } if (classWithThisMethod == null) classWithThisMethod = java.io.ObjectStreamClass.class; diff -r 16ec7c58cdea -r cb2cf6e2958a corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java --- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java Thu Apr 17 15:23:23 2014 -0700 +++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, 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 @@ -53,6 +53,7 @@ import java.io.ByteArrayOutputStream; import java.io.InvalidClassException; import java.io.Serializable; +import java.io.Externalizable; import java.util.Arrays; import java.util.Comparator; @@ -88,7 +89,7 @@ public static final long kDefaultUID = -1; private static Object noArgsList[] = {}; - private static Class noTypesList[] = {}; + private static Class noTypesList[] = {}; private static Hashtable translatedFields; @@ -96,7 +97,7 @@ * is returned if the specified class does not implement * java.io.Serializable or java.io.Externalizable. */ - static final ObjectStreamClass_1_3_1 lookup(Class cl) + static final ObjectStreamClass_1_3_1 lookup(Class cl) { ObjectStreamClass_1_3_1 desc = lookupInternal(cl); if (desc.isSerializable() || desc.isExternalizable()) @@ -108,7 +109,7 @@ * Find the class descriptor for the specified class. * Package access only so it can be called from ObjectIn/OutStream. */ - static ObjectStreamClass_1_3_1 lookupInternal(Class cl) + static ObjectStreamClass_1_3_1 lookupInternal(Class cl) { /* Synchronize on the hashtable so no two threads will do * this at the same time. @@ -122,13 +123,13 @@ } /* Check if it's serializable */ - boolean serializable = classSerializable.isAssignableFrom(cl); + boolean serializable = Serializable.class.isAssignableFrom(cl); /* If the class is only Serializable, * lookup the descriptor for the superclass. */ ObjectStreamClass_1_3_1 superdesc = null; if (serializable) { - Class superclass = cl.getSuperclass(); + Class superclass = cl.getSuperclass(); if (superclass != null) superdesc = lookup(superclass); } @@ -141,7 +142,7 @@ if (serializable) { externalizable = ((superdesc != null) && superdesc.isExternalizable()) || - classExternalizable.isAssignableFrom(cl); + Externalizable.class.isAssignableFrom(cl); if (externalizable) { serializable = false; } @@ -170,7 +171,7 @@ * that have evolved from a common root class and agree to be serialized * and deserialized using a common format. */ - public static final long getSerialVersionUID( java.lang.Class clazz) { + public static final long getSerialVersionUID( java.lang.Class clazz) { ObjectStreamClass_1_3_1 theosc = ObjectStreamClass_1_3_1.lookup( clazz ); if( theosc != null ) { @@ -204,7 +205,7 @@ /** * Return the actual (computed) serialVersionUID for this class. */ - public static final long getActualSerialVersionUID( java.lang.Class clazz ) + public static final long getActualSerialVersionUID( java.lang.Class clazz ) { ObjectStreamClass_1_3_1 theosc = ObjectStreamClass_1_3_1.lookup( clazz ); if( theosc != null ) @@ -234,7 +235,7 @@ * Return the class in the local VM that this version is mapped to. * Null is returned if there is no corresponding local class. */ - public final Class forClass() { + public final Class forClass() { return ofClass; } @@ -333,7 +334,7 @@ * Create a new ObjectStreamClass_1_3_1 from a loaded class. * Don't call this directly, call lookup instead. */ - private ObjectStreamClass_1_3_1(java.lang.Class cl, ObjectStreamClass_1_3_1 superdesc, + private ObjectStreamClass_1_3_1(java.lang.Class cl, ObjectStreamClass_1_3_1 superdesc, boolean serial, boolean extern) { ofClass = cl; /* created from this class */ @@ -376,7 +377,7 @@ private void init() { synchronized (lock) { - final Class cl = ofClass; + final Class cl = ofClass; if (fields != null) // already initialized return; @@ -558,7 +559,7 @@ * will call it as necessary. */ try { - Class[] args = {java.io.ObjectOutputStream.class}; + Class[] args = {java.io.ObjectOutputStream.class}; writeObjectMethod = cl.getDeclaredMethod("writeObject", args); hasWriteObjectMethod = true; int mods = writeObjectMethod.getModifiers(); @@ -578,7 +579,7 @@ * ObjectInputStream so it can all the method directly. */ try { - Class[] args = {java.io.ObjectInputStream.class}; + Class[] args = {java.io.ObjectInputStream.class}; readObjectMethod = cl.getDeclaredMethod("readObject", args); int mods = readObjectMethod.getModifiers(); @@ -629,11 +630,11 @@ if (translation != null) return translation; else { - Class osfClass = com.sun.corba.se.impl.orbutil.ObjectStreamField.class; + Class osfClass = com.sun.corba.se.impl.orbutil.ObjectStreamField.class; translation = (Object[])java.lang.reflect.Array.newInstance(osfClass, objs.length); Object arg[] = new Object[2]; - Class types[] = {String.class, Class.class}; + Class types[] = {String.class, Class.class}; Constructor constructor = osfClass.getDeclaredConstructor(types); for (int i = fields.length -1; i >= 0; i--){ arg[0] = fields[i].getName(); @@ -804,7 +805,7 @@ } } - private static long computeStructuralUID(ObjectStreamClass_1_3_1 osc, Class cl) { + private static long computeStructuralUID(ObjectStreamClass_1_3_1 osc, Class cl) { ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); long h = 0; @@ -824,7 +825,7 @@ DataOutputStream data = new DataOutputStream(mdo); // Get SUID of parent - Class parent = cl.getSuperclass(); + Class parent = cl.getSuperclass(); if ((parent != null)) // SerialBug 1; acc. to spec the one for // java.lang.object @@ -910,10 +911,10 @@ /** * Compute the JVM signature for the class. */ - static String getSignature(Class clazz) { + static String getSignature(Class clazz) { String type = null; if (clazz.isArray()) { - Class cl = clazz; + Class cl = clazz; int dimensions = 0; while (cl.isArray()) { dimensions++; @@ -959,7 +960,7 @@ sb.append("("); - Class[] params = meth.getParameterTypes(); // avoid clone + Class[] params = meth.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } @@ -976,7 +977,7 @@ sb.append("("); - Class[] params = cons.getParameterTypes(); // avoid clone + Class[] params = cons.getParameterTypes(); // avoid clone for (int j = 0; j < params.length; j++) { sb.append(getSignature(params[j])); } @@ -996,7 +997,7 @@ * The entries are extended from java.lang.ref.SoftReference so the * gc will be able to free them if needed. */ - private static ObjectStreamClass_1_3_1 findDescriptorFor(Class cl) { + private static ObjectStreamClass_1_3_1 findDescriptorFor(Class cl) { int hash = cl.hashCode(); int index = (hash & 0x7FFFFFFF) % descriptorFor.length; @@ -1077,7 +1078,7 @@ /* * Class that is a descriptor for in this virtual machine. */ - private Class ofClass; + private Class ofClass; /* * True if descriptor for a proxy class. @@ -1130,22 +1131,6 @@ /* Get the private static final field for serial version UID */ // private static native long getSerialVersionUIDField(Class cl); - /* The Class Object for java.io.Serializable */ - private static Class classSerializable = null; - private static Class classExternalizable = null; - - /* - * Resolve java.io.Serializable at load time. - */ - static { - try { - classSerializable = Class.forName("java.io.Serializable"); - classExternalizable = Class.forName("java.io.Externalizable"); - } catch (Throwable e) { - System.err.println("Could not load java.io.Serializable or java.io.Externalizable."); - } - } - /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -6120832682080437368L; @@ -1183,8 +1168,8 @@ private static class CompareClassByName implements Comparator { public int compare(Object o1, Object o2) { - Class c1 = (Class)o1; - Class c2 = (Class)o2; + Class c1 = (Class)o1; + Class c2 = (Class)o2; return (c1.getName()).compareTo(c2.getName()); } } diff -r 16ec7c58cdea -r cb2cf6e2958a corba/src/share/classes/org/omg/CORBA/ORB.java --- a/corba/src/share/classes/org/omg/CORBA/ORB.java Thu Apr 17 15:23:23 2014 -0700 +++ b/corba/src/share/classes/org/omg/CORBA/ORB.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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,6 +36,8 @@ import java.security.AccessController; import java.security.PrivilegedAction; +import sun.reflect.misc.ReflectUtil; + /** * A class providing APIs for the CORBA Object Request Broker * features. The ORB class also provides @@ -161,6 +163,20 @@ *

* An application or applet can be initialized in one or more ORBs. * ORB initialization is a bootstrap call into the CORBA world. + * + * + * @implNote + * As described above it is possible to specify, at runtime, an alternative ORBSingleton class and + * an alternative ORB implementation class, via the system properties {@code org.omg.CORBA.ORBSingletonClass} + * and {@code org.omg.CORBA.ORBClass} respectively. + * The class loading strategy is organized, such that, in the case of the ORBSingleton + * the system class loader is used to load the alternative singleton ORB. + * Thus, it is necessary that an application's CLASSPATH + * includes the classes for this alternative ORBSingleton, when specified. + * + * In the case of specifying an alternative ORB implementation class, the loading + * strategy will use the thread context class loader, as appropriate. + * * @since JDK1.2 */ abstract public class ORB { @@ -289,20 +305,38 @@ (className.equals("com.sun.corba.se.impl.orb.ORBSingleton"))) { singleton = new com.sun.corba.se.impl.orb.ORBSingleton(); } else { - singleton = create_impl(className); + singleton = create_impl_with_systemclassloader(className); } } return singleton; } + private static ORB create_impl_with_systemclassloader(String className) { + + try { + ReflectUtil.checkPackageAccess(className); + ClassLoader cl = ClassLoader.getSystemClassLoader(); + Class orbBaseClass = org.omg.CORBA.ORB.class; + Class singletonOrbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass); + return (ORB)singletonOrbClass.newInstance(); + } catch (Throwable ex) { + SystemException systemException = new INITIALIZE( + "can't instantiate default ORB implementation " + className); + systemException.initCause(ex); + throw systemException; + } + } + private static ORB create_impl(String className) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) cl = ClassLoader.getSystemClassLoader(); try { - return (ORB) Class.forName(className, true, cl).newInstance(); + ReflectUtil.checkPackageAccess(className); + Class orbBaseClass = org.omg.CORBA.ORB.class; + Class orbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass); + return (ORB)orbClass.newInstance(); } catch (Throwable ex) { SystemException systemException = new INITIALIZE( "can't instantiate default ORB implementation " + className); @@ -346,7 +380,6 @@ } else { orb = create_impl(className); } - orb.set_parameters(args, props); return orb; } @@ -377,7 +410,6 @@ } else { orb = create_impl(className); } - orb.set_parameters(app, props); return orb; } @@ -573,7 +605,7 @@ try { // First try to load the OperationDef class String opDefClassName = "org.omg.CORBA.OperationDef"; - Class opDefClass = null; + Class opDefClass = null; ClassLoader cl = Thread.currentThread().getContextClassLoader(); if ( cl == null ) @@ -583,7 +615,7 @@ // OK, we loaded OperationDef. Now try to get the // create_operation_list(OperationDef oper) method. - Class[] argc = { opDefClass }; + Class[] argc = { opDefClass }; java.lang.reflect.Method meth = this.getClass().getMethod("create_operation_list", argc); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/.hgtags --- a/hotspot/.hgtags Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/.hgtags Wed Jul 05 19:37:43 2017 +0200 @@ -411,3 +411,4 @@ 52377a30a3f87b62d6135706997b8c7a47366e37 jdk9-b06 52f7edf2589d9f9d35db3008bc5377f279de9c18 jdk9-b07 4dedef5e51ed3a36677a8ba82949fc517ad64162 jdk9-b08 +05e8f5242c26ba45d4fa947e4f4f54c058c9b522 jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -958,7 +958,7 @@ // reset handle block __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), G3_scratch); - __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); // handle exceptions (exception handling will handle unlocking!) diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -2687,7 +2687,7 @@ if (!is_critical_native) { // reset handle block __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5); - __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, L5, JNIHandleBlock::top_offset_in_bytes()); __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch); check_forward_pending_exception(masm, G3_scratch); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1147,7 +1147,7 @@ // reset handle block __ ld_ptr(G2_thread, JavaThread::active_handles_offset(), G3_scratch); - __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); // If we have an oop result store it where it will be safe for any further gc // until we return now that we've released the handle it might be protected by diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1358,7 +1358,7 @@ // reset handle block __ movptr(t, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); // If result was an oop then unbox and save it in the frame { Label L; diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -162,7 +162,7 @@ "Number of milliseconds to wait before start calculating aborts " \ "for RTM locking") \ \ - experimental(bool, UseRTMXendForLockBusy, false, \ + experimental(bool, UseRTMXendForLockBusy, true, \ "Use RTM Xend instead of Xabort when lock busy") \ \ /* assembler */ \ diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1488,11 +1488,10 @@ movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort bind(L_rtm_retry); } - if (!UseRTMXendForLockBusy) { - movptr(tmpReg, Address(objReg, 0)); - testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased - jcc(Assembler::notZero, IsInflated); - } + movptr(tmpReg, Address(objReg, 0)); + testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jcc(Assembler::notZero, IsInflated); + if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { @@ -1512,10 +1511,7 @@ Register abort_status_Reg = tmpReg; // status of abort is stored in RAX if (UseRTMXendForLockBusy) { xend(); - movptr(tmpReg, Address(objReg, 0)); - testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased - jcc(Assembler::notZero, IsInflated); - movptr(abort_status_Reg, 0x1); // Set the abort status to 1 (as xabort does) + movptr(abort_status_Reg, 0x2); // Set the abort status to 2 (so we can retry) jmp(L_decrement_retry); } else { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -2266,7 +2266,7 @@ if (!is_critical_native) { // reset handle block __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // Any exception pending? __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -2509,7 +2509,7 @@ if (!is_critical_native) { // reset handle block __ movptr(rcx, Address(r15_thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); } // pop our frame diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1287,7 +1287,7 @@ // reset handle block __ movptr(t, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // If result was an oop then unbox and save it in the frame { Label L; diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1259,7 +1259,7 @@ // reset handle block __ movptr(t, Address(r15_thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); // If result is an oop unbox and store it in frame where gc will see it // and result handler will pick it up diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2014 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2811,18 +2811,13 @@ os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN; } -void os::yield_all(int attempts) { +void os::yield_all() { // Yields to all threads, including threads with lower priorities // Threads on Linux are all with same priority. The Solaris style // os::yield_all() with nanosleep(1ms) is not necessary. sched_yield(); } -// Called from the tight loops to possibly influence time-sharing heuristics -void os::loop_breaker(int attempts) { - os::yield_all(attempts); -} - //////////////////////////////////////////////////////////////////////////////// // thread priority support @@ -3079,7 +3074,7 @@ for (int n = 0; !osthread->sr.is_suspended(); n++) { for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) { - os::yield_all(i); + os::yield_all(); } // timeout, try to cancel the request @@ -3113,7 +3108,7 @@ if (sr_notify(osthread) == 0) { for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) { for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) { - os::yield_all(i); + os::yield_all(); } } } else { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -917,9 +917,20 @@ ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; } @@ -2551,18 +2562,13 @@ os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;} -void os::yield_all(int attempts) { +void os::yield_all() { // Yields to all threads, including threads with lower priorities // Threads on Bsd are all with same priority. The Solaris style // os::yield_all() with nanosleep(1ms) is not necessary. sched_yield(); } -// Called from the tight loops to possibly influence time-sharing heuristics -void os::loop_breaker(int attempts) { - os::yield_all(attempts); -} - //////////////////////////////////////////////////////////////////////////////// // thread priority support diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1032,9 +1032,20 @@ ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; } @@ -3781,18 +3792,13 @@ os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;} -void os::yield_all(int attempts) { +void os::yield_all() { // Yields to all threads, including threads with lower priorities // Threads on Linux are all with same priority. The Solaris style // os::yield_all() with nanosleep(1ms) is not necessary. sched_yield(); } -// Called from the tight loops to possibly influence time-sharing heuristics -void os::loop_breaker(int attempts) { - os::yield_all(attempts); -} - //////////////////////////////////////////////////////////////////////////////// // thread priority support diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/solaris/vm/attachListener_solaris.cpp --- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -29,6 +29,7 @@ #include "services/dtraceAttacher.hpp" #include +#include #include #include #include @@ -668,11 +669,13 @@ out->print_cr("No probe specified"); return JNI_ERR; } else { - int probe_typess = atoi(probe); - if (errno) { + char *end; + long val = strtol(probe, &end, 10); + if (end == probe || val < 0 || val > INT_MAX) { out->print_cr("invalid probe type"); return JNI_ERR; } else { + int probe_typess = (int) val; DTrace::enable_dprobes(probe_typess); return JNI_OK; } @@ -703,8 +706,9 @@ bool flag = true; const char* arg1; if ((arg1 = op->arg(1)) != NULL) { - flag = (atoi(arg1) != 0); - if (errno) { + char *end; + flag = (strtol(arg1, &end, 10) != 0); + if (arg1 == end) { out->print_cr("flag value has to be an integer"); return JNI_ERR; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/solaris/vm/osThread_solaris.cpp --- a/hotspot/src/os/solaris/vm/osThread_solaris.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/solaris/vm/osThread_solaris.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -49,16 +49,6 @@ // copied from synchronizer.cpp -void OSThread::handle_spinlock_contention(int tries) { - if (NoYieldsInMicrolock) return; - - if (tries > 10) { - os::yield_all(tries); // Yield to threads of any priority - } else if (tries > 5) { - os::yield(); // Yield to threads of same or higher priority - } -} - void OSThread::SR_handler(Thread* thread, ucontext_t* uc) { os::Solaris::SR_handler(thread, uc); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/solaris/vm/osThread_solaris.hpp --- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -82,8 +82,6 @@ void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; } static void SR_handler(Thread* thread, ucontext_t* uc); - static void handle_spinlock_contention(int tries); // Used for thread local eden locking - // *************************************************************** // Platform dependent initialization and cleanup // *************************************************************** diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/solaris/vm/os_solaris.cpp --- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -969,9 +969,6 @@ return true; } -// _T2_libthread is true if we believe we are running with the newer -// SunSoft lwp/libthread.so (2.8 patch, 2.9 default) -bool os::Solaris::_T2_libthread = false; bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { // Allocate the OSThread object @@ -1056,71 +1053,10 @@ thread->set_osthread(osthread); // Create the Solaris thread - // explicit THR_BOUND for T2_libthread case in case - // that assumption is not accurate, but our alternate signal stack - // handling is based on it which must have bound threads thread_t tid = 0; - long flags = (UseDetachedThreads ? THR_DETACHED : 0) | THR_SUSPENDED - | ((UseBoundThreads || os::Solaris::T2_libthread() || - (thr_type == vm_thread) || - (thr_type == cgc_thread) || - (thr_type == pgc_thread) || - (thr_type == compiler_thread && BackgroundCompilation)) ? - THR_BOUND : 0); + long flags = (UseDetachedThreads ? THR_DETACHED : 0) | THR_SUSPENDED; int status; - // 4376845 -- libthread/kernel don't provide enough LWPs to utilize all CPUs. - // - // On multiprocessors systems, libthread sometimes under-provisions our - // process with LWPs. On a 30-way systems, for instance, we could have - // 50 user-level threads in ready state and only 2 or 3 LWPs assigned - // to our process. This can result in under utilization of PEs. - // I suspect the problem is related to libthread's LWP - // pool management and to the kernel's SIGBLOCKING "last LWP parked" - // upcall policy. - // - // The following code is palliative -- it attempts to ensure that our - // process has sufficient LWPs to take advantage of multiple PEs. - // Proper long-term cures include using user-level threads bound to LWPs - // (THR_BOUND) or using LWP-based synchronization. Note that there is a - // slight timing window with respect to sampling _os_thread_count, but - // the race is benign. Also, we should periodically recompute - // _processors_online as the min of SC_NPROCESSORS_ONLN and the - // the number of PEs in our partition. You might be tempted to use - // THR_NEW_LWP here, but I'd recommend against it as that could - // result in undesirable growth of the libthread's LWP pool. - // The fix below isn't sufficient; for instance, it doesn't take into count - // LWPs parked on IO. It does, however, help certain CPU-bound benchmarks. - // - // Some pathologies this scheme doesn't handle: - // * Threads can block, releasing the LWPs. The LWPs can age out. - // When a large number of threads become ready again there aren't - // enough LWPs available to service them. This can occur when the - // number of ready threads oscillates. - // * LWPs/Threads park on IO, thus taking the LWP out of circulation. - // - // Finally, we should call thr_setconcurrency() periodically to refresh - // the LWP pool and thwart the LWP age-out mechanism. - // The "+3" term provides a little slop -- we want to slightly overprovision. - - if (AdjustConcurrency && os::Solaris::_os_thread_count < (_processors_online+3)) { - if (!(flags & THR_BOUND)) { - thr_setconcurrency (os::Solaris::_os_thread_count); // avoid starvation - } - } - // Although this doesn't hurt, we should warn of undefined behavior - // when using unbound T1 threads with schedctl(). This should never - // happen, as the compiler and VM threads are always created bound - DEBUG_ONLY( - if ((VMThreadHintNoPreempt || CompilerThreadHintNoPreempt) && - (!os::Solaris::T2_libthread() && (!(flags & THR_BOUND))) && - ((thr_type == vm_thread) || (thr_type == cgc_thread) || - (thr_type == pgc_thread) || (thr_type == compiler_thread && BackgroundCompilation))) { - warning("schedctl behavior undefined when Compiler/VM/GC Threads are Unbound"); - } - ); - - // Mark that we don't have an lwp or thread id yet. // In case we attempt to set the priority before the thread starts. osthread->set_lwp_id(-1); @@ -1145,13 +1081,6 @@ // Remember that we created this thread so we can set priority on it osthread->set_vm_created(); - // Set the default thread priority. If using bound threads, setting - // lwp priority will be delayed until thread start. - set_native_priority(thread, - DefaultThreadPriority == -1 ? - java_to_os_priority[NormPriority] : - DefaultThreadPriority); - // Initial thread state is INITIALIZED, not SUSPENDED osthread->set_state(INITIALIZED); @@ -1333,39 +1262,8 @@ jt->set_stack_size(stack_size); } - // 5/22/01: Right now alternate signal stacks do not handle - // throwing stack overflow exceptions, see bug 4463178 - // Until a fix is found for this, T2 will NOT imply alternate signal - // stacks. - // If using T2 libthread threads, install an alternate signal stack. - // Because alternate stacks associate with LWPs on Solaris, - // see sigaltstack(2), if using UNBOUND threads, or if UseBoundThreads - // we prefer to explicitly stack bang. - // If not using T2 libthread, but using UseBoundThreads any threads - // (primordial thread, jni_attachCurrentThread) we do not create, - // probably are not bound, therefore they can not have an alternate - // signal stack. Since our stack banging code is generated and - // is shared across threads, all threads must be bound to allow - // using alternate signal stacks. The alternative is to interpose - // on _lwp_create to associate an alt sig stack with each LWP, - // and this could be a problem when the JVM is embedded. - // We would prefer to use alternate signal stacks with T2 - // Since there is currently no accurate way to detect T2 - // we do not. Assuming T2 when running T1 causes sig 11s or assertions - // on installing alternate signal stacks - - - // 05/09/03: removed alternate signal stack support for Solaris - // The alternate signal stack mechanism is no longer needed to - // handle stack overflow. This is now handled by allocating - // guard pages (red zone) and stackbanging. - // Initially the alternate signal stack mechanism was removed because - // it did not work with T1 llibthread. Alternate - // signal stacks MUST have all threads bound to lwps. Applications - // can create their own threads and attach them without their being - // bound under T1. This is frequently the case for the primordial thread. - // If we were ever to reenable this mechanism we would need to - // use the dynamic check for T2 libthread. + // With the T2 libthread (T1 is no longer supported) threads are always bound + // and we use stackbanging in all cases. os::Solaris::init_thread_fpu_state(); std::set_terminate(_handle_uncaught_cxx_exception); @@ -2092,12 +1990,7 @@ } void os::Solaris::print_libversion_info(outputStream* st) { - if (os::Solaris::T2_libthread()) { - st->print(" (T2 libthread)"); - } - else { - st->print(" (T1 libthread)"); - } + st->print(" (T2 libthread)"); st->cr(); } @@ -3323,41 +3216,10 @@ os::YieldResult os::NakedYield() { thr_yield(); return os::YIELD_UNKNOWN; } - -// On Solaris we found that yield_all doesn't always yield to all other threads. -// There have been cases where there is a thread ready to execute but it doesn't -// get an lwp as the VM thread continues to spin with sleeps of 1 millisecond. -// The 1 millisecond wait doesn't seem long enough for the kernel to issue a -// SIGWAITING signal which will cause a new lwp to be created. So we count the -// number of times yield_all is called in the one loop and increase the sleep -// time after 8 attempts. If this fails too we increase the concurrency level -// so that the starving thread would get an lwp - -void os::yield_all(int attempts) { +void os::yield_all() { // Yields to all threads, including threads with lower priorities - if (attempts == 0) { - os::sleep(Thread::current(), 1, false); - } else { - int iterations = attempts % 30; - if (iterations == 0 && !os::Solaris::T2_libthread()) { - // thr_setconcurrency and _getconcurrency make sense only under T1. - int noofLWPS = thr_getconcurrency(); - if (noofLWPS < (Threads::number_of_threads() + 2)) { - thr_setconcurrency(thr_getconcurrency() + 1); - } - } else if (iterations < 25) { - os::sleep(Thread::current(), 1, false); - } else { - os::sleep(Thread::current(), 10, false); - } - } -} - -// Called from the tight loops to possibly influence time-sharing heuristics -void os::loop_breaker(int attempts) { - os::yield_all(attempts); -} - + os::sleep(Thread::current(), 1, false); +} // Interface for setting lwp priorities. If we are using T2 libthread, // which forces the use of BoundThreads or we manually set UseBoundThreads, @@ -3365,6 +3227,9 @@ // function is meaningless in this mode so we must adjust the real lwp's priority // The routines below implement the getting and setting of lwp priorities. // +// Note: T2 is now the only supported libthread. UseBoundThreads flag is +// being deprecated and all threads are now BoundThreads +// // Note: There are three priority scales used on Solaris. Java priotities // which range from 1 to 10, libthread "thr_setprio" scale which range // from 0 to 127, and the current scheduling class of the process we @@ -3437,29 +3302,19 @@ if (!UseThreadPriorities) return 0; - // We are using Bound threads, we need to determine our priority ranges - if (os::Solaris::T2_libthread() || UseBoundThreads) { - // If ThreadPriorityPolicy is 1, switch tables - if (ThreadPriorityPolicy == 1) { - for (i = 0 ; i < CriticalPriority+1; i++) - os::java_to_os_priority[i] = prio_policy1[i]; - } - if (UseCriticalJavaThreadPriority) { - // MaxPriority always maps to the FX scheduling class and criticalPrio. - // See set_native_priority() and set_lwp_class_and_priority(). - // Save original MaxPriority mapping in case attempt to - // use critical priority fails. - java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority]; - // Set negative to distinguish from other priorities - os::java_to_os_priority[MaxPriority] = -criticalPrio; - } - } - // Not using Bound Threads, set to ThreadPolicy 1 - else { - for ( i = 0 ; i < CriticalPriority+1; i++ ) { + // If ThreadPriorityPolicy is 1, switch tables + if (ThreadPriorityPolicy == 1) { + for (i = 0 ; i < CriticalPriority+1; i++) os::java_to_os_priority[i] = prio_policy1[i]; - } - return 0; + } + if (UseCriticalJavaThreadPriority) { + // MaxPriority always maps to the FX scheduling class and criticalPrio. + // See set_native_priority() and set_lwp_class_and_priority(). + // Save original MaxPriority mapping in case attempt to + // use critical priority fails. + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority]; + // Set negative to distinguish from other priorities + os::java_to_os_priority[MaxPriority] = -criticalPrio; } // Get IDs for a set of well-known scheduling classes. @@ -3583,10 +3438,6 @@ // set_lwp_class_and_priority -// -// Set the class and priority of the lwp. This call should only -// be made when using bound threads (T2 threads are bound by default). -// int set_lwp_class_and_priority(int ThreadID, int lwpid, int newPrio, int new_class, bool scale) { int rslt; @@ -3812,23 +3663,20 @@ status = thr_setprio(thread->osthread()->thread_id(), newpri); } - if (os::Solaris::T2_libthread() || - (UseBoundThreads && osthread->is_vm_created())) { - int lwp_status = - set_lwp_class_and_priority(osthread->thread_id(), - osthread->lwp_id(), - newpri, - fxcritical ? fxLimits.schedPolicy : myClass, - !fxcritical); - if (lwp_status != 0 && fxcritical) { - // Try again, this time without changing the scheduling class - newpri = java_MaxPriority_to_os_priority; - lwp_status = set_lwp_class_and_priority(osthread->thread_id(), - osthread->lwp_id(), - newpri, myClass, false); - } - status |= lwp_status; - } + int lwp_status = + set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, + fxcritical ? fxLimits.schedPolicy : myClass, + !fxcritical); + if (lwp_status != 0 && fxcritical) { + // Try again, this time without changing the scheduling class + newpri = java_MaxPriority_to_os_priority; + lwp_status = set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, myClass, false); + } + status |= lwp_status; return (status == 0) ? OS_OK : OS_ERR; } @@ -4495,13 +4343,6 @@ } } -// (Static) wrappers for the new libthread API -int_fnP_thread_t_iP_uP_stack_tP_gregset_t os::Solaris::_thr_getstate; -int_fnP_thread_t_i_gregset_t os::Solaris::_thr_setstate; -int_fnP_thread_t_i os::Solaris::_thr_setmutator; -int_fnP_thread_t os::Solaris::_thr_suspend_mutator; -int_fnP_thread_t os::Solaris::_thr_continue_mutator; - // (Static) wrapper for getisax(2) call. os::Solaris::getisax_func_t os::Solaris::_getisax = 0; @@ -4536,78 +4377,9 @@ return addr; } - - -// isT2_libthread() -// -// Routine to determine if we are currently using the new T2 libthread. -// -// We determine if we are using T2 by reading /proc/self/lstatus and -// looking for a thread with the ASLWP bit set. If we find this status -// bit set, we must assume that we are NOT using T2. The T2 team -// has approved this algorithm. -// -// We need to determine if we are running with the new T2 libthread -// since setting native thread priorities is handled differently -// when using this library. All threads created using T2 are bound -// threads. Calling thr_setprio is meaningless in this case. -// -bool isT2_libthread() { - static prheader_t * lwpArray = NULL; - static int lwpSize = 0; - static int lwpFile = -1; - lwpstatus_t * that; - char lwpName [128]; - bool isT2 = false; - -#define ADR(x) ((uintptr_t)(x)) -#define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) - - lwpFile = ::open("/proc/self/lstatus", O_RDONLY, 0); - if (lwpFile < 0) { - if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n"); - return false; - } - lwpSize = 16*1024; - for (;;) { - ::lseek64 (lwpFile, 0, SEEK_SET); - lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize, mtInternal); - if (::read(lwpFile, lwpArray, lwpSize) < 0) { - if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n"); - break; - } - if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) { - // We got a good snapshot - now iterate over the list. - int aslwpcount = 0; - for (int i = 0; i < lwpArray->pr_nent; i++ ) { - that = LWPINDEX(lwpArray,i); - if (that->pr_flags & PR_ASLWP) { - aslwpcount++; - } - } - if (aslwpcount == 0) isT2 = true; - break; - } - lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize; - FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal); // retry. - } - - FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal); - ::close (lwpFile); - if (ThreadPriorityVerbose) { - if (isT2) tty->print_cr("We are running with a T2 libthread\n"); - else tty->print_cr("We are not running with a T2 libthread\n"); - } - return isT2; -} - - void os::Solaris::libthread_init() { address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators"); - // Determine if we are running with the new T2 libthread - os::Solaris::set_T2_libthread(isT2_libthread()); - lwp_priocntl_init(); // RTLD_DEFAULT was not defined on some early versions of 5.5.1 @@ -4618,22 +4390,6 @@ guarantee(func != NULL, "libthread.so is too old."); } - // Initialize the new libthread getstate API wrappers - func = resolve_symbol("thr_getstate"); - os::Solaris::set_thr_getstate(CAST_TO_FN_PTR(int_fnP_thread_t_iP_uP_stack_tP_gregset_t, func)); - - func = resolve_symbol("thr_setstate"); - os::Solaris::set_thr_setstate(CAST_TO_FN_PTR(int_fnP_thread_t_i_gregset_t, func)); - - func = resolve_symbol("thr_setmutator"); - os::Solaris::set_thr_setmutator(CAST_TO_FN_PTR(int_fnP_thread_t_i, func)); - - func = resolve_symbol("thr_suspend_mutator"); - os::Solaris::set_thr_suspend_mutator(CAST_TO_FN_PTR(int_fnP_thread_t, func)); - - func = resolve_symbol("thr_continue_mutator"); - os::Solaris::set_thr_continue_mutator(CAST_TO_FN_PTR(int_fnP_thread_t, func)); - int size; void (*handler_info_func)(address *, int *); handler_info_func = CAST_TO_FN_PTR(void (*)(address *, int *), resolve_symbol("thr_sighndlrinfo")); @@ -5536,11 +5292,7 @@ } bool os::is_thread_cpu_time_supported() { - if ( os::Solaris::T2_libthread() || UseBoundThreads ) { - return true; - } else { - return false; - } + return true; } // System loadavg support. Returns -1 if load average cannot be obtained. diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/solaris/vm/os_solaris.hpp --- a/hotspot/src/os/solaris/vm/os_solaris.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -41,19 +41,6 @@ #define TRS_LWPID 2 #define TRS_INVALID 3 - // _T2_libthread is true if we believe we are running with the newer - // SunSoft lib/lwp/libthread: default Solaris 9, available Solaris 8 - // which is a lightweight libthread that also supports all T1 - static bool _T2_libthread; - // These refer to new libthread interface functions - // They get intialized if we dynamically detect new libthread - static int_fnP_thread_t_iP_uP_stack_tP_gregset_t _thr_getstate; - static int_fnP_thread_t_i_gregset_t _thr_setstate; - static int_fnP_thread_t_i _thr_setmutator; - static int_fnP_thread_t _thr_suspend_mutator; - static int_fnP_thread_t _thr_continue_mutator; - // libthread_init sets the above, if the new functionality is detected - // initialized to libthread or lwp synchronization primitives depending on UseLWPSychronization static int_fnP_mutex_tP _mutex_lock; static int_fnP_mutex_tP _mutex_trylock; @@ -214,29 +201,6 @@ static struct sigaction *get_chained_signal_action(int sig); static bool chained_handler(int sig, siginfo_t *siginfo, void *context); - // The following allow us to link against both the old and new libthread (2.8) - // and exploit the new libthread functionality if available. - - static bool T2_libthread() { return _T2_libthread; } - static void set_T2_libthread(bool T2_libthread) { _T2_libthread = T2_libthread; } - - static int thr_getstate(thread_t tid, int *flag, unsigned *lwp, stack_t *ss, gregset_t rs) - { return _thr_getstate(tid, flag, lwp, ss, rs); } - static void set_thr_getstate(int_fnP_thread_t_iP_uP_stack_tP_gregset_t func) - { _thr_getstate = func; } - - static int thr_setstate(thread_t tid, int flag, gregset_t rs) { return _thr_setstate(tid, flag, rs); } - static void set_thr_setstate(int_fnP_thread_t_i_gregset_t func) { _thr_setstate = func; } - - static int thr_setmutator(thread_t tid, int enabled) { return _thr_setmutator(tid, enabled); } - static void set_thr_setmutator(int_fnP_thread_t_i func) { _thr_setmutator = func; } - - static int thr_suspend_mutator(thread_t tid) { return _thr_suspend_mutator(tid); } - static void set_thr_suspend_mutator(int_fnP_thread_t func) { _thr_suspend_mutator = func; } - - static int thr_continue_mutator(thread_t tid) { return _thr_continue_mutator(tid); } - static void set_thr_continue_mutator(int_fnP_thread_t func) { _thr_continue_mutator = func; } - // Allows us to switch between lwp and thread -based synchronization static int mutex_lock(mutex_t *mx) { return _mutex_lock(mx); } static int mutex_trylock(mutex_t *mx) { return _mutex_trylock(mx); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -3518,7 +3518,7 @@ void os::yield() { os::NakedYield(); } -void os::yield_all(int attempts) { +void os::yield_all() { // Yields to all threads, including threads with lower priorities Sleep(1); } @@ -3864,12 +3864,6 @@ win32::setmode_streams(); init_page_sizes((size_t) win32::vm_page_size()); - // For better scalability on MP systems (must be called after initialize_system_info) -#ifndef PRODUCT - if (is_MP()) { - NoYieldsInMicrolock = true; - } -#endif // This may be overridden later when argument processing is done. FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation, os::win32::is_windows_2003()); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os/windows/vm/os_windows.inline.hpp --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -52,9 +52,6 @@ return (void*)::GetProcAddress((HMODULE)lib, name); } -// Used to improve time-sharing on some systems -inline void os::loop_breaker(int attempts) {} - inline bool os::obsolete_option(const JavaVMOption *option) { return false; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -270,31 +270,6 @@ } } -static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { - char lwpstatusfile[PROCFILE_LENGTH]; - int lwpfd, err; - - if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs)) - return (err); - if (*flags == TRS_LWPID) { - sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(), - *lwp); - if ((lwpfd = ::open(lwpstatusfile, O_RDONLY)) < 0) { - perror("thr_mutator_status: open lwpstatus"); - return (EINVAL); - } - if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) != - sizeof (lwpstatus_t)) { - perror("thr_mutator_status: read lwpstatus"); - (void) ::close(lwpfd); - return (EINVAL); - } - (void) ::close(lwpfd); - } - return (0); -} - - bool os::is_allocatable(size_t bytes) { #ifdef _LP64 return true; diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -256,30 +256,6 @@ } } -static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { - char lwpstatusfile[PROCFILE_LENGTH]; - int lwpfd, err; - - if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs)) - return (err); - if (*flags == TRS_LWPID) { - sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(), - *lwp); - if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) { - perror("thr_mutator_status: open lwpstatus"); - return (EINVAL); - } - if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) != - sizeof (lwpstatus_t)) { - perror("thr_mutator_status: read lwpstatus"); - (void) close(lwpfd); - return (EINVAL); - } - (void) close(lwpfd); - } - return (0); -} - #ifndef AMD64 // Detecting SSE support by OS diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -2777,6 +2777,11 @@ "Short length on BootstrapMethods in class file %s", CHECK); + guarantee_property(attribute_byte_length > sizeof(u2), + "Invalid BootstrapMethods attribute length %u in class file %s", + attribute_byte_length, + CHECK); + // The attribute contains a counted array of counted tuples of shorts, // represending bootstrap specifiers: // length*{bootstrap_method_index, argument_count*{argument_index}} @@ -4180,8 +4185,12 @@ clear_class_metadata(); - // deallocate the klass if already created. - MetadataFactory::free_metadata(_loader_data, _klass); + // deallocate the klass if already created. Don't directly deallocate, but add + // to the deallocate list so that the klass is removed from the CLD::_klasses list + // at a safepoint. + if (_klass != NULL) { + _loader_data->add_to_deallocate_list(_klass); + } _klass = NULL; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -464,25 +464,26 @@ void java_lang_String::print(oop java_string, outputStream* st) { assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(java_string); - int offset = java_lang_String::offset(java_string); - int length = java_lang_String::length(java_string); - - int end = MIN2(length, 100); + if (value == NULL) { // This can happen if, e.g., printing a String // object before its initializer has been called - st->print_cr("NULL"); - } else { - st->print("\""); - for (int index = 0; index < length; index++) { - st->print("%c", value->char_at(index + offset)); - } - st->print("\""); + st->print("NULL"); + return; } -} - -static void initialize_static_field(fieldDescriptor* fd, TRAPS) { - Handle mirror (THREAD, fd->field_holder()->java_mirror()); + + int offset = java_lang_String::offset(java_string); + int length = java_lang_String::length(java_string); + + st->print("\""); + for (int index = 0; index < length; index++) { + st->print("%c", value->char_at(index + offset)); + } + st->print("\""); +} + + +static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) { assert(mirror.not_null() && fd->is_static(), "just checking"); if (fd->has_initial_value()) { BasicType t = fd->field_type(); @@ -549,21 +550,45 @@ create_mirror(k, Handle(NULL), CHECK); } -oop java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) { +void java_lang_Class::initialize_mirror_fields(KlassHandle k, + Handle mirror, + Handle protection_domain, + TRAPS) { + // Allocate a simple java object for a lock. + // This needs to be a java object because during class initialization + // it can be held across a java call. + typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK); + set_init_lock(mirror(), r); + + // Set protection domain also + set_protection_domain(mirror(), protection_domain()); + + // Initialize static fields + InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK); +} + +void java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) { assert(k->java_mirror() == NULL, "should only assign mirror once"); // Use this moment of initialization to cache modifier_flags also, // to support Class.getModifiers(). Instance classes recalculate // the cached flags after the class file is parsed, but before the // class is put into the system dictionary. - int computed_modifiers = k->compute_modifier_flags(CHECK_0); + int computed_modifiers = k->compute_modifier_flags(CHECK); k->set_modifier_flags(computed_modifiers); // Class_klass has to be loaded because it is used to allocate // the mirror. if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) - Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); + Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK); + + // Setup indirection from mirror->klass + if (!k.is_null()) { + java_lang_Class::set_klass(mirror(), k()); + } InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); + assert(oop_size(mirror()) == mk->instance_size(k), "should have been set"); + java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); // It might also have a component mirror. This mirror must already exist. @@ -576,29 +601,32 @@ assert(k->oop_is_objArray(), "Must be"); Klass* element_klass = ObjArrayKlass::cast(k())->element_klass(); assert(element_klass != NULL, "Must have an element klass"); - comp_mirror = element_klass->java_mirror(); + comp_mirror = element_klass->java_mirror(); } assert(comp_mirror.not_null(), "must have a mirror"); - // Two-way link between the array klass and its component mirror: + // Two-way link between the array klass and its component mirror: ArrayKlass::cast(k())->set_component_mirror(comp_mirror()); set_array_klass(comp_mirror(), k()); } else { assert(k->oop_is_instance(), "Must be"); - // Allocate a simple java object for a lock. - // This needs to be a java object because during class initialization - // it can be held across a java call. - typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_NULL); - set_init_lock(mirror(), r); - - // Set protection domain also - set_protection_domain(mirror(), protection_domain()); - - // Initialize static fields - InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL); + initialize_mirror_fields(k, mirror, protection_domain, THREAD); + if (HAS_PENDING_EXCEPTION) { + // If any of the fields throws an exception like OOM remove the klass field + // from the mirror so GC doesn't follow it after the klass has been deallocated. + // This mirror looks like a primitive type, which logically it is because it + // it represents no class. + java_lang_Class::set_klass(mirror(), NULL); + return; + } } - return mirror(); + + // Setup indirection from klass->mirror last + // after any exceptions can happen during allocations. + if (!k.is_null()) { + k->set_java_mirror(mirror()); + } } else { if (fixup_mirror_list() == NULL) { GrowableArray* list = @@ -606,12 +634,10 @@ set_fixup_mirror_list(list); } fixup_mirror_list()->push(k()); - return NULL; } } - int java_lang_Class::oop_size(oop java_class) { assert(_oop_size_offset != 0, "must be set"); return java_class->int_field(_oop_size_offset); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/javaClasses.hpp --- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -246,11 +246,12 @@ static void set_init_lock(oop java_class, oop init_lock); static void set_protection_domain(oop java_class, oop protection_domain); + static void initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS); public: static void compute_offsets(); // Instance creation - static oop create_mirror(KlassHandle k, Handle protection_domain, TRAPS); + static void create_mirror(KlassHandle k, Handle protection_domain, TRAPS); static void fixup_mirror(KlassHandle k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); // Conversion diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/symbolTable.cpp --- a/hotspot/src/share/vm/classfile/symbolTable.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -810,11 +810,11 @@ const int limit = the_table()->table_size(); assert(0 <= start_idx && start_idx <= limit, - err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); + err_msg("start_idx (%d) is out of bounds", start_idx)); assert(0 <= end_idx && end_idx <= limit, - err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); + err_msg("end_idx (%d) is out of bounds", end_idx)); assert(start_idx <= end_idx, - err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, + err_msg("Index ordering: start_idx=%d, end_idx=%d", start_idx, end_idx)); for (int i = start_idx; i < end_idx; i += 1) { @@ -833,11 +833,11 @@ const int limit = the_table()->table_size(); assert(0 <= start_idx && start_idx <= limit, - err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); + err_msg("start_idx (%d) is out of bounds", start_idx)); assert(0 <= end_idx && end_idx <= limit, - err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); + err_msg("end_idx (%d) is out of bounds", end_idx)); assert(start_idx <= end_idx, - err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, + err_msg("Index ordering: start_idx=%d, end_idx=%d", start_idx, end_idx)); for (int i = start_idx; i < end_idx; ++i) { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -826,47 +826,6 @@ } } // load_instance_class loop - if (HAS_PENDING_EXCEPTION) { - // An exception, such as OOM could have happened at various places inside - // load_instance_class. We might have partially initialized a shared class - // and need to clean it up. - if (class_loader.is_null()) { - // In some cases k may be null. Let's find the shared class again. - instanceKlassHandle ik(THREAD, find_shared_class(name)); - if (ik.not_null()) { - if (ik->class_loader_data() == NULL) { - // We didn't go as far as Klass::restore_unshareable_info(), - // so nothing to clean up. - } else { - Klass *kk; - { - MutexLocker mu(SystemDictionary_lock, THREAD); - kk = find_class(d_index, d_hash, name, ik->class_loader_data()); - } - if (kk != NULL) { - // No clean up is needed if the shared class has been entered - // into system dictionary, as load_shared_class() won't be called - // again. - } else { - // This must be done outside of the SystemDictionary_lock to - // avoid deadlock. - // - // Note that Klass::restore_unshareable_info (called via - // load_instance_class above) is also called outside - // of SystemDictionary_lock. Other threads are blocked from - // loading this class because they are waiting on the - // SystemDictionary_lock until this thread removes - // the placeholder below. - // - // This need to be re-thought when parallel-capable non-boot - // classloaders are supported by CDS (today they're not). - clean_up_shared_class(ik, class_loader, THREAD); - } - } - } - } - } - if (load_instance_added == true) { // clean up placeholder entries for LOAD_INSTANCE success or error // This brackets the SystemDictionary updates for both defining @@ -1272,19 +1231,6 @@ return ik; } -void SystemDictionary::clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS) { - // Updating methods must be done under a lock so multiple - // threads don't update these in parallel - // Shared classes are all currently loaded by the bootstrap - // classloader, so this will never cause a deadlock on - // a custom class loader lock. - { - Handle lockObject = compute_loader_lock_object(class_loader, THREAD); - check_loader_lock_contention(lockObject, THREAD); - ObjectLocker ol(lockObject, THREAD, true); - ik->remove_unshareable_info(); - } -} instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -617,7 +617,6 @@ Handle class_loader, TRAPS); static instanceKlassHandle load_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS); - static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS); static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -57,10 +57,10 @@ _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC); - int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids(); + uint worker_id_offset = DirtyCardQueueSet::num_par_ids(); ConcurrentG1RefineThread *next = NULL; - for (int i = _n_threads - 1; i >= 0; i--) { + for (uint i = _n_threads - 1; i != UINT_MAX; i--) { ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { @@ -87,7 +87,7 @@ void ConcurrentG1Refine::stop() { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { _threads[i]->stop(); } } @@ -96,7 +96,7 @@ void ConcurrentG1Refine::reinitialize_threads() { reset_threshold_step(); if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { _threads[i]->initialize(); } } @@ -104,7 +104,7 @@ ConcurrentG1Refine::~ConcurrentG1Refine() { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { delete _threads[i]; } FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads, mtGC); @@ -113,7 +113,7 @@ void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { tc->do_thread(_threads[i]); } } @@ -121,20 +121,20 @@ void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { if (_threads != NULL) { - for (int i = 0; i < worker_thread_num(); i++) { + for (uint i = 0; i < worker_thread_num(); i++) { tc->do_thread(_threads[i]); } } } -int ConcurrentG1Refine::thread_num() { - int n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads +uint ConcurrentG1Refine::thread_num() { + uint n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads : ParallelGCThreads; - return MAX2(n_threads, 1); + return MAX2(n_threads, 1); } void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { - for (int i = 0; i < _n_threads; ++i) { + for (uint i = 0; i < _n_threads; ++i) { _threads[i]->print_on(st); st->cr(); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -39,8 +39,8 @@ class ConcurrentG1Refine: public CHeapObj { ConcurrentG1RefineThread** _threads; - int _n_threads; - int _n_worker_threads; + uint _n_threads; + uint _n_worker_threads; /* * The value of the update buffer queue length falls into one of 3 zones: * green, yellow, red. If the value is in [0, green) nothing is @@ -88,7 +88,7 @@ // The RS sampling thread ConcurrentG1RefineThread * sampling_thread() const; - static int thread_num(); + static uint thread_num(); void print_worker_threads_on(outputStream* st) const; @@ -100,8 +100,8 @@ int yellow_zone() const { return _yellow_zone; } int red_zone() const { return _red_zone; } - int total_thread_num() const { return _n_threads; } - int worker_thread_num() const { return _n_worker_threads; } + uint total_thread_num() const { return _n_threads; } + uint worker_thread_num() const { return _n_worker_threads; } int thread_threshold_step() const { return _thread_threshold_step; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -33,7 +33,7 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, - int worker_id_offset, int worker_id) : + uint worker_id_offset, uint worker_id) : ConcurrentGCThread(), _worker_id_offset(worker_id_offset), _worker_id(worker_id), diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -38,8 +38,8 @@ double _vtime_start; // Initial virtual time. double _vtime_accum; // Initial virtual time. - int _worker_id; - int _worker_id_offset; + uint _worker_id; + uint _worker_id_offset; // The refinement threads collection is linked list. A predecessor can activate a successor // when the number of the rset update buffer crosses a certain threshold. A successor @@ -71,7 +71,7 @@ virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, - int worker_id_offset, int worker_id); + uint worker_id_offset, uint worker_id); void initialize(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -567,8 +567,8 @@ _root_regions.init(_g1h, this); if (ConcGCThreads > ParallelGCThreads) { - warning("Can't have more ConcGCThreads (" UINT32_FORMAT ") " - "than ParallelGCThreads (" UINT32_FORMAT ").", + warning("Can't have more ConcGCThreads (" UINTX_FORMAT ") " + "than ParallelGCThreads (" UINTX_FORMAT ").", ConcGCThreads, ParallelGCThreads); return; } @@ -1804,7 +1804,6 @@ class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { G1CollectedHeap* _g1; - int _worker_num; size_t _max_live_bytes; uint _regions_claimed; size_t _freed_bytes; @@ -1817,10 +1816,9 @@ public: G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, - int worker_num, FreeRegionList* local_cleanup_list, HRRSCleanupTask* hrrs_cleanup_task) : - _g1(g1), _worker_num(worker_num), + _g1(g1), _max_live_bytes(0), _regions_claimed(0), _freed_bytes(0), _claimed_region_time(0.0), _max_region_time(0.0), @@ -1893,7 +1891,7 @@ double start = os::elapsedTime(); FreeRegionList local_cleanup_list("Local Cleanup List"); HRRSCleanupTask hrrs_cleanup_task; - G1NoteEndOfConcMarkClosure g1_note_end(_g1h, worker_id, &local_cleanup_list, + G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, &hrrs_cleanup_task); if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, @@ -2145,7 +2143,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); - _cleanup_list.verify_list(); + _cleanup_list.verify_optional(); FreeRegionList tmp_free_list("Tmp Free List"); if (G1ConcRegionFreeingVerbose) { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -34,12 +34,12 @@ bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, bool consume, - size_t worker_i) { + uint worker_i) { bool res = true; if (_buf != NULL) { res = apply_closure_to_buffer(cl, _buf, _index, _sz, consume, - (int) worker_i); + worker_i); if (res && consume) _index = _sz; } return res; @@ -49,7 +49,7 @@ void** buf, size_t index, size_t sz, bool consume, - int worker_i) { + uint worker_i) { if (cl == NULL) return true; for (size_t i = index; i < sz; i += oopSize) { int ind = byte_index_to_index((int)i); @@ -79,8 +79,8 @@ } // Determines how many mutator threads can process the buffers in parallel. -size_t DirtyCardQueueSet::num_par_ids() { - return os::processor_count(); +uint DirtyCardQueueSet::num_par_ids() { + return (uint)os::processor_count(); } void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, @@ -103,7 +103,7 @@ } void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, - size_t worker_i) { + uint worker_i) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); for(JavaThread* t = Threads::first(); t; t = t->next()) { bool b = t->dirty_card_queue().apply_closure(_closure, consume); @@ -126,11 +126,11 @@ // We get the the number of any par_id that this thread // might have already claimed. - int worker_i = thread->get_claimed_par_id(); + uint worker_i = thread->get_claimed_par_id(); - // If worker_i is not -1 then the thread has already claimed + // If worker_i is not UINT_MAX then the thread has already claimed // a par_id. We make note of it using the already_claimed value - if (worker_i != -1) { + if (worker_i != UINT_MAX) { already_claimed = true; } else { @@ -142,7 +142,7 @@ } bool b = false; - if (worker_i != -1) { + if (worker_i != UINT_MAX) { b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, _sz, true, worker_i); if (b) Atomic::inc(&_processed_buffers_mut); @@ -154,8 +154,8 @@ // we release the id _free_ids->release_par_id(worker_i); - // and set the claimed_id in the thread to -1 - thread->set_claimed_par_id(-1); + // and set the claimed_id in the thread to UINT_MAX + thread->set_claimed_par_id(UINT_MAX); } } return b; @@ -186,7 +186,7 @@ bool DirtyCardQueueSet:: apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, BufferNode* nd) { if (nd != NULL) { void **buf = BufferNode::make_buffer_from_node(nd); @@ -208,7 +208,7 @@ } bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, int stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); @@ -218,7 +218,7 @@ return res; } -bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, +bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i, int stop_at, bool during_pause) { return apply_closure_to_completed_buffer(_closure, worker_i, diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -36,7 +36,7 @@ public: // Process the card whose card table entry is "card_ptr". If returns // "false", terminate the iteration early. - virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0; + virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0; }; // A ptrQueue whose elements are "oops", pointers to object heads. @@ -53,7 +53,7 @@ // deletes processed entries from logs. bool apply_closure(CardTableEntryClosure* cl, bool consume = true, - size_t worker_i = 0); + uint worker_i = 0); // Apply the closure to all elements of "buf", down to "index" // (inclusive.) If returns "false", then a closure application returned @@ -63,7 +63,7 @@ static bool apply_closure_to_buffer(CardTableEntryClosure* cl, void** buf, size_t index, size_t sz, bool consume = true, - int worker_i = 0); + uint worker_i = 0); void **get_buf() { return _buf;} void set_buf(void **buf) {_buf = buf;} size_t get_index() { return _index;} @@ -98,7 +98,7 @@ // The number of parallel ids that can be claimed to allow collector or // mutator threads to do card-processing work. - static size_t num_par_ids(); + static uint num_par_ids(); static void handle_zero_index_for_thread(JavaThread* t); @@ -115,7 +115,7 @@ // change in the future.) If "consume" is true, processed entries are // discarded. void iterate_closure_all_threads(bool consume = true, - size_t worker_i = 0); + uint worker_i = 0); // If there exists some completed buffer, pop it, then apply the // registered closure to all its elements, nulling out those elements @@ -124,7 +124,7 @@ // but is only partially completed before a "yield" happens, the // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. - bool apply_closure_to_completed_buffer(int worker_i = 0, + bool apply_closure_to_completed_buffer(uint worker_i = 0, int stop_at = 0, bool during_pause = false); @@ -136,13 +136,13 @@ // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - int worker_i = 0, + uint worker_i = 0, int stop_at = 0, bool during_pause = false); // Helper routine for the above. bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, BufferNode* nd); BufferNode* get_completed_buffer(int stop_at); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -304,26 +304,26 @@ if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) { guarantee(entry > N_words, err_msg("Should be in logarithmic region - " - "entry: " UINT32_FORMAT ", " - "_array->offset_array(c): " UINT32_FORMAT ", " - "N_words: " UINT32_FORMAT, - entry, _array->offset_array(c), N_words)); + "entry: %u, " + "_array->offset_array(c): %u, " + "N_words: %u", + (uint)entry, (uint)_array->offset_array(c), (uint)N_words)); } size_t backskip = BlockOffsetArray::entry_to_cards_back(entry); size_t landing_card = c - backskip; guarantee(landing_card >= (start_card - 1), "Inv"); if (landing_card >= start_card) { guarantee(_array->offset_array(landing_card) <= entry, - err_msg("Monotonicity - landing_card offset: " UINT32_FORMAT ", " - "entry: " UINT32_FORMAT, - _array->offset_array(landing_card), entry)); + err_msg("Monotonicity - landing_card offset: %u, " + "entry: %u", + (uint)_array->offset_array(landing_card), (uint)entry)); } else { guarantee(landing_card == start_card - 1, "Tautology"); // Note that N_words is the maximum offset value guarantee(_array->offset_array(landing_card) <= N_words, - err_msg("landing card offset: " UINT32_FORMAT ", " - "N_words: " UINT32_FORMAT, - _array->offset_array(landing_card), N_words)); + err_msg("landing card offset: %u, " + "N_words: %u", + (uint)_array->offset_array(landing_card), (uint)N_words)); } } } @@ -554,21 +554,20 @@ (_array->offset_array(orig_index) > 0 && _array->offset_array(orig_index) <= N_words), err_msg("offset array should have been set - " - "orig_index offset: " UINT32_FORMAT ", " + "orig_index offset: %u, " "blk_start: " PTR_FORMAT ", " "boundary: " PTR_FORMAT, - _array->offset_array(orig_index), + (uint)_array->offset_array(orig_index), blk_start, boundary)); for (size_t j = orig_index + 1; j <= end_index; j++) { assert(_array->offset_array(j) > 0 && _array->offset_array(j) <= (u_char) (N_words+BlockOffsetArray::N_powers-1), err_msg("offset array should have been set - " - UINT32_FORMAT " not > 0 OR " - UINT32_FORMAT " not <= " UINT32_FORMAT, - _array->offset_array(j), - _array->offset_array(j), - (u_char) (N_words+BlockOffsetArray::N_powers-1))); + "%u not > 0 OR %u not <= %u", + (uint) _array->offset_array(j), + (uint) _array->offset_array(j), + (uint) (N_words+BlockOffsetArray::N_powers-1))); } #endif } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -146,8 +146,8 @@ void check_offset(size_t offset, const char* msg) const { assert(offset <= N_words, err_msg("%s - " - "offset: " UINT32_FORMAT", N_words: " UINT32_FORMAT, - msg, offset, N_words)); + "offset: " SIZE_FORMAT", N_words: %u", + msg, offset, (uint)N_words)); } // Bounds checking accessors: diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -102,7 +102,7 @@ ConcurrentG1Refine* cg1r) : _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); // This path is executed by the concurrent refine or mutator threads, // concurrently, and so we do not care if card_ptr contains references @@ -131,7 +131,7 @@ { for (int i = 0; i < 256; i++) _histo[i] = 0; } - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { _calls++; unsigned char* ujb = (unsigned char*)card_ptr; @@ -160,7 +160,7 @@ RedirtyLoggedCardTableEntryClosure() : _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { _calls++; *card_ptr = 0; @@ -1288,7 +1288,7 @@ print_heap_before_gc(); trace_heap_before_gc(gc_tracer); - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); verify_region_sets_optional(); @@ -2314,7 +2314,7 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, DirtyCardQueue* into_cset_dcq, bool concurrent, - int worker_i) { + uint worker_i) { // Clean cards in the hot card cache G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache(); hot_card_cache->drain(worker_i, g1_rem_set(), into_cset_dcq); @@ -2843,7 +2843,7 @@ // Given the id of a worker, obtain or calculate a suitable // starting region for iterating over the current collection set. -HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) { +HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) { assert(get_gc_time_stamp() > 0, "should have been updated by now"); HeapRegion* result = NULL; @@ -5103,7 +5103,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i) { + uint worker_i) { // First scan the strong roots double ext_roots_start = os::elapsedTime(); @@ -5207,10 +5207,10 @@ ~G1StringSymbolTableUnlinkTask() { guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size, - err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT, + err_msg("claim value %d after unlink less than initial string table size %d", StringTable::parallel_claimed_index(), _initial_string_table_size)); guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, - err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT, + err_msg("claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size)); } @@ -5275,7 +5275,7 @@ class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { public: - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { *card_ptr = CardTableModRefBS::dirty_card_val(); return true; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -845,7 +845,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i); + uint worker_i); // Notifies all the necessary spaces that the committed space has // been updated (either expanded or shrunk). It should be called @@ -1139,7 +1139,7 @@ void iterate_dirty_card_closure(CardTableEntryClosure* cl, DirtyCardQueue* into_cset_dcq, - bool concurrent, int worker_i); + bool concurrent, uint worker_i); // The shared block offset table array. G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; } @@ -1370,7 +1370,7 @@ // Given the id of a worker, obtain or calculate a suitable // starting region for iterating over the current collection set. - HeapRegion* start_cset_region_for_worker(int worker_i); + HeapRegion* start_cset_region_for_worker(uint worker_i); // This is a convenience method that is used by the // HeapRegionIterator classes to calculate the starting region for diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1204,7 +1204,7 @@ (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; if (full) { - _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes(); + _metaspace_used_bytes_before_gc = MetaspaceAux::used_bytes(); } } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -147,7 +147,7 @@ void WorkerDataArray::verify() { for (uint i = 0; i < _length; i++) { assert(_data[i] != _uninitialized, - err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf", + err_msg("Invalid data for worker %u, data: %lf, uninitialized: %lf", i, (double)_data[i], (double)_uninitialized)); } } @@ -246,8 +246,8 @@ LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } -void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) { - LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); +void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) { + LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers); } double G1GCPhaseTimes::accounted_time_ms() { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -161,7 +161,7 @@ // Helper methods for detailed logging void print_stats(int level, const char* str, double value); - void print_stats(int level, const char* str, double value, int workers); + void print_stats(int level, const char* str, double value, uint workers); public: G1GCPhaseTimes(uint max_gc_threads); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -44,9 +44,9 @@ _hot_cache_idx = 0; // For refining the cards in the hot cache in parallel - int n_workers = (ParallelGCThreads > 0 ? + uint n_workers = (ParallelGCThreads > 0 ? _g1h->workers()->total_workers() : 1); - _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / n_workers); + _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers); _hot_cache_par_claimed_idx = 0; _card_counts.initialize(); @@ -89,7 +89,7 @@ return res; } -void G1HotCardCache::drain(int worker_i, +void G1HotCardCache::drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq) { if (!default_use_cache()) { @@ -122,8 +122,8 @@ // RSet updating while within an evacuation pause. // In this case worker_i should be the id of a GC worker thread assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint"); - assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), - err_msg("incorrect worker id: "INT32_FORMAT, worker_i)); + assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), + err_msg("incorrect worker id: %u", worker_i)); into_cset_dcq->enqueue(card_ptr); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -99,7 +99,7 @@ // Refine the cards that have delayed as a result of // being in the cache. - void drain(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq); + void drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq); // Set up for parallel processing of the cards in the hot cache void reset_hot_cache_claimed_index() { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -234,14 +234,14 @@ HeapRegion* _from; OopsInHeapRegionClosure* _push_ref_cl; bool _record_refs_into_cset; - int _worker_i; + uint _worker_i; public: G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, G1RemSet* rs, OopsInHeapRegionClosure* push_ref_cl, bool record_refs_into_cset, - int worker_i = 0); + uint worker_i = 0); void set_from(HeapRegion* from) { assert(from != NULL, "from region must be non-NULL"); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -113,14 +113,14 @@ G1SATBCardTableModRefBS *_ct_bs; double _strong_code_root_scan_time_sec; - int _worker_i; + uint _worker_i; int _block_size; bool _try_claimed; public: ScanRSClosure(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) : + uint worker_i) : _oc(oc), _code_root_cl(code_root_cl), _strong_code_root_scan_time_sec(0.0), @@ -162,7 +162,7 @@ void printCard(HeapRegion* card_region, size_t card_index, HeapWord* card_start) { - gclog_or_tty->print_cr("T %d Region [" PTR_FORMAT ", " PTR_FORMAT ") " + gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") " "RS names card %p: " "[" PTR_FORMAT ", " PTR_FORMAT ")", _worker_i, @@ -241,7 +241,7 @@ void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) { + uint worker_i) { double rs_time_start = os::elapsedTime(); HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i); @@ -274,13 +274,13 @@ DirtyCardQueue* into_cset_dcq) : _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { // The only time we care about recording cards that // contain references that point into the collection set // is during RSet updating within an evacuation pause. // In this case worker_i should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); + assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); if (_g1rs->refine_card(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection @@ -295,7 +295,7 @@ } }; -void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) { +void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { double start = os::elapsedTime(); // Apply the given closure to all remaining log entries. RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); @@ -320,14 +320,14 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) { + uint worker_i) { #if CARD_REPEAT_HISTO ct_freq_update_histo_and_reset(); #endif // We cache the value of 'oc' closure into the appropriate slot in the // _cset_rs_update_cl for this worker - assert(worker_i < (int)n_workers(), "sanity"); + assert(worker_i < n_workers(), "sanity"); _cset_rs_update_cl[worker_i] = oc; // A DirtyCardQueue that is used to hold cards containing references @@ -399,7 +399,7 @@ _g1(g1), _ct_bs(bs) { } - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { // Construct the region representing the card. HeapWord* start = _ct_bs->addr_for(card_ptr); // And find the region containing it. @@ -543,7 +543,7 @@ G1RemSet* rs, OopsInHeapRegionClosure* push_ref_cl, bool record_refs_into_cset, - int worker_i) : + uint worker_i) : _g1(g1h), _g1_rem_set(rs), _from(NULL), _record_refs_into_cset(record_refs_into_cset), _push_ref_cl(push_ref_cl), _worker_i(worker_i) { } @@ -552,7 +552,7 @@ // into the collection set, if we're checking for such references; // false otherwise. -bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i, +bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, bool check_for_refs_into_cset) { // If the card is no longer dirty, nothing to do. diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -97,7 +97,7 @@ // In the sequential case this param will be ignored. void oops_into_collection_set_do(OopsInHeapRegionClosure* blk, CodeBlobToOopClosure* code_root_cl, - int worker_i); + uint worker_i); // Prepare for and cleanup after an oops_into_collection_set_do // call. Must call each of these once before and after (in sequential @@ -109,9 +109,9 @@ void scanRS(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i); + uint worker_i); - void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i); + void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i); CardTableModRefBS* ct_bs() { return _ct_bs; } size_t cardsScanned() { return _total_cards_scanned; } @@ -138,7 +138,7 @@ // if the given card contains oops that have references into the // current collection set. virtual bool refine_card(jbyte* card_ptr, - int worker_i, + uint worker_i, bool check_for_refs_into_cset); // Print accumulated summary info from the start of the VM. @@ -171,12 +171,12 @@ class UpdateRSOopClosure: public ExtendedOopClosure { HeapRegion* _from; G1RemSet* _rs; - int _worker_i; + uint _worker_i; template void do_oop_work(T* p); public: - UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) : + UpdateRSOopClosure(G1RemSet* rs, uint worker_i = 0) : _from(NULL), _rs(rs), _worker_i(worker_i) {} diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -390,7 +390,7 @@ void FromCardCache::print(outputStream* out) { for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { for (uint j = 0; j < _max_regions; j++) { - out->print_cr("_from_card_cache["UINT32_FORMAT"]["UINT32_FORMAT"] = "INT32_FORMAT".", + out->print_cr("_from_card_cache[%u][%u] = %d.", i, j, at(i, j)); } } @@ -430,7 +430,7 @@ int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = "INT32_FORMAT")", + gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)", hr()->bottom(), from_card, FromCardCache::at((uint)tid, cur_hrs_ind)); } @@ -853,13 +853,13 @@ // This can be done by either mutator threads together with the // concurrent refinement threads or GC threads. uint HeapRegionRemSet::num_par_rem_sets() { - return (uint)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); + return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), (uint)ParallelGCThreads); } HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) : _bosa(bosa), - _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #"UINT32_FORMAT, hr->hrs_index()), true), + _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrs_index()), true), _code_roots(), _other_regions(hr, &_m) { reset_for_par_iteration(); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -30,7 +30,7 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { check_mt_safety(); assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u")); - assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); + assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked")); _count.increment(1u, hr->capacity()); hr->set_containing_set(this); @@ -40,7 +40,7 @@ inline void HeapRegionSetBase::remove(HeapRegion* hr) { check_mt_safety(); verify_region(hr); - assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); + assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked")); hr->set_containing_set(NULL); assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition")); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -290,7 +290,7 @@ shared_satb_queue()->apply_closure_and_empty(_closure); } -void SATBMarkQueueSet::par_iterate_closure_all_threads(int worker) { +void SATBMarkQueueSet::par_iterate_closure_all_threads(uint worker) { SharedHeap* sh = SharedHeap::heap(); int parity = sh->strong_roots_parity(); @@ -315,7 +315,7 @@ } bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par, - int worker) { + uint worker) { BufferNode* nd = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -84,7 +84,7 @@ // Utility function to support sequential and parallel versions. If // "par" is true, then "worker" is the par thread id; if "false", worker // is ignored. - bool apply_closure_to_completed_buffer_work(bool par, int worker); + bool apply_closure_to_completed_buffer_work(bool par, uint worker); #ifdef ASSERT void dump_active_states(bool expected_active); @@ -124,7 +124,7 @@ // be called serially and at a safepoint. void iterate_closure_all_threads(); // Parallel version of the above. - void par_iterate_closure_all_threads(int worker); + void par_iterate_closure_all_threads(uint worker); // If there exists some completed buffer, pop it, then apply the // registered closure to all its elements, and return true. If no @@ -133,7 +133,7 @@ return apply_closure_to_completed_buffer_work(false, 0); } // Parallel version of the above. - bool par_apply_closure_to_completed_buffer(int worker) { + bool par_apply_closure_to_completed_buffer(uint worker) { return apply_closure_to_completed_buffer_work(true, worker); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -184,7 +184,7 @@ size_t prev_used = heap->used(); // Capture metadata size before collection for sizing. - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); // For PrintGCDetails size_t old_gen_prev_used = old_gen->used_in_bytes(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -928,7 +928,7 @@ _heap_used = heap->used(); _young_gen_used = heap->young_gen()->used_in_bytes(); _old_gen_used = heap->old_gen()->used_in_bytes(); - _metadata_used = MetaspaceAux::allocated_used_bytes(); + _metadata_used = MetaspaceAux::used_bytes(); }; size_t heap_used() const { return _heap_used; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -62,16 +62,16 @@ }; class MetaspaceSizes : public StackObj { - size_t _capacity; + size_t _committed; size_t _used; size_t _reserved; public: - MetaspaceSizes() : _capacity(0), _used(0), _reserved(0) {} - MetaspaceSizes(size_t capacity, size_t used, size_t reserved) : - _capacity(capacity), _used(used), _reserved(reserved) {} + MetaspaceSizes() : _committed(0), _used(0), _reserved(0) {} + MetaspaceSizes(size_t committed, size_t used, size_t reserved) : + _committed(committed), _used(used), _reserved(reserved) {} - size_t capacity() const { return _capacity; } + size_t committed() const { return _committed; } size_t used() const { return _used; } size_t reserved() const { return _reserved; } }; diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -258,7 +258,7 @@ static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) { TraceStructMetaspaceSizes meta_sizes; - meta_sizes.set_capacity(sizes.capacity()); + meta_sizes.set_committed(sizes.committed()); meta_sizes.set_used(sizes.used()); meta_sizes.set_reserved(sizes.reserved()); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_interface/collectedHeap.cpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -85,16 +85,16 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { const MetaspaceSizes meta_space( - MetaspaceAux::allocated_capacity_bytes(), - MetaspaceAux::allocated_used_bytes(), + MetaspaceAux::committed_bytes(), + MetaspaceAux::used_bytes(), MetaspaceAux::reserved_bytes()); const MetaspaceSizes data_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType), + MetaspaceAux::committed_bytes(Metaspace::NonClassType), + MetaspaceAux::used_bytes(Metaspace::NonClassType), MetaspaceAux::reserved_bytes(Metaspace::NonClassType)); const MetaspaceSizes class_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), + MetaspaceAux::committed_bytes(Metaspace::ClassType), + MetaspaceAux::used_bytes(Metaspace::ClassType), MetaspaceAux::reserved_bytes(Metaspace::ClassType)); const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary = @@ -582,36 +582,6 @@ } } -oop CollectedHeap::Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS) { - debug_only(check_for_valid_allocation_state()); - assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); - assert(size >= 0, "int won't convert to size_t"); - HeapWord* obj; - assert(ScavengeRootsInCode > 0, "must be"); - obj = common_mem_allocate_init(real_klass, size, CHECK_NULL); - post_allocation_setup_common(klass, obj); - assert(Universe::is_bootstrapping() || - !((oop)obj)->is_array(), "must not be an array"); - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); - oop mirror = (oop)obj; - - java_lang_Class::set_oop_size(mirror, size); - - // Setup indirections - if (!real_klass.is_null()) { - java_lang_Class::set_klass(mirror, real_klass()); - real_klass->set_java_mirror(mirror); - } - - InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); - assert(size == mk->instance_size(real_klass), "should have been set"); - - // notify jvmti and dtrace - post_allocation_notify(klass, (oop)obj); - - return mirror; -} - /////////////// Unit tests /////////////// #ifndef PRODUCT diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -312,9 +312,6 @@ // May be overridden to set additional parallelism. virtual void set_par_threads(uint t) { _n_par_threads = t; }; - // Allocate and initialize instances of Class - static oop Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS); - // General obj/array allocation facilities. inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/collectorPolicy.cpp --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -257,6 +257,12 @@ assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment"); assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment"); assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment"); + assert(_min_gen0_size <= bound_minus_alignment(_min_gen0_size, _min_heap_byte_size), + "Ergonomics made minimum young generation larger than minimum heap"); + assert(_initial_gen0_size <= bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size), + "Ergonomics made initial young generation larger than initial heap"); + assert(_max_gen0_size <= bound_minus_alignment(_max_gen0_size, _max_heap_byte_size), + "Ergonomics made maximum young generation lager than maximum heap"); } void TwoGenerationCollectorPolicy::assert_size_info() { @@ -267,6 +273,9 @@ assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment"); assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment"); assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes"); + assert(_min_gen0_size + _min_gen1_size <= _min_heap_byte_size, "Minimum generation sizes exceed minimum heap size"); + assert(_initial_gen0_size + _initial_gen1_size == _initial_heap_byte_size, "Initial generation sizes should match initial heap size"); + assert(_max_gen0_size + _max_gen1_size == _max_heap_byte_size, "Maximum generation sizes should match maximum heap size"); } #endif // ASSERT @@ -303,20 +312,26 @@ } } + // Make sure NewSize allows an old generation to fit even if set on the command line + if (FLAG_IS_CMDLINE(NewSize) && NewSize >= _initial_heap_byte_size) { + warning("NewSize was set larger than initial heap size, will use initial heap size."); + NewSize = bound_minus_alignment(NewSize, _initial_heap_byte_size); + } + // Now take the actual NewSize into account. We will silently increase NewSize // if the user specified a smaller or unaligned value. - smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment)); - if (smallest_new_size != NewSize) { + uintx bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize); + bounded_new_size = MAX2(smallest_new_size, (uintx)align_size_down(bounded_new_size, _gen_alignment)); + if (bounded_new_size != NewSize) { // Do not use FLAG_SET_ERGO to update NewSize here, since this will override // if NewSize was set on the command line or not. This information is needed // later when setting the initial and minimum young generation size. - NewSize = smallest_new_size; + NewSize = bounded_new_size; } + _min_gen0_size = smallest_new_size; _initial_gen0_size = NewSize; if (!FLAG_IS_DEFAULT(MaxNewSize)) { - uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size); - if (MaxNewSize >= MaxHeapSize) { // Make sure there is room for an old generation uintx smaller_max_new_size = MaxHeapSize - _gen_alignment; @@ -330,8 +345,8 @@ FLAG_SET_ERGO(uintx, NewSize, MaxNewSize); _initial_gen0_size = NewSize; } - } else if (MaxNewSize < min_new_size) { - FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size); + } else if (MaxNewSize < _initial_gen0_size) { + FLAG_SET_ERGO(uintx, MaxNewSize, _initial_gen0_size); } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) { FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment)); } @@ -361,7 +376,9 @@ GenCollectorPolicy::initialize_flags(); if (!is_size_aligned(OldSize, _gen_alignment)) { - FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment)); + // Setting OldSize directly to preserve information about the possible + // setting of OldSize on the command line. + OldSize = align_size_down(OldSize, _gen_alignment); } if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) { @@ -400,6 +417,20 @@ } } + // Update NewSize, if possible, to avoid sizing gen0 to small when only + // OldSize is set on the command line. + if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) { + if (OldSize < _initial_heap_byte_size) { + size_t new_size = _initial_heap_byte_size - OldSize; + // Need to compare against the flag value for max since _max_gen0_size + // might not have been set yet. + if (new_size >= _min_gen0_size && new_size <= MaxNewSize) { + FLAG_SET_ERGO(uintx, NewSize, new_size); + _initial_gen0_size = NewSize; + } + } + } + always_do_update_barrier = UseConcMarkSweepGC; DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();) @@ -441,57 +472,37 @@ // Given the maximum gen0 size, determine the initial and // minimum gen0 sizes. - if (_max_heap_byte_size == _min_heap_byte_size) { - // The maximum and minimum heap sizes are the same so the generations - // minimum and initial must be the same as its maximum. - _min_gen0_size = max_new_size; - _initial_gen0_size = max_new_size; - _max_gen0_size = max_new_size; + if (_max_heap_byte_size == _initial_heap_byte_size) { + // The maxium and initial heap sizes are the same so the generation's + // initial size must be the same as it maximum size. Use NewSize as the + // size if set on command line. + size_t fixed_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : max_new_size; + + _initial_gen0_size = fixed_young_size; + _max_gen0_size = fixed_young_size; + + // Also update the minimum size if min == initial == max. + if (_max_heap_byte_size == _min_heap_byte_size) { + _min_gen0_size = fixed_young_size; + } } else { size_t desired_new_size = 0; if (FLAG_IS_CMDLINE(NewSize)) { - // If NewSize is set on the command line, we must use it as - // the initial size and it also makes sense to use it as the - // lower limit. - _min_gen0_size = NewSize; - desired_new_size = NewSize; - max_new_size = MAX2(max_new_size, NewSize); - } else if (FLAG_IS_ERGO(NewSize)) { - // If NewSize is set ergonomically, we should use it as a lower - // limit, but use NewRatio to calculate the initial size. - _min_gen0_size = NewSize; + // If NewSize is set on the command line, we should use it as + // the initial size, but make sure it is within the heap bounds. desired_new_size = - MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); - max_new_size = MAX2(max_new_size, NewSize); + MIN2(max_new_size, bound_minus_alignment(NewSize, _initial_heap_byte_size)); + _min_gen0_size = bound_minus_alignment(desired_new_size, _min_heap_byte_size); } else { - // For the case where NewSize is the default, use NewRatio - // to size the minimum and initial generation sizes. - // Use the default NewSize as the floor for these values. If - // NewRatio is overly large, the resulting sizes can be too small. - _min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize); + // For the case where NewSize is not set on the command line, use + // NewRatio to size the initial generation size. Use the current + // NewSize as the floor, because if NewRatio is overly large, the resulting + // size can be too small. desired_new_size = - MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); + MIN2(max_new_size, MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize)); } - - assert(_min_gen0_size > 0, "Sanity check"); _initial_gen0_size = desired_new_size; _max_gen0_size = max_new_size; - - // At this point the desirable initial and minimum sizes have been - // determined without regard to the maximum sizes. - - // Bound the sizes by the corresponding overall heap sizes. - _min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size); - _initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size); - _max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size); - - // At this point all three sizes have been checked against the - // maximum sizes but have not been checked for consistency among the three. - - // Final check min <= initial <= max - _min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size); - _initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size); - _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size); } // Write back to flags if necessary. @@ -512,33 +523,6 @@ DEBUG_ONLY(GenCollectorPolicy::assert_size_info();) } -// Call this method during the sizing of the gen1 to make -// adjustments to gen0 because of gen1 sizing policy. gen0 initially has -// the most freedom in sizing because it is done before the -// policy for gen1 is applied. Once gen1 policies have been applied, -// there may be conflicts in the shape of the heap and this method -// is used to make the needed adjustments. The application of the -// policies could be more sophisticated (iterative for example) but -// keeping it simple also seems a worthwhile goal. -bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, - size_t* gen1_size_ptr, - const size_t heap_size) { - bool result = false; - - if ((*gen0_size_ptr + *gen1_size_ptr) > heap_size) { - uintx smallest_new_size = young_gen_size_lower_bound(); - if ((heap_size < (*gen0_size_ptr + _min_gen1_size)) && - (heap_size >= _min_gen1_size + smallest_new_size)) { - // Adjust gen0 down to accommodate _min_gen1_size - *gen0_size_ptr = align_size_down_bounded(heap_size - _min_gen1_size, _gen_alignment); - result = true; - } else { - *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment); - } - } - return result; -} - // Minimum sizes of the generations may be different than // the initial sizes. An inconsistency is permitted here // in the total size that can be specified explicitly by @@ -564,57 +548,64 @@ // with the overall heap size). In either case make // the minimum, maximum and initial sizes consistent // with the gen0 sizes and the overall heap sizes. - _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment); - _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment); + _min_gen1_size = _gen_alignment; + _initial_gen1_size = MIN2(_max_gen1_size, MAX2(_initial_heap_byte_size - _initial_gen0_size, _min_gen1_size)); // _max_gen1_size has already been made consistent above FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size); } else { - // OldSize has been explicitly set on the command line. Use the - // OldSize and then determine the consequences. - _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size); - _initial_gen1_size = OldSize; - + // OldSize has been explicitly set on the command line. Use it + // for the initial size but make sure the minimum allow a young + // generation to fit as well. // If the user has explicitly set an OldSize that is inconsistent // with other command line flags, issue a warning. // The generation minimums and the overall heap minimum should // be within one generation alignment. - if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) { - warning("Inconsistency between minimum heap size and minimum " - "generation sizes: using minimum heap = " SIZE_FORMAT, - _min_heap_byte_size); - } if (OldSize > _max_gen1_size) { warning("Inconsistency between maximum heap size and maximum " - "generation sizes: using maximum heap = " SIZE_FORMAT - " -XX:OldSize flag is being ignored", - _max_heap_byte_size); + "generation sizes: using maximum heap = " SIZE_FORMAT + " -XX:OldSize flag is being ignored", + _max_heap_byte_size); + FLAG_SET_ERGO(uintx, OldSize, _max_gen1_size); } - // If there is an inconsistency between the OldSize and the minimum and/or - // initial size of gen0, since OldSize was explicitly set, OldSize wins. - if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, _min_heap_byte_size)) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " - SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, - _min_gen0_size, _initial_gen0_size, _max_gen0_size); - } + + _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size); + _initial_gen1_size = OldSize; + } + + // The initial generation sizes should match the initial heap size, + // if not issue a warning and resize the generations. This behavior + // differs from JDK8 where the generation sizes have higher priority + // than the initial heap size. + if ((_initial_gen1_size + _initial_gen0_size) != _initial_heap_byte_size) { + warning("Inconsistency between generation sizes and heap size, resizing " + "the generations to fit the heap."); + + size_t desired_gen0_size = _initial_heap_byte_size - _initial_gen1_size; + if (_initial_heap_byte_size < _initial_gen1_size) { + // Old want all memory, use minimum for young and rest for old + _initial_gen0_size = _min_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size; + } else if (desired_gen0_size > _max_gen0_size) { + // Need to increase both young and old generation + _initial_gen0_size = _max_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _max_gen0_size; + } else if (desired_gen0_size < _min_gen0_size) { + // Need to decrease both young and old generation + _initial_gen0_size = _min_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size; + } else { + // The young generation boundaries allow us to only update the + // young generation. + _initial_gen0_size = desired_gen0_size; } - // The same as above for the old gen initial size. - if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, - _initial_heap_byte_size)) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 " - SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, - _min_gen0_size, _initial_gen0_size, _max_gen0_size); - } + + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " + SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, + _min_gen0_size, _initial_gen0_size, _max_gen0_size); } } - _min_gen1_size = MIN2(_min_gen1_size, _max_gen1_size); - - // Make sure that min gen1 <= initial gen1 <= max gen1. - _initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size); - _initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size); - // Write back to flags if necessary if (NewSize != _initial_gen0_size) { FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size); @@ -994,56 +985,88 @@ // verify that there are some basic rules for NewSize honored by the policies. class TestGenCollectorPolicy { public: - static void test() { + static void test_new_size() { size_t flag_value; save_flags(); - // Set some limits that makes the math simple. - FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); - FLAG_SET_ERGO(uintx, InitialHeapSize, 120 * M); - Arguments::set_min_heap_size(40 * M); - // If NewSize is set on the command line, it should be used // for both min and initial young size if less than min heap. flag_value = 20 * M; + set_basic_flag_values(); FLAG_SET_CMDLINE(uintx, NewSize, flag_value); - verify_min(flag_value); - verify_initial(flag_value); + verify_gen0_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_gen0_initial(flag_value); // If NewSize is set on command line, but is larger than the min // heap size, it should only be used for initial young size. flag_value = 80 * M; + set_basic_flag_values(); FLAG_SET_CMDLINE(uintx, NewSize, flag_value); - verify_initial(flag_value); + verify_gen0_initial(flag_value); // If NewSize has been ergonomically set, the collector policy // should use it for min but calculate the initial young size // using NewRatio. flag_value = 20 * M; + set_basic_flag_values(); FLAG_SET_ERGO(uintx, NewSize, flag_value); - verify_min(flag_value); - verify_scaled_initial(InitialHeapSize); + verify_gen0_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_ERGO(uintx, NewSize, flag_value); + verify_scaled_gen0_initial(InitialHeapSize); restore_flags(); + } + + static void test_old_size() { + size_t flag_value; + + save_flags(); + + // If OldSize is set on the command line, it should be used + // for both min and initial old size if less than min heap. + flag_value = 20 * M; + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + verify_gen1_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + verify_gen1_initial(flag_value); + + // If MaxNewSize is large, the maximum OldSize will be less than + // what's requested on the command line and it should be reset + // ergonomically. + flag_value = 30 * M; + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + FLAG_SET_CMDLINE(uintx, MaxNewSize, 170*M); + // Calculate what we expect the flag to be. + flag_value = MaxHeapSize - MaxNewSize; + verify_gen1_initial(flag_value); } - static void verify_min(size_t expected) { + static void verify_gen0_min(size_t expected) { MarkSweepPolicy msp; msp.initialize_all(); assert(msp.min_gen0_size() <= expected, err_msg("%zu > %zu", msp.min_gen0_size(), expected)); } - static void verify_initial(size_t expected) { + static void verify_gen0_initial(size_t expected) { MarkSweepPolicy msp; msp.initialize_all(); assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); } - static void verify_scaled_initial(size_t initial_heap_size) { + static void verify_scaled_gen0_initial(size_t initial_heap_size) { MarkSweepPolicy msp; msp.initialize_all(); @@ -1053,6 +1076,21 @@ err_msg("NewSize should have been set ergonomically to %zu, but was %zu", expected, NewSize)); } + static void verify_gen1_min(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.min_gen1_size() <= expected, err_msg("%zu > %zu", msp.min_gen1_size(), expected)); + } + + static void verify_gen1_initial(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.initial_gen1_size() == expected, err_msg("%zu != %zu", msp.initial_gen1_size(), expected)); + } + + private: static size_t original_InitialHeapSize; static size_t original_MaxHeapSize; @@ -1061,6 +1099,15 @@ static size_t original_NewSize; static size_t original_OldSize; + static void set_basic_flag_values() { + FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); + FLAG_SET_ERGO(uintx, InitialHeapSize, 100 * M); + FLAG_SET_ERGO(uintx, OldSize, 4 * M); + FLAG_SET_ERGO(uintx, NewSize, 1 * M); + FLAG_SET_ERGO(uintx, MaxNewSize, 80 * M); + Arguments::set_min_heap_size(40 * M); + } + static void save_flags() { original_InitialHeapSize = InitialHeapSize; original_MaxHeapSize = MaxHeapSize; @@ -1088,7 +1135,11 @@ size_t TestGenCollectorPolicy::original_OldSize = 0; void TestNewSize_test() { - TestGenCollectorPolicy::test(); + TestGenCollectorPolicy::test_new_size(); +} + +void TestOldSize_test() { + TestGenCollectorPolicy::test_old_size(); } #endif diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/collectorPolicy.hpp --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -248,13 +248,13 @@ // Compute max heap alignment. size_t compute_max_alignment(); - // Scale the base_size by NewRatio according to - // result = base_size / (NewRatio + 1) - // and align by min_alignment() - size_t scale_by_NewRatio_aligned(size_t base_size); + // Scale the base_size by NewRatio according to + // result = base_size / (NewRatio + 1) + // and align by min_alignment() + size_t scale_by_NewRatio_aligned(size_t base_size); - // Bound the value by the given maximum minus the min_alignment. - size_t bound_minus_alignment(size_t desired_size, size_t maximum_size); + // Bound the value by the given maximum minus the min_alignment. + size_t bound_minus_alignment(size_t desired_size, size_t maximum_size); public: GenCollectorPolicy(); @@ -335,10 +335,6 @@ virtual CollectorPolicy::Name kind() { return CollectorPolicy::TwoGenerationCollectorPolicyKind; } - - // Returns true if gen0 sizes were adjusted - bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - const size_t heap_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -374,7 +374,7 @@ ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); - const size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + const size_t metadata_prev_used = MetaspaceAux::used_bytes(); print_heap_before_gc(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/metaspace.cpp --- a/hotspot/src/share/vm/memory/metaspace.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/metaspace.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1447,7 +1447,7 @@ uint current_shrink_factor = _shrink_factor; _shrink_factor = 0; - const size_t used_after_gc = MetaspaceAux::allocated_capacity_bytes(); + const size_t used_after_gc = MetaspaceAux::capacity_bytes(); const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC(); const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0; @@ -2538,8 +2538,8 @@ // MetaspaceAux -size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0}; -size_t MetaspaceAux::_allocated_used_words[] = {0, 0}; +size_t MetaspaceAux::_capacity_words[] = {0, 0}; +size_t MetaspaceAux::_used_words[] = {0, 0}; size_t MetaspaceAux::free_bytes(Metaspace::MetadataType mdtype) { VirtualSpaceList* list = Metaspace::get_space_list(mdtype); @@ -2552,38 +2552,38 @@ void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); - assert(words <= allocated_capacity_words(mdtype), + assert(words <= capacity_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_capacity_words(mdtype))); - _allocated_capacity_words[mdtype] -= words; + " is greater than _capacity_words[%u] " SIZE_FORMAT, + words, mdtype, capacity_words(mdtype))); + _capacity_words[mdtype] -= words; } void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); // Needs to be atomic - _allocated_capacity_words[mdtype] += words; + _capacity_words[mdtype] += words; } void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) { - assert(words <= allocated_used_words(mdtype), + assert(words <= used_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_used_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_used_words(mdtype))); + " is greater than _used_words[%u] " SIZE_FORMAT, + words, mdtype, used_words(mdtype))); // For CMS deallocation of the Metaspaces occurs during the // sweep which is a concurrent phase. Protection by the expand_lock() // is not enough since allocation is on a per Metaspace basis // and protected by the Metaspace lock. jlong minus_words = (jlong) - (jlong) words; - Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(minus_words, &_used_words[mdtype]); } void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) { - // _allocated_used_words tracks allocations for + // _used_words tracks allocations for // each piece of metadata. Those allocations are // generally done concurrently by different application // threads so must be done atomically. - Atomic::add_ptr(words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(words, &_used_words[mdtype]); } size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) { @@ -2630,16 +2630,16 @@ size_t MetaspaceAux::capacity_bytes_slow() { #ifdef PRODUCT - // Use allocated_capacity_bytes() in PRODUCT instead of this function. + // Use capacity_bytes() in PRODUCT instead of this function. guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT"); #endif size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType); size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType); - assert(allocated_capacity_bytes() == class_capacity + non_class_capacity, - err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT + assert(capacity_bytes() == class_capacity + non_class_capacity, + err_msg("bad accounting: capacity_bytes() " SIZE_FORMAT " class_capacity + non_class_capacity " SIZE_FORMAT " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT, - allocated_capacity_bytes(), class_capacity + non_class_capacity, + capacity_bytes(), class_capacity + non_class_capacity, class_capacity, non_class_capacity)); return class_capacity + non_class_capacity; @@ -2699,14 +2699,14 @@ "->" SIZE_FORMAT "(" SIZE_FORMAT ")", prev_metadata_used, - allocated_used_bytes(), + used_bytes(), reserved_bytes()); } else { gclog_or_tty->print(" " SIZE_FORMAT "K" "->" SIZE_FORMAT "K" "(" SIZE_FORMAT "K)", prev_metadata_used/K, - allocated_used_bytes()/K, + used_bytes()/K, reserved_bytes()/K); } @@ -2722,8 +2722,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes()/K, - allocated_capacity_bytes()/K, + used_bytes()/K, + capacity_bytes()/K, committed_bytes()/K, reserved_bytes()/K); @@ -2734,8 +2734,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes(ct)/K, - allocated_capacity_bytes(ct)/K, + used_bytes(ct)/K, + capacity_bytes(ct)/K, committed_bytes(ct)/K, reserved_bytes(ct)/K); } @@ -2837,42 +2837,42 @@ void MetaspaceAux::verify_capacity() { #ifdef ASSERT - size_t running_sum_capacity_bytes = allocated_capacity_bytes(); + size_t running_sum_capacity_bytes = capacity_bytes(); // For purposes of the running sum of capacity, verify against capacity size_t capacity_in_use_bytes = capacity_bytes_slow(); assert(running_sum_capacity_bytes == capacity_in_use_bytes, - err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT + err_msg("capacity_words() * BytesPerWord " SIZE_FORMAT " capacity_bytes_slow()" SIZE_FORMAT, running_sum_capacity_bytes, capacity_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t capacity_in_use_bytes = capacity_bytes_slow(i); - assert(allocated_capacity_bytes(i) == capacity_in_use_bytes, - err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT + assert(capacity_bytes(i) == capacity_in_use_bytes, + err_msg("capacity_bytes(%u) " SIZE_FORMAT " capacity_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_capacity_bytes(i), i, capacity_in_use_bytes)); + i, capacity_bytes(i), i, capacity_in_use_bytes)); } #endif } void MetaspaceAux::verify_used() { #ifdef ASSERT - size_t running_sum_used_bytes = allocated_used_bytes(); + size_t running_sum_used_bytes = used_bytes(); // For purposes of the running sum of used, verify against used size_t used_in_use_bytes = used_bytes_slow(); - assert(allocated_used_bytes() == used_in_use_bytes, - err_msg("allocated_used_bytes() " SIZE_FORMAT + assert(used_bytes() == used_in_use_bytes, + err_msg("used_bytes() " SIZE_FORMAT " used_bytes_slow()" SIZE_FORMAT, - allocated_used_bytes(), used_in_use_bytes)); + used_bytes(), used_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t used_in_use_bytes = used_bytes_slow(i); - assert(allocated_used_bytes(i) == used_in_use_bytes, - err_msg("allocated_used_bytes(%u) " SIZE_FORMAT + assert(used_bytes(i) == used_in_use_bytes, + err_msg("used_bytes(%u) " SIZE_FORMAT " used_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_used_bytes(i), i, used_in_use_bytes)); + i, used_bytes(i), i, used_in_use_bytes)); } #endif } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/metaspace.hpp --- a/hotspot/src/share/vm/memory/metaspace.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/metaspace.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -280,11 +280,11 @@ // allocated to a Metaspace. This is used instead of // iterating over all the classloaders. One for each // type of Metadata - static size_t _allocated_capacity_words[Metaspace:: MetadataTypeCount]; - // Running sum of space in all Metachunks that have + static size_t _capacity_words[Metaspace:: MetadataTypeCount]; + // Running sum of space in all Metachunks that // are being used for metadata. One for each // type of Metadata. - static size_t _allocated_used_words[Metaspace:: MetadataTypeCount]; + static size_t _used_words[Metaspace:: MetadataTypeCount]; public: // Decrement and increment _allocated_capacity_words @@ -308,32 +308,32 @@ static size_t free_chunks_total_bytes(); static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); - static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) { - return _allocated_capacity_words[mdtype]; + static size_t capacity_words(Metaspace::MetadataType mdtype) { + return _capacity_words[mdtype]; } - static size_t allocated_capacity_words() { - return allocated_capacity_words(Metaspace::NonClassType) + - allocated_capacity_words(Metaspace::ClassType); + static size_t capacity_words() { + return capacity_words(Metaspace::NonClassType) + + capacity_words(Metaspace::ClassType); } - static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) { - return allocated_capacity_words(mdtype) * BytesPerWord; + static size_t capacity_bytes(Metaspace::MetadataType mdtype) { + return capacity_words(mdtype) * BytesPerWord; } - static size_t allocated_capacity_bytes() { - return allocated_capacity_words() * BytesPerWord; + static size_t capacity_bytes() { + return capacity_words() * BytesPerWord; } - static size_t allocated_used_words(Metaspace::MetadataType mdtype) { - return _allocated_used_words[mdtype]; + static size_t used_words(Metaspace::MetadataType mdtype) { + return _used_words[mdtype]; } - static size_t allocated_used_words() { - return allocated_used_words(Metaspace::NonClassType) + - allocated_used_words(Metaspace::ClassType); + static size_t used_words() { + return used_words(Metaspace::NonClassType) + + used_words(Metaspace::ClassType); } - static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) { - return allocated_used_words(mdtype) * BytesPerWord; + static size_t used_bytes(Metaspace::MetadataType mdtype) { + return used_words(mdtype) * BytesPerWord; } - static size_t allocated_used_bytes() { - return allocated_used_words() * BytesPerWord; + static size_t used_bytes() { + return used_words() * BytesPerWord; } static size_t free_bytes(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/memory/metaspaceCounters.cpp --- a/hotspot/src/share/vm/memory/metaspaceCounters.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/memory/metaspaceCounters.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -66,7 +66,7 @@ MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL; size_t MetaspaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspaceCounters::capacity() { @@ -98,7 +98,7 @@ MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL; size_t CompressedClassSpaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } size_t CompressedClassSpaceCounters::capacity() { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/constantPool.cpp --- a/hotspot/src/share/vm/oops/constantPool.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -144,6 +144,10 @@ // CDS support. Create a new resolved_references array. void ConstantPool::restore_unshareable_info(TRAPS) { + // Only create the new resolved references array and lock if it hasn't been + // attempted before + if (resolved_references() != NULL) return; + // restore the C++ vtable from the shared archive restore_vtable(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1289,17 +1289,18 @@ } -void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS) { +void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) { instanceKlassHandle h_this(THREAD, this); - do_local_static_fields_impl(h_this, f, CHECK); + do_local_static_fields_impl(h_this, f, mirror, CHECK); } -void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS) { +void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, + void f(fieldDescriptor* fd, Handle, TRAPS), Handle mirror, TRAPS) { for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { fieldDescriptor& fd = fs.field_descriptor(); - f(&fd, CHECK); + f(&fd, mirror, CHECK); } } } @@ -2240,9 +2241,7 @@ int num_methods = methods->length(); for (int index2 = 0; index2 < num_methods; ++index2) { methodHandle m(THREAD, methods->at(index2)); - m()->link_method(m, CHECK); - // restore method's vtable by calling a virtual function - m->restore_vtable(); + m->restore_unshareable_info(CHECK); } if (JvmtiExport::has_redefined_a_class()) { // Reinitialize vtable because RedefineClasses may have changed some @@ -3409,6 +3408,10 @@ ("purge: %s(%s): prev method @%d in version @%d is alive", method->name()->as_C_string(), method->signature()->as_C_string(), j, i)); + if (method->method_data() != NULL) { + // Clean out any weak method links + method->method_data()->clean_weak_method_links(); + } } } } @@ -3418,6 +3421,14 @@ ("purge: previous version stats: live=%d, deleted=%d", live_count, deleted_count)); } + + Array* methods = ik->methods(); + int num_methods = methods->length(); + for (int index2 = 0; index2 < num_methods; ++index2) { + if (methods->at(index2)->method_data() != NULL) { + methods->at(index2)->method_data()->clean_weak_method_links(); + } + } } // External interface for use during class unloading. diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -802,7 +802,7 @@ // Iterators void do_local_static_fields(FieldClosure* cl); void do_nonstatic_fields(FieldClosure* cl); // including inherited fields - void do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS); + void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS); void methods_do(void f(Method* method)); void array_klasses_do(void f(Klass* k)); @@ -1010,7 +1010,7 @@ static void set_initialization_state_and_notify_impl (instanceKlassHandle this_k, ClassState state, TRAPS); static void call_class_initializer_impl (instanceKlassHandle this_k, TRAPS); static Klass* array_klass_impl (instanceKlassHandle this_k, bool or_null, int n, TRAPS); - static void do_local_static_fields_impl (instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS); + static void do_local_static_fields_impl (instanceKlassHandle this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS); /* jni_id_for_impl for jfieldID only */ static JNIid* jni_id_for_impl (instanceKlassHandle this_k, int offset); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/instanceMirrorKlass.cpp --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -367,7 +367,12 @@ // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, this); - instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL); + instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); + + // Since mirrors can be variable sized because of the static fields, store + // the size in the mirror itself. + java_lang_Class::set_oop_size(i, size); + return i; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/klass.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -475,12 +475,8 @@ } void Klass::remove_unshareable_info() { - if (!DumpSharedSpaces) { - // Clean up after OOM during class loading - if (class_loader_data() != NULL) { - class_loader_data()->remove_class(this); - } - } + assert (DumpSharedSpaces, "only called for DumpSharedSpaces"); + set_subklass(NULL); set_next_sibling(NULL); // Clear the java mirror @@ -492,17 +488,26 @@ } void Klass::restore_unshareable_info(TRAPS) { - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - // Restore class_loader_data to the null class loader data - set_class_loader_data(loader_data); + // If an exception happened during CDS restore, some of these fields may already be + // set. We leave the class on the CLD list, even if incomplete so that we don't + // modify the CLD list outside a safepoint. + if (class_loader_data() == NULL) { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + // Restore class_loader_data to the null class loader data + set_class_loader_data(loader_data); - // Add to null class loader list first before creating the mirror - // (same order as class file parsing) - loader_data->add_class(this); + // Add to null class loader list first before creating the mirror + // (same order as class file parsing) + loader_data->add_class(this); + } // Recreate the class mirror. The protection_domain is always null for // boot loader, for now. - java_lang_Class::create_mirror(this, Handle(NULL), CHECK); + // Only recreate it if not present. A previous attempt to restore may have + // gotten an OOM later but keep the mirror if it was created. + if (java_mirror() == NULL) { + java_lang_Class::create_mirror(this, Handle(NULL), CHECK); + } } Klass* Klass::array_klass_or_null(int rank) { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -903,6 +903,19 @@ return adapter->get_c2i_entry(); } +void Method::restore_unshareable_info(TRAPS) { + // Since restore_unshareable_info can be called more than once for a method, don't + // redo any work. If this field is restored, there is nothing to do. + if (_from_compiled_entry == NULL) { + // restore method's vtable by calling a virtual function + restore_vtable(); + + methodHandle mh(THREAD, this); + link_method(mh, CHECK); + } +} + + // The verified_code_entry() must be called when a invoke is resolved // on this method. diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/method.hpp --- a/hotspot/src/share/vm/oops/method.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -123,6 +123,8 @@ void restore_vtable() { guarantee(is_method(), "vtable restored by this call"); } bool is_method() const volatile { return true; } + void restore_unshareable_info(TRAPS); + // accessors for instance variables ConstMethod* constMethod() const { return _constMethod; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/methodData.cpp --- a/hotspot/src/share/vm/oops/methodData.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/methodData.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1531,9 +1531,35 @@ } } -// Remove SpeculativeTrapData entries that reference an unloaded -// method -void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { +class CleanExtraDataClosure : public StackObj { +public: + virtual bool is_live(Method* m) = 0; +}; + +// Check for entries that reference an unloaded method +class CleanExtraDataKlassClosure : public CleanExtraDataClosure { +private: + BoolObjectClosure* _is_alive; +public: + CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {} + bool is_live(Method* m) { + return m->method_holder()->is_loader_alive(_is_alive); + } +}; + +// Check for entries that reference a redefined method +class CleanExtraDataMethodClosure : public CleanExtraDataClosure { +public: + CleanExtraDataMethodClosure() {} + bool is_live(Method* m) { + return m->on_stack(); + } +}; + + +// Remove SpeculativeTrapData entries that reference an unloaded or +// redefined method +void MethodData::clean_extra_data(CleanExtraDataClosure* cl) { DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); @@ -1544,7 +1570,7 @@ SpeculativeTrapData* data = new SpeculativeTrapData(dp); Method* m = data->method(); assert(m != NULL, "should have a method"); - if (!m->method_holder()->is_loader_alive(is_alive)) { + if (!cl->is_live(m)) { // "shift" accumulates the number of cells for dead // SpeculativeTrapData entries that have been seen so // far. Following entries must be shifted left by that many @@ -1575,9 +1601,9 @@ } } -// Verify there's no unloaded method referenced by a +// Verify there's no unloaded or redefined method referenced by a // SpeculativeTrapData entry -void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { +void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { #ifdef ASSERT DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); @@ -1587,7 +1613,7 @@ case DataLayout::speculative_trap_data_tag: { SpeculativeTrapData* data = new SpeculativeTrapData(dp); Method* m = data->method(); - assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); + assert(m != NULL && cl->is_live(m), "Method should exist"); break; } case DataLayout::bit_data_tag: @@ -1613,6 +1639,19 @@ parameters->clean_weak_klass_links(is_alive); } - clean_extra_data(is_alive); - verify_extra_data_clean(is_alive); + CleanExtraDataKlassClosure cl(is_alive); + clean_extra_data(&cl); + verify_extra_data_clean(&cl); } + +void MethodData::clean_weak_method_links() { + for (ProfileData* data = first_data(); + is_valid(data); + data = next_data(data)) { + data->clean_weak_method_links(); + } + + CleanExtraDataMethodClosure cl; + clean_extra_data(&cl); + verify_extra_data_clean(&cl); +} diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/methodData.hpp --- a/hotspot/src/share/vm/oops/methodData.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -251,6 +251,9 @@ // GC support void clean_weak_klass_links(BoolObjectClosure* cl); + + // Redefinition support + void clean_weak_method_links(); }; @@ -506,6 +509,9 @@ // GC support virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {} + // Redefinition support + virtual void clean_weak_method_links() {} + // CI translation: ProfileData can represent both MethodDataOop data // as well as CIMethodData data. This function is provided for translating // an oop in a ProfileData to the ci equivalent. Generally speaking, @@ -1989,6 +1995,7 @@ // CC_INTERP_ONLY(class BytecodeInterpreter;) +class CleanExtraDataClosure; class MethodData : public Metadata { friend class VMStructs; @@ -2146,9 +2153,9 @@ static bool profile_parameters_jsr292_only(); static bool profile_all_parameters(); - void clean_extra_data(BoolObjectClosure* is_alive); + void clean_extra_data(CleanExtraDataClosure* cl); void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); - void verify_extra_data_clean(BoolObjectClosure* is_alive); + void verify_extra_data_clean(CleanExtraDataClosure* cl); public: static int header_size() { @@ -2440,6 +2447,8 @@ static bool profile_return_jsr292_only(); void clean_method_data(BoolObjectClosure* is_alive); + + void clean_weak_method_links(); }; #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/oops/objArrayKlass.cpp --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -269,7 +269,7 @@ if (element_is_null || (new_val->klass())->is_subtype_of(bound)) { bs->write_ref_field_pre(p, new_val); - *p = *from; + *p = element; } else { // We must do a barrier to cover the partial copy. const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -70,6 +70,7 @@ JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) { Compile* C = Compile::current(); + C->print_inlining_update(this); if (is_osr()) { // The JVMS for a OSR has a single argument (see its TypeFunc). @@ -126,6 +127,7 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); bool is_static = method()->is_static(); address target = is_static ? SharedRuntime::get_resolve_static_call_stub() : SharedRuntime::get_resolve_opt_virtual_call_stub(); @@ -178,6 +180,8 @@ GraphKit kit(jvms); Node* receiver = kit.argument(0); + kit.C->print_inlining_update(this); + if (kit.C->log() != NULL) { kit.C->log()->elem("virtual_call bci='%d'", jvms->bci()); } @@ -271,14 +275,13 @@ LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : DirectCallGenerator(method, true), _inline_cg(inline_cg) {} - virtual bool is_late_inline() const { return true; } + virtual bool is_late_inline() const { return true; } // Convert the CallStaticJava into an inline virtual void do_late_inline(); virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); // Record that this call site should be revisited once the main // parse is finished. @@ -296,10 +299,11 @@ virtual void print_inlining_late(const char* msg) { CallNode* call = call_node(); Compile* C = Compile::current(); - C->print_inlining_insert(this); + C->print_inlining_assert_ready(); C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg); + C->print_inlining_move_to(this); + C->print_inlining_update_delayed(this); } - }; void LateInlineCallGenerator::do_late_inline() { @@ -360,6 +364,10 @@ map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1)); } + C->print_inlining_assert_ready(); + + C->print_inlining_move_to(this); + // This check is done here because for_method_handle_inline() method // needs jvms for inlined state. if (!do_late_inline_check(jvms)) { @@ -367,8 +375,6 @@ return; } - C->print_inlining_insert(this); - CompileLog* log = C->log(); if (log != NULL) { log->head("late_inline method='%d'", log->identify(method())); @@ -388,7 +394,7 @@ C->set_default_node_notes(entry_nn); } - // Now perform the inling using the synthesized JVMState + // Now perform the inlining using the synthesized JVMState JVMState* new_jvms = _inline_cg->generate(jvms, NULL); if (new_jvms == NULL) return; // no change if (C->failing()) return; @@ -431,6 +437,7 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser); + if (_input_not_const) { // inlining won't be possible so no need to enqueue right now. call_node()->set_generator(this); @@ -439,17 +446,14 @@ } return new_jvms; } - - virtual void print_inlining_late(const char* msg) { - if (!_input_not_const) return; - LateInlineCallGenerator::print_inlining_late(msg); - } }; bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) { CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const); + Compile::current()->print_inlining_update_delayed(this); + if (!_input_not_const) { _attempt++; } @@ -479,8 +483,6 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); - C->add_string_late_inline(this); JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); @@ -502,7 +504,6 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); C->add_boxing_late_inline(this); @@ -554,6 +555,8 @@ JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { Compile* C = Compile::current(); + C->print_inlining_update(this); + if (C->log() != NULL) { C->log()->elem("warm_call bci='%d'", jvms->bci()); } @@ -632,6 +635,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); PhaseGVN& gvn = kit.gvn(); // We need an explicit receiver null_check before checking its type. // We share a map with the caller, so his JVMS gets adjusted. @@ -779,6 +783,9 @@ assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; + } else { + const char* msg = "receiver not constant"; + if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); } } break; @@ -844,11 +851,13 @@ // provide us with a type speculative_receiver_type = receiver_type->speculative_type(); } - CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; + } else { + const char* msg = "member_name not constant"; + if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); } } break; @@ -904,6 +913,7 @@ if (kit.failing()) return NULL; // might happen because of NodeCountInliningCutoff + kit.C->print_inlining_update(this); SafePointNode* slow_map = NULL; JVMState* slow_jvms; if (slow_ctl != NULL) { @@ -1017,6 +1027,7 @@ JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). int nargs = method()->arg_size(); kit.inc_sp(nargs); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -662,6 +662,7 @@ _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), + _print_inlining_stream(NULL), _print_inlining_idx(0), _preserve_jvm_state(0) { C = this; @@ -723,9 +724,7 @@ PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (print_inlining() || print_intrinsics()) { - _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); - } + print_inlining_init(); { // Scope for timing the parser TracePhase t3("parse", &_t_parser, true); @@ -967,6 +966,7 @@ _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), + _print_inlining_stream(NULL), _print_inlining_idx(0), _preserve_jvm_state(0), _allowed_reasons(0) { @@ -2023,6 +2023,8 @@ ResourceMark rm; int loop_opts_cnt; + print_inlining_reinit(); + NOT_PRODUCT( verify_graph_edges(); ) print_method(PHASE_AFTER_PARSING); @@ -3755,30 +3757,114 @@ } } -void Compile::dump_inlining() { +// The message about the current inlining is accumulated in +// _print_inlining_stream and transfered into the _print_inlining_list +// once we know whether inlining succeeds or not. For regular +// inlining, messages are appended to the buffer pointed by +// _print_inlining_idx in the _print_inlining_list. For late inlining, +// a new buffer is added after _print_inlining_idx in the list. This +// way we can update the inlining message for late inlining call site +// when the inlining is attempted again. +void Compile::print_inlining_init() { + if (print_inlining() || print_intrinsics()) { + _print_inlining_stream = new stringStream(); + _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); + } +} + +void Compile::print_inlining_reinit() { + if (print_inlining() || print_intrinsics()) { + // Re allocate buffer when we change ResourceMark + _print_inlining_stream = new stringStream(); + } +} + +void Compile::print_inlining_reset() { + _print_inlining_stream->reset(); +} + +void Compile::print_inlining_commit() { + assert(print_inlining() || print_intrinsics(), "PrintInlining off?"); + // Transfer the message from _print_inlining_stream to the current + // _print_inlining_list buffer and clear _print_inlining_stream. + _print_inlining_list->at(_print_inlining_idx).ss()->write(_print_inlining_stream->as_string(), _print_inlining_stream->size()); + print_inlining_reset(); +} + +void Compile::print_inlining_push() { + // Add new buffer to the _print_inlining_list at current position + _print_inlining_idx++; + _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer()); +} + +Compile::PrintInliningBuffer& Compile::print_inlining_current() { + return _print_inlining_list->at(_print_inlining_idx); +} + +void Compile::print_inlining_update(CallGenerator* cg) { if (print_inlining() || print_intrinsics()) { + if (!cg->is_late_inline()) { + if (print_inlining_current().cg() != NULL) { + print_inlining_push(); + } + print_inlining_commit(); + } else { + if (print_inlining_current().cg() != cg && + (print_inlining_current().cg() != NULL || + print_inlining_current().ss()->size() != 0)) { + print_inlining_push(); + } + print_inlining_commit(); + print_inlining_current().set_cg(cg); + } + } +} + +void Compile::print_inlining_move_to(CallGenerator* cg) { + // We resume inlining at a late inlining call site. Locate the + // corresponding inlining buffer so that we can update it. + if (print_inlining()) { + for (int i = 0; i < _print_inlining_list->length(); i++) { + if (_print_inlining_list->adr_at(i)->cg() == cg) { + _print_inlining_idx = i; + return; + } + } + ShouldNotReachHere(); + } +} + +void Compile::print_inlining_update_delayed(CallGenerator* cg) { + if (print_inlining()) { + assert(_print_inlining_stream->size() > 0, "missing inlining msg"); + assert(print_inlining_current().cg() == cg, "wrong entry"); + // replace message with new message + _print_inlining_list->at_put(_print_inlining_idx, PrintInliningBuffer()); + print_inlining_commit(); + print_inlining_current().set_cg(cg); + } +} + +void Compile::print_inlining_assert_ready() { + assert(!_print_inlining || _print_inlining_stream->size() == 0, "loosing data"); +} + +void Compile::dump_inlining() { + bool do_print_inlining = print_inlining() || print_intrinsics(); + if (do_print_inlining) { // Print inlining message for candidates that we couldn't inline - // for lack of space or non constant receiver + // for lack of space for (int i = 0; i < _late_inlines.length(); i++) { CallGenerator* cg = _late_inlines.at(i); - cg->print_inlining_late("live nodes > LiveNodeCountInliningCutoff"); - } - Unique_Node_List useful; - useful.push(root()); - for (uint next = 0; next < useful.size(); ++next) { - Node* n = useful.at(next); - if (n->is_Call() && n->as_Call()->generator() != NULL && n->as_Call()->generator()->call_node() == n) { - CallNode* call = n->as_Call(); - CallGenerator* cg = call->generator(); - cg->print_inlining_late("receiver not constant"); - } - uint max = n->len(); - for ( uint i = 0; i < max; ++i ) { - Node *m = n->in(i); - if ( m == NULL ) continue; - useful.push(m); + if (!cg->is_mh_late_inline()) { + const char* msg = "live nodes > LiveNodeCountInliningCutoff"; + if (do_print_inlining) { + cg->print_inlining_late(msg); + } } } + } + if (do_print_inlining) { for (int i = 0; i < _print_inlining_list->length(); i++) { tty->print(_print_inlining_list->adr_at(i)->ss()->as_string()); } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -416,6 +416,7 @@ void set_cg(CallGenerator* cg) { _cg = cg; } }; + stringStream* _print_inlining_stream; GrowableArray* _print_inlining_list; int _print_inlining_idx; @@ -433,33 +434,24 @@ void* _replay_inline_data; // Pointer to data loaded from file + void print_inlining_init(); + void print_inlining_reinit(); + void print_inlining_commit(); + void print_inlining_push(); + PrintInliningBuffer& print_inlining_current(); + public: outputStream* print_inlining_stream() const { - return _print_inlining_list->adr_at(_print_inlining_idx)->ss(); - } - - void print_inlining_skip(CallGenerator* cg) { - if (_print_inlining) { - _print_inlining_list->adr_at(_print_inlining_idx)->set_cg(cg); - _print_inlining_idx++; - _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer()); - } + assert(print_inlining() || print_intrinsics(), "PrintInlining off?"); + return _print_inlining_stream; } - void print_inlining_insert(CallGenerator* cg) { - if (_print_inlining) { - for (int i = 0; i < _print_inlining_list->length(); i++) { - if (_print_inlining_list->adr_at(i)->cg() == cg) { - _print_inlining_list->insert_before(i+1, PrintInliningBuffer()); - _print_inlining_idx = i+1; - _print_inlining_list->adr_at(i)->set_cg(NULL); - return; - } - } - ShouldNotReachHere(); - } - } + void print_inlining_update(CallGenerator* cg); + void print_inlining_update_delayed(CallGenerator* cg); + void print_inlining_move_to(CallGenerator* cg); + void print_inlining_assert_ready(); + void print_inlining_reset(); void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) { stringStream ss; diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/opto/doCall.cpp --- a/hotspot/src/share/vm/opto/doCall.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -294,6 +294,8 @@ // There was no special inlining tactic, or it bailed out. // Use a more generic tactic, like a simple call. if (call_does_dispatch) { + const char* msg = "virtual call"; + if (PrintInlining) print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); return CallGenerator::for_virtual_call(callee, vtable_index); } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, @@ -396,6 +398,8 @@ // our contribution to it is cleaned up right here. kill_dead_locals(); + C->print_inlining_assert_ready(); + // Set frequently used booleans const bool is_virtual = bc() == Bytecodes::_invokevirtual; const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; @@ -531,7 +535,8 @@ // intrinsic was expecting to optimize. Should always be possible to // get a normal java call that may inline in that case cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false); - if ((new_jvms = cg->generate(jvms, this)) == NULL) { + new_jvms = cg->generate(jvms, this); + if (new_jvms == NULL) { guarantee(failing(), "call failed to generate: calls should work"); return; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -620,6 +620,7 @@ } // Push the result from the inlined method onto the stack. kit.push_result(); + C->print_inlining_update(this); return kit.transfer_exceptions_into_jvms(); } @@ -637,6 +638,7 @@ } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); + C->print_inlining_update(this); return NULL; } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -3877,6 +3877,7 @@ void TestMetachunk_test(); void TestVirtualSpaceNode_test(); void TestNewSize_test(); +void TestOldSize_test(); void TestKlass_test(); void TestBitMap_test(); #if INCLUDE_ALL_GCS @@ -3903,6 +3904,7 @@ run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); run_unit_test(TestNewSize_test()); + run_unit_test(TestOldSize_test()); run_unit_test(TestKlass_test()); run_unit_test(TestBitMap_test()); #if INCLUDE_VM_STRUCTS diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -438,6 +438,30 @@ return (mh->queued_for_compilation() || nm != NULL); WB_END +class VM_WhiteBoxOperation : public VM_Operation { + public: + VM_WhiteBoxOperation() { } + VMOp_Type type() const { return VMOp_WhiteBoxOperation; } + bool allow_nested_vm_operations() const { return true; } +}; + +class AlwaysFalseClosure : public BoolObjectClosure { + public: + bool do_object_b(oop p) { return false; } +}; + +static AlwaysFalseClosure always_false; + +class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation { + public: + VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { } + void doit() { + _mdo->clean_method_data(&always_false); + } + private: + MethodData* _mdo; +}; + WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION(env); @@ -453,6 +477,8 @@ for (int i = 0; i < arg_count; i++) { mdo->set_arg_modified(i, 0); } + VM_WhiteBoxCleanMethodData op(mdo); + VMThread::execute(&op); } mh->clear_not_c1_compilable(); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -307,6 +307,9 @@ JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, #endif // PRODUCT { "UseVMInterruptibleIO", JDK_Version::jdk(8), JDK_Version::jdk(9) }, + { "UseBoundThreads", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "DefaultThreadPriority", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "NoYieldsInMicrolock", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { NULL, JDK_Version(0), JDK_Version(0) } }; @@ -2078,17 +2081,6 @@ // Note: Needs platform-dependent factoring. bool status = true; - // Allow both -XX:-UseStackBanging and -XX:-UseBoundThreads in non-product - // builds so the cost of stack banging can be measured. -#if (defined(PRODUCT) && defined(SOLARIS)) - if (!UseBoundThreads && !UseStackBanging) { - jio_fprintf(defaultStream::error_stream(), - "-UseStackBanging conflicts with -UseBoundThreads\n"); - - status = false; - } -#endif - if (TLABRefillWasteFraction == 0) { jio_fprintf(defaultStream::error_stream(), "TLABRefillWasteFraction should be a denominator, " diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -929,6 +929,10 @@ } void os::print_date_and_time(outputStream *st) { + const int secs_per_day = 86400; + const int secs_per_hour = 3600; + const int secs_per_min = 60; + time_t tloc; (void)time(&tloc); st->print("time: %s", ctime(&tloc)); // ctime adds newline. @@ -937,7 +941,17 @@ // NOTE: It tends to crash after a SEGV if we want to printf("%f",...) in // Linux. Must be a bug in glibc ? Workaround is to round "t" to int // before printf. We lost some precision, but who cares? - st->print_cr("elapsed time: %d seconds", (int)t); + int eltime = (int)t; // elapsed time in seconds + + // print elapsed time in a human-readable format: + int eldays = eltime / secs_per_day; + int day_secs = eldays * secs_per_day; + int elhours = (eltime - day_secs) / secs_per_hour; + int hour_secs = elhours * secs_per_hour; + int elmins = (eltime - day_secs - hour_secs) / secs_per_min; + int minute_secs = elmins * secs_per_min; + int elsecs = (eltime - day_secs - hour_secs - minute_secs); + st->print_cr("elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs); } // moved from debug.cpp (used to be find()) but still called from there diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/os.hpp --- a/hotspot/src/share/vm/runtime/os.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -450,8 +450,8 @@ // yield that can be used in lieu of blocking. } ; static YieldResult NakedYield () ; - static void yield_all(int attempts = 0); // Yields to all other threads including lower priority - static void loop_breaker(int attempts); // called from within tight loops to possibly influence time-sharing + static void yield_all(); // Yields to all other threads including lower priority + // (for the default scheduling policy) static OSReturn set_priority(Thread* thread, ThreadPriority priority); static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/safepoint.cpp --- a/hotspot/src/share/vm/runtime/safepoint.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -319,7 +319,7 @@ if (steps < DeferThrSuspendLoopCount) { os::NakedYield() ; } else { - os::yield_all(steps) ; + os::yield_all() ; // Alternately, the VM thread could transiently depress its scheduling priority or // transiently increase the priority of the tardy mutator(s). } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -924,12 +924,6 @@ JRT_END #endif // !PRODUCT - -JRT_ENTRY(void, SharedRuntime::yield_all(JavaThread* thread, int attempts)) - os::yield_all(attempts); -JRT_END - - JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj)) assert(obj->is_oop(), "must be a valid oop"); assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise"); @@ -1268,8 +1262,6 @@ } #endif if (is_virtual) { - nmethod* nm = callee_nm; - if (nm == NULL) CodeCache::find_blob(caller_frame.pc()); CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc()); if (inline_cache->is_clean()) { inline_cache->set_to_monomorphic(virtual_call_info); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -253,9 +253,6 @@ // bytecode tracing is only used by the TraceBytecodes static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0; - // Used to back off a spin lock that is under heavy contention - static void yield_all(JavaThread* thread, int attempts = 0); - static oop retrieve_receiver( Symbol* sig, frame caller ); static void register_finalizer(JavaThread* thread, oopDesc* obj); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -1394,8 +1394,8 @@ void JavaThread::initialize() { // Initialize fields - // Set the claimed par_id to -1 (ie not claiming any par_ids) - set_claimed_par_id(-1); + // Set the claimed par_id to UINT_MAX (ie not claiming any par_ids) + set_claimed_par_id(UINT_MAX); set_saved_exception_pc(NULL); set_threadObj(NULL); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -1778,12 +1778,12 @@ void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); } private: // This field is used to determine if a thread has claimed - // a par_id: it is -1 if the thread has not claimed a par_id; + // a par_id: it is UINT_MAX if the thread has not claimed a par_id; // otherwise its value is the par_id that has been claimed. - int _claimed_par_id; + uint _claimed_par_id; public: - int get_claimed_par_id() { return _claimed_par_id; } - void set_claimed_par_id(int id) { _claimed_par_id = id;} + uint get_claimed_par_id() { return _claimed_par_id; } + void set_claimed_par_id(uint id) { _claimed_par_id = id;} }; // Inline implementation of JavaThread::current diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/vframe.cpp --- a/hotspot/src/share/vm/runtime/vframe.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/vframe.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -321,24 +321,38 @@ } } -StackValueCollection* interpretedVFrame::expressions() const { - int length = fr().interpreter_frame_expression_stack_size(); - if (method()->is_native()) { - // If the method is native, there is no expression stack - length = 0; +StackValueCollection* interpretedVFrame::expressions() const { + + InterpreterOopMap oop_mask; + + if (!method()->is_native()) { + // Get oopmap describing oops and int for current bci + if (TraceDeoptimization && Verbose) { + methodHandle m_h(method()); + OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); + } else { + method()->mask_for(bci(), &oop_mask); + } + } + + // If the bci is a call instruction, i.e. any of the invoke* instructions, + // the InterpreterOopMap does not include expression/operand stack liveness + // info in the oop_mask/bit_mask. This can lead to a discrepancy of what + // is actually on the expression stack compared to what is given by the + // oop_map. We need to use the length reported in the oop_map. + int length = oop_mask.expression_stack_size(); + + assert(fr().interpreter_frame_expression_stack_size() >= length, + "error in expression stack!"); + + StackValueCollection* result = new StackValueCollection(length); + + if (0 == length) { + return result; } int nof_locals = method()->max_locals(); - StackValueCollection* result = new StackValueCollection(length); - InterpreterOopMap oop_mask; - // Get oopmap describing oops and int for current bci - if (TraceDeoptimization && Verbose) { - methodHandle m_h(method()); - OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); - } else { - method()->mask_for(bci(), &oop_mask); - } // handle expressions for(int i=0; i < length; i++) { // Find stack location diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/vmThread.cpp --- a/hotspot/src/share/vm/runtime/vmThread.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/vmThread.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -305,6 +305,9 @@ _terminate_lock->notify(); } + // Thread destructor usually does this. + ThreadLocalStorage::set_thread(NULL); + // Deletion must be done synchronously by the JNI DestroyJavaVM thread // so that the VMThread deletion completes before the main thread frees // up the CodeHeap. diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/runtime/vm_operations.hpp --- a/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 19:37:43 2017 +0200 @@ -97,6 +97,7 @@ template(Exit) \ template(LinuxDllLoad) \ template(RotateGCLog) \ + template(WhiteBoxOperation) \ class VM_Operation: public CHeapObj { public: diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/services/memoryPool.cpp --- a/hotspot/src/share/vm/services/memoryPool.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/services/memoryPool.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -268,7 +268,7 @@ } size_t MetaspacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspacePool::calculate_max_size() const { @@ -280,7 +280,7 @@ MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { } size_t CompressedKlassSpacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } MemoryUsage CompressedKlassSpacePool::get_memory_usage() { diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/trace/trace.xml --- a/hotspot/src/share/vm/trace/trace.xml Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/trace/trace.xml Wed Jul 05 19:37:43 2017 +0200 @@ -185,7 +185,7 @@ - + diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/src/share/vm/utilities/taskqueue.cpp --- a/hotspot/src/share/vm/utilities/taskqueue.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -239,8 +239,8 @@ #ifdef TRACESPINNING void ParallelTaskTerminator::print_termination_counts() { - gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT - " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT, + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %u" + " Total spins: %u Total peeks: %u", total_yields(), total_spins(), total_peeks()); diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,142 @@ +/* + * 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. + */ + +import java.security.*; +import java.lang.instrument.*; +import java.lang.reflect.*; +import java.lang.management.ManagementFactory; +import com.sun.tools.attach.VirtualMachine; + +class A { + void m() { + } +} + +class B extends A { + void m() { + } +} + +class C extends A { + void m() { + } +} + +class Test { + + static public void m() throws Exception { + for (int i = 0; i < 20000; i++) { + m1(a); + } + for (int i = 0; i < 4; i++) { + m1(b); + } + } + + static boolean m1(A a) { + boolean res = Agent.m2(a); + return res; + } + + static public A a = new A(); + static public B b = new B(); + static public C c = new C(); +} + +public class Agent implements ClassFileTransformer { + + + static class MemoryChunk { + MemoryChunk other; + long[] array; + MemoryChunk(MemoryChunk other) { + other = other; + array = new long[1024 * 1024 * 1024]; + } + } + + static public boolean m2(A a) { + boolean res = false; + if (a.getClass() == B.class) { + a.m(); + } else { + res = true; + } + return res; + } + + static public void main(String[] args) throws Exception { + // Create speculative trap entries + Test.m(); + + String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); + int p = nameOfRunningVM.indexOf('@'); + String pid = nameOfRunningVM.substring(0, p); + + // Make the nmethod go away + for (int i = 0; i < 10; i++) { + System.gc(); + } + + // Redefine class + try { + VirtualMachine vm = VirtualMachine.attach(pid); + vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", ""); + vm.detach(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + Test.m(); + // GC will hit dead method pointer + for (int i = 0; i < 10; i++) { + System.gc(); + } + } + + public synchronized byte[] transform(final ClassLoader classLoader, + final String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) { + System.out.println("Transforming class " + className); + return classfileBuffer; + } + + public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) { + + try { + instrumentation.retransformClasses(to_redefine); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception { + Agent transformer = new Agent(); + instrumentation.addTransformer(transformer, true); + + redefine(agentArgs, instrumentation, Test.class); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,47 @@ +/* + * 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. + */ +import java.io.PrintWriter; +import com.oracle.java.testlibrary.*; + +/* + * @test + * @bug 8038636 + * @library /testlibrary + * @build Agent + * @run main ClassFileInstaller Agent + * @run main Launcher + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent + */ +public class Launcher { + public static void main(String[] args) throws Exception { + + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Agent-Class: Agent"); + pw.println("Can-Retransform-Classes: true"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"}); + pb.start().waitFor(); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/test/gc/g1/TestStringDeduplicationTools.java --- a/hotspot/test/gc/g1/TestStringDeduplicationTools.java Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java Wed Jul 05 19:37:43 2017 +0200 @@ -310,7 +310,9 @@ } System.gc(); + System.out.println("Heap Memory Usage: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()); + System.out.println("Array Header Size: " + unsafe.ARRAY_CHAR_BASE_OFFSET); System.out.println("End: MemoryUsageTest"); } @@ -482,31 +484,40 @@ public static void testMemoryUsage() throws Exception { // Test that memory usage is reduced after deduplication OutputAnalyzer output; - final String usagePattern = "Heap Memory Usage: (\\d+)"; + final String heapMemoryUsagePattern = "Heap Memory Usage: (\\d+)"; + final String arrayHeaderSizePattern = "Array Header Size: (\\d+)"; // Run without deduplication output = MemoryUsageTest.run(false); output.shouldHaveExitValue(0); - final long memoryUsageWithoutDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); + final long heapMemoryUsageWithoutDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); + final long arrayHeaderSizeWithoutDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); // Run with deduplication output = MemoryUsageTest.run(true); output.shouldHaveExitValue(0); - final long memoryUsageWithDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); + final long heapMemoryUsageWithDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); + final long arrayHeaderSizeWithDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); + + // Sanity check to make sure one instance isn't using compressed class pointers and the other not + if (arrayHeaderSizeWithoutDedup != arrayHeaderSizeWithDedup) { + throw new Exception("Unexpected difference between array header sizes"); + } // Calculate expected memory usage with deduplication enabled. This calculation does // not take alignment and padding into account, so it's a conservative estimate. - final long sizeOfChar = 2; // bytes - final long bytesSaved = (LargeNumberOfStrings - 1) * (StringLength * sizeOfChar + unsafe.ARRAY_CHAR_BASE_OFFSET); - final long memoryUsageWithDedupExpected = memoryUsageWithoutDedup - bytesSaved; + final long sizeOfChar = unsafe.ARRAY_CHAR_INDEX_SCALE; + final long sizeOfCharArray = StringLength * sizeOfChar + arrayHeaderSizeWithoutDedup; + final long bytesSaved = (LargeNumberOfStrings - 1) * sizeOfCharArray; + final long heapMemoryUsageWithDedupExpected = heapMemoryUsageWithoutDedup - bytesSaved; System.out.println("Memory usage summary:"); - System.out.println(" memoryUsageWithoutDedup: " + memoryUsageWithoutDedup); - System.out.println(" memoryUsageWithDedup: " + memoryUsageWithDedup); - System.out.println(" memoryUsageWithDedupExpected: " + memoryUsageWithDedupExpected); + System.out.println(" heapMemoryUsageWithoutDedup: " + heapMemoryUsageWithoutDedup); + System.out.println(" heapMemoryUsageWithDedup: " + heapMemoryUsageWithDedup); + System.out.println(" heapMemoryUsageWithDedupExpected: " + heapMemoryUsageWithDedupExpected); - if (memoryUsageWithDedup > memoryUsageWithDedupExpected) { - throw new Exception("Unexpected memory usage, memoryUsageWithDedup should less or equal to memoryUsageWithDedupExpected"); + if (heapMemoryUsageWithDedup > heapMemoryUsageWithDedupExpected) { + throw new Exception("Unexpected memory usage, heapMemoryUsageWithDedup should be less or equal to heapMemoryUsageWithDedupExpected"); } } } diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/test/runtime/6626217/Test6626217.sh --- a/hotspot/test/runtime/6626217/Test6626217.sh Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/test/runtime/6626217/Test6626217.sh Wed Jul 05 19:37:43 2017 +0200 @@ -22,7 +22,6 @@ # -# @ignore 8028733 # @test @(#)Test6626217.sh # @bug 6626217 # @summary Loader-constraint table allows arrays instead of only the base-classes diff -r 16ec7c58cdea -r cb2cf6e2958a hotspot/test/runtime/6888954/vmerrors.sh --- a/hotspot/test/runtime/6888954/vmerrors.sh Thu Apr 17 15:23:23 2014 -0700 +++ b/hotspot/test/runtime/6888954/vmerrors.sh Wed Jul 05 19:37:43 2017 +0200 @@ -85,7 +85,7 @@ [ $i -lt 10 ] && i2=0$i "$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \ - -XX:-TransmitErrorReport \ + -XX:-TransmitErrorReport -XX:-CreateMinidumpOnCrash \ -XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1 # If ErrorHandlerTest is ignored (product build), stop. diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/.hgtags --- a/jaxp/.hgtags Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/.hgtags Wed Jul 05 19:37:43 2017 +0200 @@ -251,3 +251,4 @@ 46e4951b2a267e98341613a3b796f2c7554eb831 jdk9-b06 389f4094fd603c17e215997b0b40171179629007 jdk9-b07 3b360a77658e6b3ac150dd7cdbff1a7abe855afc jdk9-b08 +f93a792fe37279d4d37aea86a99f3abbdc6fe79b jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java --- a/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xalan/internal/utils/SecuritySupport.java Wed Jul 05 19:37:43 2017 +0200 @@ -57,7 +57,7 @@ return securitySupport; } - static ClassLoader getContextClassLoader() { + public static ClassLoader getContextClassLoader() { return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ClassLoader cl = null; diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ElementSchemePointer.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ElementSchemePointer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ElementSchemePointer.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -19,7 +20,7 @@ */ package com.sun.org.apache.xerces.internal.xpointer; -import java.util.Hashtable; +import java.util.HashMap; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; import com.sun.org.apache.xerces.internal.util.SymbolTable; @@ -38,9 +39,8 @@ * @xerces.internal * * @version $Id: ElementSchemePointer.java,v 1.4 2009/06/11 23:51:50 joehw Exp $ - * */ -class ElementSchemePointer implements XPointerPart { +final class ElementSchemePointer implements XPointerPart { // Fields @@ -346,15 +346,17 @@ // Donot check for empty elements if the empty element is // a child of a found parent element - //if (!fIsElementFound) { - if (checkMatch()) { - fIsElementFound = true; + if (checkMatch()) { + if (!fIsElementFound) { fWasOnlyEmptyElementFound = true; } else { - fIsElementFound = false; + fWasOnlyEmptyElementFound = false; } - //} - + fIsElementFound = true; + } else { + fIsElementFound = false; + fWasOnlyEmptyElementFound = false; + } } } @@ -526,7 +528,7 @@ private SymbolTable fSymbolTable; - private Hashtable fTokenNames = new Hashtable(); + private HashMap fTokenNames = new HashMap<>(); /** * Constructor @@ -548,16 +550,7 @@ * @return String The token string */ private String getTokenString(int token) { - return (String) fTokenNames.get(new Integer(token)); - } - - /** - * Returns the token String - * @param token The index of the token - * @return String The token string - */ - private Integer getToken(int token) { - return (Integer) fTokenNames.get(new Integer(token)); + return fTokenNames.get(new Integer(token)); } /** @@ -566,12 +559,11 @@ * @param token The token string */ private void addToken(String tokenStr) { - Integer tokenInt = (Integer) fTokenNames.get(tokenStr); - if (tokenInt == null) { - tokenInt = new Integer(fTokenNames.size()); + if (!fTokenNames.containsValue(tokenStr)) { + Integer tokenInt = new Integer(fTokenNames.size()); fTokenNames.put(tokenInt, tokenStr); + addToken(tokenInt.intValue()); } - addToken(tokenInt.intValue()); } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ShortHandPointer.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ShortHandPointer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/ShortHandPointer.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,6 +18,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.xpointer; import com.sun.org.apache.xerces.internal.impl.Constants; @@ -37,9 +39,8 @@ * in document order that has a matching NCName as an identifier. *

* - * */ -class ShortHandPointer implements XPointerPart { +final class ShortHandPointer implements XPointerPart { // The name of the ShortHand pointer private String fShortHandPointer; @@ -261,7 +262,7 @@ * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#isChildFragmentResolved() */ public boolean isChildFragmentResolved() { - return fIsFragmentResolved & ( fMatchingChildCount > 0); + return fIsFragmentResolved && ( fMatchingChildCount > 0); } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerErrorHandler.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerErrorHandler.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerErrorHandler.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,6 +18,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.xpointer; import java.io.PrintWriter; @@ -31,7 +33,7 @@ * implementation and reported as resource errors. * */ -class XPointerErrorHandler implements XMLErrorHandler { +final class XPointerErrorHandler implements XMLErrorHandler { // // Data diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerHandler.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerHandler.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerHandler.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,10 +18,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.xpointer; -import java.util.Hashtable; -import java.util.Vector; +import java.util.ArrayList; +import java.util.HashMap; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; @@ -32,6 +34,7 @@ import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; +import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; @@ -64,8 +67,8 @@ XPointerProcessor { // Fields - // A Vector of XPointerParts - protected Vector fXPointerParts = null; + // An ArrayList of XPointerParts + protected ArrayList fXPointerParts = null; // The current XPointerPart protected XPointerPart fXPointerPart = null; @@ -102,7 +105,7 @@ public XPointerHandler() { super(); - fXPointerParts = new Vector(); + fXPointerParts = new ArrayList<>(); fSymbolTable = new SymbolTable(); } @@ -110,13 +113,17 @@ XMLErrorHandler errorHandler, XMLErrorReporter errorReporter) { super(); - fXPointerParts = new Vector(); + fXPointerParts = new ArrayList<>(); fSymbolTable = symbolTable; fErrorHandler = errorHandler; fXPointerErrorReporter = errorReporter; //fErrorReporter = errorReporter; // The XInclude ErrorReporter } + public void setDocumentHandler(XMLDocumentHandler handler) { + fDocumentHandler = handler; + } + // ************************************************************************ // Implementation of the XPointerProcessor interface. // ************************************************************************ @@ -300,7 +307,7 @@ // in the XPointer expression until a matching element is found. for (int i = 0; i < fXPointerParts.size(); i++) { - fXPointerPart = (XPointerPart) fXPointerParts.get(i); + fXPointerPart = fXPointerParts.get(i); if (fXPointerPart.resolveXPointer(element, attributes, augs, event)) { @@ -430,11 +437,11 @@ } /** - * Returns a Vector of XPointerPart objects + * Returns an ArrayList of XPointerPart objects * - * @return A Vector of XPointerPart objects. + * @return An ArrayList of XPointerPart objects. */ - public Vector getPointerParts() { + public ArrayList getPointerParts() { return fXPointerParts; } @@ -480,7 +487,7 @@ private SymbolTable fSymbolTable; - private Hashtable fTokenNames = new Hashtable(); + private HashMap fTokenNames = new HashMap<>(); /** * Constructor @@ -508,7 +515,7 @@ * @return String The token string */ private String getTokenString(int token) { - return (String) fTokenNames.get(new Integer(token)); + return fTokenNames.get(new Integer(token)); } /** @@ -517,12 +524,11 @@ * @param token The token string */ private void addToken(String tokenStr) { - Integer tokenInt = (Integer) fTokenNames.get(tokenStr); - if (tokenInt == null) { - tokenInt = new Integer(fTokenNames.size()); + if (!fTokenNames.containsValue(tokenStr)) { + Integer tokenInt = new Integer(fTokenNames.size()); fTokenNames.put(tokenInt, tokenStr); + addToken(tokenInt.intValue()); } - addToken(tokenInt.intValue()); } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerMessageFormatter.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerMessageFormatter.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerMessageFormatter.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,6 +18,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.xpointer; import java.util.Locale; @@ -34,7 +36,7 @@ * * @version $Id: XPointerMessageFormatter.java,v 1.5 2010-11-01 04:40:26 joehw Exp $ */ -class XPointerMessageFormatter implements MessageFormatter { +final class XPointerMessageFormatter implements MessageFormatter { public static final String XPOINTER_DOMAIN = "http://www.w3.org/TR/XPTR"; diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerPart.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerPart.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerPart.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -17,6 +18,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.xpointer; import com.sun.org.apache.xerces.internal.xni.Augmentations; @@ -49,7 +51,7 @@ * Provides scheme specific parsing of a XPointer expression i.e. * the PointerPart or ShortHandPointer. * - * @param xpointer A String representing the PointerPart or ShortHandPointer. + * @param part A String representing the PointerPart or ShortHandPointer. * @throws XNIException Thrown if the PointerPart string does not conform to * the syntax defined by its scheme. * diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerProcessor.java --- a/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerProcessor.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xerces/internal/xpointer/XPointerProcessor.java Wed Jul 05 19:37:43 2017 +0200 @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -34,7 +35,6 @@ * * @xerces.internal * - * */ public interface XPointerProcessor { @@ -56,7 +56,6 @@ * @throws XNIException Thrown if the xpointer string does not conform to * the XPointer Framework syntax or the syntax of the pointer part does * not conform to its definition for its scheme. - * */ public void parseXPointer(String xpointer) throws XNIException; @@ -74,7 +73,6 @@ * 2 - An empty element call * @return true if the element was resolved by the xpointer * @throws XNIException Thrown to signal an error - * */ public boolean resolveXPointer(QName element, XMLAttributes attributes, Augmentations augs, int event) throws XNIException; @@ -86,7 +84,6 @@ * @return True if the xpointer expression matches a node/fragment in the resource * else returns false. * @throws XNIException Thrown to signal an error - * */ public boolean isFragmentResolved() throws XNIException; @@ -97,7 +94,6 @@ * @return True if the xpointer expression matches a fragment in the resource * else returns false. * @throws XNIException Thrown to signal an error - * */ public boolean isXPointerResolved() throws XNIException; diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xml/internal/serializer/CharInfo.java --- a/jaxp/src/com/sun/org/apache/xml/internal/serializer/CharInfo.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/CharInfo.java Wed Jul 05 19:37:43 2017 +0200 @@ -22,6 +22,11 @@ */ package com.sun.org.apache.xml.internal.serializer; +import com.sun.org.apache.xalan.internal.utils.SecuritySupport; +import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; +import com.sun.org.apache.xml.internal.serializer.utils.SystemIDResolver; +import com.sun.org.apache.xml.internal.serializer.utils.Utils; +import com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -29,19 +34,11 @@ import java.net.URL; import java.util.Enumeration; import java.util.HashMap; +import java.util.Locale; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; -import java.security.AccessController; -import java.security.PrivilegedAction; - import javax.xml.transform.TransformerException; -import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; -import com.sun.org.apache.xml.internal.serializer.utils.SystemIDResolver; -import com.sun.org.apache.xml.internal.serializer.utils.Utils; -import com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException; -import com.sun.org.apache.xalan.internal.utils.ObjectFactory; - /** * This class provides services that tell if a character should have * special treatement, such as entity reference substitution or normalization @@ -176,13 +173,19 @@ // file // 3) try treating the resource a URI - if (internal) { - try { + try { + if (internal) { // Load entity property files by using PropertyResourceBundle, // cause of security issure for applets entities = PropertyResourceBundle.getBundle(entitiesResource); - } catch (Exception e) {} - } + } else { + ClassLoader cl = SecuritySupport.getContextClassLoader(); + if (cl != null) { + entities = PropertyResourceBundle.getBundle(entitiesResource, + Locale.getDefault(), cl); + } + } + } catch (Exception e) {} if (entities != null) { Enumeration keys = entities.getKeys(); @@ -198,6 +201,7 @@ set(S_CARRIAGERETURN); } else { InputStream is = null; + String err = null; // Load user specified resource file by using URL loading, it // requires a valid URI as parameter @@ -205,18 +209,22 @@ if (internal) { is = CharInfo.class.getResourceAsStream(entitiesResource); } else { - ClassLoader cl = ObjectFactory.findClassLoader(); - if (cl == null) { - is = ClassLoader.getSystemResourceAsStream(entitiesResource); - } else { - is = cl.getResourceAsStream(entitiesResource); + ClassLoader cl = SecuritySupport.getContextClassLoader(); + if (cl != null) { + try { + is = cl.getResourceAsStream(entitiesResource); + } catch (Exception e) { + err = e.getMessage(); + } } if (is == null) { try { URL url = new URL(entitiesResource); is = url.openStream(); - } catch (Exception e) {} + } catch (Exception e) { + err = e.getMessage(); + } } } @@ -224,7 +232,7 @@ throw new RuntimeException( Utils.messages.createMessage( MsgKey.ER_RESOURCE_COULD_NOT_FIND, - new Object[] {entitiesResource, entitiesResource})); + new Object[] {entitiesResource, err})); } // Fix Bugzilla#4000: force reading in UTF-8 @@ -456,64 +464,56 @@ return isCleanTextASCII[value]; } -// In the future one might want to use the array directly and avoid -// the method call, but I think the JIT alreay inlines this well enough -// so don't do it (for now) - bjm -// public final boolean[] getASCIIClean() -// { -// return isCleanTextASCII; -// } - - private static CharInfo getCharInfoBasedOnPrivilege( - final String entitiesFileName, final String method, - final boolean internal){ - return (CharInfo) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return new CharInfo(entitiesFileName, - method, internal);} - }); + /** + * Read an internal resource file that describes the mapping of + * characters to entity references; Construct a CharInfo object. + * + * @param entitiesFileName Name of entities resource file that should + * be loaded, which describes the mapping of characters to entity references. + * @param method the output method type, which should be one of "xml", "html", and "text". + * @return an instance of CharInfo + * + * @xsl.usage internal + */ + static CharInfo getCharInfoInternal(String entitiesFileName, String method) + { + CharInfo charInfo = (CharInfo) m_getCharInfoCache.get(entitiesFileName); + if (charInfo != null) { + return charInfo; + } + + charInfo = new CharInfo(entitiesFileName, method, true); + m_getCharInfoCache.put(entitiesFileName, charInfo); + return charInfo; } /** - * Factory that reads in a resource file that describes the mapping of - * characters to entity references. + * Constructs a CharInfo object using the following process to try reading + * the entitiesFileName parameter: * - * Resource files must be encoded in UTF-8 and have a format like: + * 1) attempt to load it as a ResourceBundle + * 2) try using the class loader to find the specified file + * 3) try opening it as an URI + * + * In case of 2 and 3, the resource file must be encoded in UTF-8 and have the + * following format: *
      * # First char # is a comment
      * Entity numericValue
      * quot 34
      * amp 38
      * 
- * (Note: Why don't we just switch to .properties files? Oct-01 -sc) * - * @param entitiesResource Name of entities resource file that should - * be loaded, which describes that mapping of characters to entity references. - * @param method the output method type, which should be one of "xml", "html", "text"... - * - * @xsl.usage internal + * @param entitiesFileName Name of entities resource file that should + * be loaded, which describes the mapping of characters to entity references. + * @param method the output method type, which should be one of "xml", "html", and "text". + * @return an instance of CharInfo */ static CharInfo getCharInfo(String entitiesFileName, String method) { - CharInfo charInfo = (CharInfo) m_getCharInfoCache.get(entitiesFileName); - if (charInfo != null) { - return charInfo; - } - - // try to load it internally - cache try { - charInfo = getCharInfoBasedOnPrivilege(entitiesFileName, - method, true); - m_getCharInfoCache.put(entitiesFileName, charInfo); - return charInfo; - } catch (Exception e) {} - - // try to load it externally - do not cache - try { - return getCharInfoBasedOnPrivilege(entitiesFileName, - method, false); + return new CharInfo(entitiesFileName, method, false); } catch (Exception e) {} String absoluteEntitiesFileName; @@ -530,8 +530,7 @@ } } - return getCharInfoBasedOnPrivilege(entitiesFileName, - method, false); + return new CharInfo(absoluteEntitiesFileName, method, false); } /** Table of user-specified char infos. */ diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java --- a/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Wed Jul 05 19:37:43 2017 +0200 @@ -60,7 +60,7 @@ */ private static final CharInfo m_htmlcharInfo = // new CharInfo(CharInfo.HTML_ENTITIES_RESOURCE); - CharInfo.getCharInfo(CharInfo.HTML_ENTITIES_RESOURCE, Method.HTML); + CharInfo.getCharInfoInternal(CharInfo.HTML_ENTITIES_RESOURCE, Method.HTML); /** A digital search trie for fast, case insensitive lookup of ElemDesc objects. */ static final Trie m_elementFlags = new Trie(); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxp/src/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java --- a/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxp/src/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java Wed Jul 05 19:37:43 2017 +0200 @@ -58,7 +58,7 @@ */ private static CharInfo m_xmlcharInfo = // new CharInfo(CharInfo.XML_ENTITIES_RESOURCE); - CharInfo.getCharInfo(CharInfo.XML_ENTITIES_RESOURCE, Method.XML); + CharInfo.getCharInfoInternal(CharInfo.XML_ENTITIES_RESOURCE, Method.XML); /** * Default constructor. diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/.hgtags --- a/jaxws/.hgtags Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/.hgtags Wed Jul 05 19:37:43 2017 +0200 @@ -254,3 +254,4 @@ cf0a6e41670f990414cd337000ad5f3bd1908073 jdk9-b06 856a9132f506cafe2f251c1a16a0b14e4d16048d jdk9-b07 2d9f4166e0be68aa43c5f4fd0f8d34768e11f652 jdk9-b08 +c9e8bb8c1144a966ca7b481142c6b5e55d14a29c jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaf_classes/javax/activation/CommandMap.java --- a/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java Wed Jul 05 19:37:43 2017 +0200 @@ -25,6 +25,9 @@ package javax.activation; +import java.util.Map; +import java.util.WeakHashMap; + /** * The CommandMap class provides an interface to a registry of @@ -38,6 +41,8 @@ */ public abstract class CommandMap { private static CommandMap defaultCommandMap = null; + private static Map map = + new WeakHashMap(); /** * Get the default CommandMap. @@ -56,11 +61,18 @@ * * @return the CommandMap */ - public static CommandMap getDefaultCommandMap() { - if (defaultCommandMap == null) - defaultCommandMap = new MailcapCommandMap(); + public static synchronized CommandMap getDefaultCommandMap() { + if (defaultCommandMap != null) + return defaultCommandMap; - return defaultCommandMap; + // fetch per-thread-context-class-loader default + ClassLoader tccl = SecuritySupport.getContextClassLoader(); + CommandMap def = map.get(tccl); + if (def == null) { + def = new MailcapCommandMap(); + map.put(tccl, def); + } + return def; } /** @@ -71,7 +83,7 @@ * @exception SecurityException if the caller doesn't have permission * to change the default */ - public static void setDefaultCommandMap(CommandMap commandMap) { + public static synchronized void setDefaultCommandMap(CommandMap commandMap) { SecurityManager security = System.getSecurityManager(); if (security != null) { try { @@ -79,13 +91,16 @@ security.checkSetFactory(); } catch (SecurityException ex) { // otherwise, we also allow it if this code and the - // factory come from the same class loader (e.g., + // factory come from the same (non-system) class loader (e.g., // the JAF classes were loaded with the applet classes). - if (CommandMap.class.getClassLoader() != + if (CommandMap.class.getClassLoader() == null || + CommandMap.class.getClassLoader() != commandMap.getClass().getClassLoader()) throw ex; } } + // remove any per-thread-context-class-loader CommandMap + map.remove(SecuritySupport.getContextClassLoader()); defaultCommandMap = commandMap; } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaf_classes/javax/activation/DataHandler.java --- a/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java Wed Jul 05 19:37:43 2017 +0200 @@ -368,7 +368,12 @@ // if it's not set, set it... if (transferFlavors == emptyFlavors) transferFlavors = getDataContentHandler().getTransferDataFlavors(); - return transferFlavors; + + if (transferFlavors == emptyFlavors) + return transferFlavors; + else + return transferFlavors.clone(); + } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java --- a/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java Wed Jul 05 19:37:43 2017 +0200 @@ -26,6 +26,8 @@ package javax.activation; import java.io.File; +import java.util.Map; +import java.util.WeakHashMap; /** * The FileTypeMap is an abstract class that provides a data typing @@ -48,6 +50,8 @@ public abstract class FileTypeMap { private static FileTypeMap defaultMap = null; + private static Map map = + new WeakHashMap(); /** * The default constructor. @@ -78,11 +82,11 @@ * Sets the default FileTypeMap for the system. This instance * will be returned to callers of getDefaultFileTypeMap. * - * @param map The FileTypeMap. + * @param fileTypeMap The FileTypeMap. * @exception SecurityException if the caller doesn't have permission * to change the default */ - public static void setDefaultFileTypeMap(FileTypeMap map) { + public static synchronized void setDefaultFileTypeMap(FileTypeMap fileTypeMap) { SecurityManager security = System.getSecurityManager(); if (security != null) { try { @@ -90,14 +94,17 @@ security.checkSetFactory(); } catch (SecurityException ex) { // otherwise, we also allow it if this code and the - // factory come from the same class loader (e.g., + // factory come from the same (non-system) class loader (e.g., // the JAF classes were loaded with the applet classes). - if (FileTypeMap.class.getClassLoader() != - map.getClass().getClassLoader()) + if (FileTypeMap.class.getClassLoader() == null || + FileTypeMap.class.getClassLoader() != + fileTypeMap.getClass().getClassLoader()) throw ex; } } - defaultMap = map; + // remove any per-thread-context-class-loader FileTypeMap + map.remove(SecuritySupport.getContextClassLoader()); + defaultMap = fileTypeMap; } /** @@ -109,10 +116,17 @@ * @return The default FileTypeMap * @see javax.activation.FileTypeMap#setDefaultFileTypeMap */ - public static FileTypeMap getDefaultFileTypeMap() { - // XXX - probably should be synchronized - if (defaultMap == null) - defaultMap = new MimetypesFileTypeMap(); - return defaultMap; + public static synchronized FileTypeMap getDefaultFileTypeMap() { + if (defaultMap != null) + return defaultMap; + + // fetch per-thread-context-class-loader default + ClassLoader tccl = SecuritySupport.getContextClassLoader(); + FileTypeMap def = map.get(tccl); + if (def == null) { + def = new MimetypesFileTypeMap(); + map.put(tccl, def); + } + return def; } } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java --- a/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java Wed Jul 05 19:37:43 2017 +0200 @@ -120,11 +120,7 @@ public class MailcapCommandMap extends CommandMap { /* * We manage a collection of databases, searched in order. - * The default database is shared between all instances - * of this class. - * XXX - Can we safely share more databases between instances? */ - private static MailcapFile defDB = null; private MailcapFile[] DB; private static final int PROG = 0; // programmatically added entries @@ -164,14 +160,10 @@ loadAllResources(dbv, "META-INF/mailcap"); LogSupport.log("MailcapCommandMap: load DEF"); - synchronized (MailcapCommandMap.class) { - // see if another instance has created this yet. - if (defDB == null) - defDB = loadResource("/META-INF/mailcap.default"); - } + mf = loadResource("/META-INF/mailcap.default"); - if (defDB != null) - dbv.add(defDB); + if (mf != null) + dbv.add(mf); DB = new MailcapFile[dbv.size()]; DB = (MailcapFile[])dbv.toArray(DB); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java --- a/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java Wed Jul 05 19:37:43 2017 +0200 @@ -69,11 +69,7 @@ public class MimetypesFileTypeMap extends FileTypeMap { /* * We manage a collection of databases, searched in order. - * The default database is shared between all instances - * of this class. - * XXX - Can we safely share more databases between instances? */ - private static MimeTypeFile defDB = null; private MimeTypeFile[] DB; private static final int PROG = 0; // programmatically added entries @@ -114,14 +110,10 @@ loadAllResources(dbv, "META-INF/mime.types"); LogSupport.log("MimetypesFileTypeMap: load DEF"); - synchronized (MimetypesFileTypeMap.class) { - // see if another instance has created this yet. - if (defDB == null) - defDB = loadResource("/META-INF/mimetypes.default"); - } + mf = loadResource("/META-INF/mimetypes.default"); - if (defDB != null) - dbv.addElement(defDB); + if (mf != null) + dbv.addElement(mf); DB = new MimeTypeFile[dbv.size()]; dbv.copyInto(DB); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.tools.internal.ws.wsdl.parser; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Internalizer.java --- a/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Internalizer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Internalizer.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -60,12 +60,10 @@ */ public class Internalizer { - private static final XPathFactory xpf = XmlUtil.newXPathFactory(true); - private final XPath xpath = xpf.newXPath(); + private final XPath xpath = xpf.get().newXPath(); private final DOMForest forest; private final ErrorReceiver errorReceiver; - public Internalizer(DOMForest forest, WsimportOptions options, ErrorReceiver errorReceiver) { this.forest = forest; this.errorReceiver = errorReceiver; @@ -77,6 +75,12 @@ } } + private static final ContextClassloaderLocal xpf = new ContextClassloaderLocal() { + @Override + protected XPathFactory initialValue() throws Exception { + return XPathFactory.newInstance(); + } + }; /** * Validates attributes of a <JAXWS:bindings> element. */ diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/JAXWSBindingExtensionHandler.java --- a/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/JAXWSBindingExtensionHandler.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/JAXWSBindingExtensionHandler.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -54,8 +54,14 @@ public class JAXWSBindingExtensionHandler extends AbstractExtensionHandler { // xml security enabled always, xpath used for parsing "part" attribute - private static final XPathFactory xpf = XmlUtil.newXPathFactory(true); - private final XPath xpath = xpf.newXPath(); + private static final ContextClassloaderLocal xpf = new ContextClassloaderLocal() { + @Override + protected XPathFactory initialValue() throws Exception { + return XPathFactory.newInstance(); + } + }; + + private final XPath xpath = xpf.get().newXPath(); public JAXWSBindingExtensionHandler(Map extensionHandlerMap) { super(extensionHandlerMap); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/Internalizer.java --- a/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/Internalizer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/Internalizer.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -76,8 +76,6 @@ private static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/"; - private static XPathFactory xpf = null; - private final XPath xpath; /** @@ -99,12 +97,7 @@ this.errorHandler = forest.getErrorHandler(); this.forest = forest; this.enableSCD = enableSCD; - synchronized (this) { - if (xpf == null) { - xpf = XmlFactory.createXPathFactory(disableSecureProcessing); - } - } - xpath = xpf.newXPath(); + xpath = XmlFactory.createXPathFactory(disableSecureProcessing).newXPath(); } /** @@ -170,7 +163,6 @@ if( a.getLocalName().equals("multiple") ) // continue; - // TODO: flag error for this undefined attribute } } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/DatatypeConverterImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/DatatypeConverterImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/DatatypeConverterImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -27,9 +27,14 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Calendar; +import java.util.Collections; import java.util.GregorianCalendar; +import java.util.Map; import java.util.TimeZone; +import java.util.WeakHashMap; import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverterInterface; @@ -356,7 +361,7 @@ public static GregorianCalendar _parseDateTime(CharSequence s) { String val = WhiteSpaceProcessor.trim(s).toString(); - return datatypeFactory.newXMLGregorianCalendar(val).toGregorianCalendar(); + return getDatatypeFactory().newXMLGregorianCalendar(val).toGregorianCalendar(); } public static String _printDateTime(Calendar val) { @@ -722,14 +727,30 @@ } return false; } - private static final DatatypeFactory datatypeFactory; + + private static final Map DF_CACHE = Collections.synchronizedMap(new WeakHashMap()); - static { - try { - datatypeFactory = DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException e) { - throw new Error(e); + public static DatatypeFactory getDatatypeFactory() { + ClassLoader tccl = AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + DatatypeFactory df = DF_CACHE.get(tccl); + if (df == null) { + synchronized (DatatypeConverterImpl.class) { + df = DF_CACHE.get(tccl); + if (df == null) { // to prevent multiple initialization + try { + df = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new Error(Messages.FAILED_TO_INITIALE_DATATYPE_FACTORY.format(),e); + } + DF_CACHE.put(tccl, df); + } + } } + return df; } private static final class CalendarFormatter { @@ -1045,7 +1066,7 @@ @Deprecated public Calendar parseTime(String lexicalXSDTime) { - return datatypeFactory.newXMLGregorianCalendar(lexicalXSDTime).toGregorianCalendar(); + return getDatatypeFactory().newXMLGregorianCalendar(lexicalXSDTime).toGregorianCalendar(); } @Deprecated @@ -1055,7 +1076,7 @@ @Deprecated public Calendar parseDate(String lexicalXSDDate) { - return datatypeFactory.newXMLGregorianCalendar(lexicalXSDDate).toGregorianCalendar(); + return getDatatypeFactory().newXMLGregorianCalendar(lexicalXSDDate).toGregorianCalendar(); } @Deprecated diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,48 @@ +/* + * 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 com.sun.xml.internal.bind; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * Message resources + */ +enum Messages { + FAILED_TO_INITIALE_DATATYPE_FACTORY, // 0 args + ; + + private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName()); + + @Override + public String toString() { + return format(); + } + + public String format( Object... args ) { + return MessageFormat.format( rb.getString(name()), args ); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,27 @@ +# +# 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. +# + +FAILED_TO_INITIALE_DATATYPE_FACTORY = \ + Failed to initialize JAXP 1.3 DatatypeFactory class. diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Messages.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Messages.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/Messages.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -60,7 +60,6 @@ PROPERTY_ORDER_CONTAINS_UNUSED_ENTRY, // 2 args INVALID_XML_ENUM_VALUE, // 2 arg - FAILED_TO_INITIALE_DATATYPE_FACTORY, // 0 args NO_IMAGE_WRITER, // 1 arg ILLEGAL_MIME_TYPE, // 2 args diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -63,9 +63,7 @@ import javax.imageio.stream.ImageOutputStream; import javax.xml.bind.ValidationEvent; import javax.xml.bind.helpers.ValidationEventImpl; -import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -574,7 +572,8 @@ public XMLGregorianCalendar parse(CharSequence lexical) throws SAXException { try { - return datatypeFactory.newXMLGregorianCalendar(lexical.toString().trim()); // (.trim() - issue 396) + return DatatypeConverterImpl.getDatatypeFactory() + .newXMLGregorianCalendar(lexical.toString().trim()); // (.trim() - issue 396) } catch (Exception e) { UnmarshallingContext.getInstance().handleError(e); return null; @@ -844,7 +843,7 @@ public Duration parse(CharSequence lexical) { TODO.checkSpec("JSR222 Issue #42"); - return datatypeFactory.newDuration(lexical.toString()); + return DatatypeConverterImpl.getDatatypeFactory().newDuration(lexical.toString()); } }); primaryList.add( @@ -885,21 +884,6 @@ } } - - /** - * Cached instance of {@link DatatypeFactory} to create - * {@link XMLGregorianCalendar} and {@link Duration}. - */ - private static final DatatypeFactory datatypeFactory = init(); - - private static DatatypeFactory init() { - try { - return DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException e) { - throw new Error(Messages.FAILED_TO_INITIALE_DATATYPE_FACTORY.format(),e); - } - } - private static void checkXmlGregorianCalendarFieldRef(QName type, XMLGregorianCalendar cal)throws javax.xml.bind.MarshalException{ StringBuilder buf = new StringBuilder(); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -129,14 +129,6 @@ private final Map bridges = new LinkedHashMap(); /** - * Shared instance of {@link TransformerFactory}. - * Lock before use, because a {@link TransformerFactory} is not thread-safe - * whereas {@link JAXBContextImpl} is. - * Lazily created. - */ - private volatile static SAXTransformerFactory tf; - - /** * Shared instance of {@link DocumentBuilder}. * Lock before use. Lazily created. */ @@ -705,13 +697,7 @@ */ static Transformer createTransformer(boolean disableSecureProcessing) { try { - if (tf==null) { - synchronized(JAXBContextImpl.class) { - if (tf==null) { - tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); - } - } - } + SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); return tf.newTransformer(); } catch (TransformerConfigurationException e) { throw new Error(e); // impossible @@ -723,13 +709,7 @@ */ public static TransformerHandler createTransformerHandler(boolean disableSecureProcessing) { try { - if (tf==null) { - synchronized(JAXBContextImpl.class) { - if (tf==null) { - tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); - } - } - } + SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); return tf.newTransformerHandler(); } catch (TransformerConfigurationException e) { throw new Error(e); // impossible diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Messages.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Messages.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/Messages.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -58,6 +58,7 @@ FAILED_TO_GENERATE_SCHEMA, // 0 args ERROR_PROCESSING_SCHEMA, // 0 args ILLEGAL_CONTENT, // 2 args + FAILED_TO_INITIALE_DATATYPE_FACTORY, // 2 args ; private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName()); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/XMLStreamWriterOutput.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -153,7 +153,6 @@ } } - /** * Reference to FI's XMLStreamWriter class, if FI can be loaded. */ @@ -162,9 +161,8 @@ private static Class initFIStAXWriterClass() { try { - ClassLoader loader = getClassLoader(); - Class llfisw = Class.forName("com.sun.xml.internal.org.jvnet.fastinfoset.stax.LowLevelFastInfosetStreamWriter", true, loader); - Class sds = loader.loadClass("com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer"); + Class llfisw = Class.forName("com.sun.xml.internal.org.jvnet.fastinfoset.stax.LowLevelFastInfosetStreamWriter"); + Class sds = Class.forName("com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer"); // Check if StAXDocumentSerializer implements LowLevelFastInfosetStreamWriter if (llfisw.isAssignableFrom(sds)) return sds; @@ -179,8 +177,7 @@ try { if (FI_STAX_WRITER_CLASS == null) return null; - ClassLoader loader = getClassLoader(); - Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.FastInfosetStreamWriterOutput", true, loader); + Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.FastInfosetStreamWriterOutput"); return c.getConstructor(FI_STAX_WRITER_CLASS, JAXBContextImpl.class); } catch (Throwable e) { return null; @@ -195,8 +192,7 @@ private static Class initStAXExWriterClass() { try { - ClassLoader loader = getClassLoader(); - return Class.forName("com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx",true,loader); + return Class.forName("com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx"); } catch (Throwable e) { return null; } @@ -204,20 +200,11 @@ private static Constructor initStAXExOutputClass() { try { - ClassLoader loader = getClassLoader(); - Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput",true, loader); + Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput"); return c.getConstructor(STAXEX_WRITER_CLASS); } catch (Throwable e) { return null; } } - private static ClassLoader getClassLoader() { - ClassLoader cl = SecureLoader.getClassClassLoader(UnmarshallerImpl.class); - if (cl == null) { - cl = SecureLoader.getContextClassLoader(); - } - return cl; - } - } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Messages.properties --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Messages.properties Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/reflect/Messages.properties Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, 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 @@ -38,3 +38,6 @@ NO_GETTER = \ The property has a setter "{0}" but no getter. \ For marshaller, please define getters. + +INVALID_XML_ENUM_VALUE = \ + "{0}" is not a valid value for {1}. diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXStreamConnector.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXStreamConnector.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXStreamConnector.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -336,9 +336,8 @@ private static Class initFIStAXReaderClass() { try { - ClassLoader cl = getClassLoader(); - Class fisr = cl.loadClass("com.sun.xml.internal.org.jvnet.fastinfoset.stax.FastInfosetStreamReader"); - Class sdp = cl.loadClass("com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser"); + Class fisr = Class.forName("com.sun.xml.internal.org.jvnet.fastinfoset.stax.FastInfosetStreamReader"); + Class sdp = Class.forName("com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser"); // Check if StAXDocumentParser implements FastInfosetStreamReader if (fisr.isAssignableFrom(sdp)) return sdp; @@ -354,7 +353,7 @@ if (FI_STAX_READER_CLASS == null) return null; - Class c = getClassLoader().loadClass( + Class c = Class.forName( "com.sun.xml.internal.bind.v2.runtime.unmarshaller.FastInfosetConnector"); return c.getConstructor(FI_STAX_READER_CLASS,XmlVisitor.class); } catch (Throwable e) { @@ -370,7 +369,7 @@ private static Class initStAXExReader() { try { - return getClassLoader().loadClass("com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx"); + return Class.forName("com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx"); } catch (Throwable e) { return null; } @@ -378,19 +377,11 @@ private static Constructor initStAXExConnector() { try { - Class c = getClassLoader().loadClass("com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXExConnector"); + Class c = Class.forName("com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXExConnector"); return c.getConstructor(STAX_EX_READER_CLASS,XmlVisitor.class); } catch (Throwable e) { return null; } } - private static ClassLoader getClassLoader() { - ClassLoader cl = SecureLoader.getClassClassLoader(UnmarshallerImpl.class); - if (cl == null) { - cl = SecureLoader.getContextClassLoader(); - } - return cl; - } - } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/AttachmentPartImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/AttachmentPartImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/AttachmentPartImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -62,61 +62,6 @@ Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); - static { - try { - CommandMap map = CommandMap.getDefaultCommandMap(); - if (map instanceof MailcapCommandMap) { - MailcapCommandMap mailMap = (MailcapCommandMap) map; - String hndlrStr = ";;x-java-content-handler="; - mailMap.addMailcap( - "text/xml" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"); - mailMap.addMailcap( - "application/xml" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"); - mailMap.addMailcap( - "application/fastinfoset" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.FastInfosetDataContentHandler"); - /* Image DataContentHandler handles all image types - mailMap.addMailcap( - "image/jpeg" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.JpegDataContentHandler"); - mailMap.addMailcap( - "image/gif" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.GifDataContentHandler"); */ - /*mailMap.addMailcap( - "multipart/*" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.MultipartDataContentHandler");*/ - mailMap.addMailcap( - "image/*" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.ImageDataContentHandler"); - mailMap.addMailcap( - "text/plain" - + hndlrStr - + "com.sun.xml.internal.messaging.saaj.soap.StringDataContentHandler"); - } else { - throw new SOAPExceptionImpl("Default CommandMap is not a MailcapCommandMap"); - } - } catch (Throwable t) { - log.log( - Level.SEVERE, - "SAAJ0508.soap.cannot.register.handlers", - t); - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } else { - throw new RuntimeException(t.getLocalizedMessage()); - } - } - }; - private final MimeHeaders headers; private MimeBodyPart rawContent = null; private DataHandler dataHandler = null; @@ -126,6 +71,12 @@ public AttachmentPartImpl() { headers = new MimeHeaders(); + + // initialization from here should cover most of cases; + // if not, it would be necessary to call + // AttachmentPartImpl.initializeJavaActivationHandlers() + // explicitly by programmer + initializeJavaActivationHandlers(); } public AttachmentPartImpl(MIMEPart part) { @@ -619,4 +570,43 @@ return headers; } + public static void initializeJavaActivationHandlers() { + // DataHandler.writeTo() may search for DCH. So adding some default ones. + try { + CommandMap map = CommandMap.getDefaultCommandMap(); + if (map instanceof MailcapCommandMap) { + MailcapCommandMap mailMap = (MailcapCommandMap) map; + + // registering our DCH since javamail's DCH doesn't handle + if (!cmdMapInitialized(mailMap)) { + mailMap.addMailcap("text/xml;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"); + mailMap.addMailcap("application/xml;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"); + mailMap.addMailcap("application/fastinfoset;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.FastInfosetDataContentHandler"); + mailMap.addMailcap("multipart/*;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.MultipartDataContentHandler"); + mailMap.addMailcap("image/*;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.ImageDataContentHandler"); + mailMap.addMailcap("text/plain;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.StringDataContentHandler"); + } + } + } catch (Throwable t) { + // ignore the exception. + } + } + + private static boolean cmdMapInitialized(MailcapCommandMap mailMap) { + + // checking fastinfoset handler, since this one is specific to SAAJ + CommandInfo[] commands = mailMap.getAllCommands("application/fastinfoset"); + if (commands == null || commands.length == 0) { + return false; + } + + String saajClassName = "com.sun.xml.internal.ws.binding.FastInfosetDataContentHandler"; + for (CommandInfo command : commands) { + String commandClass = command.getCommandClass(); + if (saajClassName.equals(commandClass)) { + return true; + } + } + return false; + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.messaging.saaj.soap; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/EnvelopeFactory.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/EnvelopeFactory.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/EnvelopeFactory.java Wed Jul 05 19:37:43 2017 +0200 @@ -25,7 +25,14 @@ package com.sun.xml.internal.messaging.saaj.soap; -import java.util.logging.Logger; +import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; +import com.sun.xml.internal.messaging.saaj.util.JAXMStreamSource; +import com.sun.xml.internal.messaging.saaj.util.LogDomainConstants; +import com.sun.xml.internal.messaging.saaj.util.ParserPool; +import com.sun.xml.internal.messaging.saaj.util.RejectDoctypeSaxFilter; +import com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; import javax.xml.parsers.SAXParser; import javax.xml.soap.SOAPException; @@ -39,13 +46,10 @@ import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; -import org.xml.sax.InputSource; -import org.xml.sax.XMLReader; +import com.sun.xml.internal.messaging.saaj.LazyEnvelopeSource; +import com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer; -import com.sun.xml.internal.messaging.saaj.LazyEnvelopeSource; -import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; -import com.sun.xml.internal.messaging.saaj.util.*; -import com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer; +import java.util.logging.Logger; /** * EnvelopeFactory creates SOAP Envelope objects using different @@ -54,10 +58,16 @@ public class EnvelopeFactory { protected static final Logger - log = Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, - "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); + log = Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, + "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); - private static ParserPool parserPool = new ParserPool(5); + private static ContextClassloaderLocal parserPool = + new ContextClassloaderLocal() { + @Override + protected ParserPool initialValue() throws Exception { + return new ParserPool(5); + } + }; public static Envelope createEnvelope(Source src, SOAPPartImpl soapPart) throws SOAPException @@ -130,15 +140,15 @@ SAXParser saxParser = null; if (src instanceof StreamSource) { try { - saxParser = parserPool.get(); + saxParser = parserPool.get().get(); } catch (Exception e) { log.severe("SAAJ0601.util.newSAXParser.exception"); throw new SOAPExceptionImpl( - "Couldn't get a SAX parser while constructing a envelope", - e); + "Couldn't get a SAX parser while constructing a envelope", + e); } InputSource is = SAXSource.sourceToInputSource(src); - if (is.getEncoding()== null && soapPart.getSourceCharsetEncoding() != null) { + if (is.getEncoding() == null && soapPart.getSourceCharsetEncoding() != null) { is.setEncoding(soapPart.getSourceCharsetEncoding()); } XMLReader rejectFilter; @@ -147,15 +157,15 @@ } catch (Exception ex) { log.severe("SAAJ0510.soap.cannot.create.envelope"); throw new SOAPExceptionImpl( - "Unable to create envelope from given source: ", - ex); + "Unable to create envelope from given source: ", + ex); } src = new SAXSource(rejectFilter, is); } try { Transformer transformer = - EfficientStreamingTransformer.newTransformer(); + EfficientStreamingTransformer.newTransformer(); DOMResult result = new DOMResult(soapPart); transformer.transform(src, result); @@ -167,11 +177,11 @@ } log.severe("SAAJ0511.soap.cannot.create.envelope"); throw new SOAPExceptionImpl( - "Unable to create envelope from given source: ", - ex); + "Unable to create envelope from given source: ", + ex); } finally { if (saxParser != null) { - parserPool.returnParser(saxParser); + parserPool.get().returnParser(saxParser); } } } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.stream.buffer; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/XMLStreamBuffer.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -370,7 +370,12 @@ writeTo(handler, errorHandler, isFragment()); } - private static final TransformerFactory trnsformerFactory = TransformerFactory.newInstance(); + private static final ContextClassloaderLocal trnsformerFactory = new ContextClassloaderLocal() { + @Override + protected TransformerFactory initialValue() throws Exception { + return TransformerFactory.newInstance(); + } + }; /** * Writes out the contents of this buffer as DOM node and append that to the given node. @@ -382,7 +387,7 @@ */ public final Node writeTo(Node n) throws XMLStreamBufferException { try { - Transformer t = trnsformerFactory.newTransformer(); + Transformer t = trnsformerFactory.get().newTransformer(); t.transform(new XMLStreamBufferSource(this), new DOMResult(n)); return n.getLastChild(); } catch (TransformerException e) { diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.ws.api.streaming; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -63,39 +63,43 @@ private static final Logger LOGGER = Logger.getLogger(XMLStreamReaderFactory.class.getName()); + private static final String CLASS_NAME_OF_WSTXINPUTFACTORY = "com.ctc.wstx.stax.WstxInputFactory"; + /** * Singleton instance. */ - private static volatile @NotNull XMLStreamReaderFactory theInstance; + private static volatile ContextClassloaderLocal streamReader = + new ContextClassloaderLocal() { - private static final String CLASS_NAME_OF_WSTXINPUTFACTORY = "com.ctc.wstx.stax.WstxInputFactory"; + @Override + protected XMLStreamReaderFactory initialValue() { - static { - XMLInputFactory xif = getXMLInputFactory(); - XMLStreamReaderFactory f=null; + XMLInputFactory xif = getXMLInputFactory(); + XMLStreamReaderFactory f=null; - // this system property can be used to disable the pooling altogether, - // in case someone hits an issue with pooling in the production system. - if(!getProperty(XMLStreamReaderFactory.class.getName()+".noPool")) { - f = Zephyr.newInstance(xif); - } + // this system property can be used to disable the pooling altogether, + // in case someone hits an issue with pooling in the production system. + if(!getProperty(XMLStreamReaderFactory.class.getName()+".noPool")) { + f = Zephyr.newInstance(xif); + } - if(f==null) { - // is this Woodstox? - if (xif.getClass().getName().equals(CLASS_NAME_OF_WSTXINPUTFACTORY)) { - f = new Woodstox(xif); - } - } + if(f==null) { + // is this Woodstox? + if (xif.getClass().getName().equals(CLASS_NAME_OF_WSTXINPUTFACTORY)) { + f = new Woodstox(xif); + } + } - if (f==null) { - f = new Default(); - } + if (f==null) { + f = new Default(); + } - theInstance = f; - if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", theInstance); - } - } + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", f); + } + return f; + } + }; private static XMLInputFactory getXMLInputFactory() { XMLInputFactory xif = null; @@ -126,11 +130,11 @@ if(f==null) { throw new IllegalArgumentException(); } - theInstance = f; + streamReader.set(f); } public static XMLStreamReaderFactory get() { - return theInstance; + return streamReader.get(); } public static XMLStreamReader create(InputSource source, boolean rejectDTDs) { diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamWriterFactory.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamWriterFactory.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamWriterFactory.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -62,52 +62,54 @@ /** * Singleton instance. */ - private static volatile @NotNull XMLStreamWriterFactory theInstance; - + private static volatile ContextClassloaderLocal writerFactory = + new ContextClassloaderLocal() { - static { - XMLOutputFactory xof = null; - if (Boolean.getBoolean(XMLStreamWriterFactory.class.getName()+".woodstox")) { - try { - xof = (XMLOutputFactory)Class.forName("com.ctc.wstx.stax.WstxOutputFactory").newInstance(); - } catch (Exception e) { - // Ignore and fallback to default XMLOutputFactory + @Override + protected XMLStreamWriterFactory initialValue() { + XMLOutputFactory xof = null; + if (Boolean.getBoolean(XMLStreamWriterFactory.class.getName()+".woodstox")) { + try { + xof = (XMLOutputFactory)Class.forName("com.ctc.wstx.stax.WstxOutputFactory").newInstance(); + } catch (Exception e) { + // Ignore and fallback to default XMLOutputFactory + } } - } - if (xof == null) { - xof = XMLOutputFactory.newInstance(); - } + if (xof == null) { + xof = XMLOutputFactory.newInstance(); + } - XMLStreamWriterFactory f=null; + XMLStreamWriterFactory f=null; - // this system property can be used to disable the pooling altogether, - // in case someone hits an issue with pooling in the production system. - if (!Boolean.getBoolean(XMLStreamWriterFactory.class.getName()+".noPool")) { - try { - Class clazz = xof.createXMLStreamWriter(new StringWriter()).getClass(); - if (clazz.getName().startsWith("com.sun.xml.internal.stream.")) { - f = new Zephyr(xof,clazz); + // this system property can be used to disable the pooling altogether, + // in case someone hits an issue with pooling in the production system. + if (!Boolean.getBoolean(XMLStreamWriterFactory.class.getName()+".noPool")) { + try { + Class clazz = xof.createXMLStreamWriter(new StringWriter()).getClass(); + if (clazz.getName().startsWith("com.sun.xml.internal.stream.")) { + f = new Zephyr(xof,clazz); + } + } catch (XMLStreamException ex) { + Logger.getLogger(XMLStreamWriterFactory.class.getName()).log(Level.INFO, null, ex); + } catch (NoSuchMethodException ex) { + Logger.getLogger(XMLStreamWriterFactory.class.getName()).log(Level.INFO, null, ex); } - } catch (XMLStreamException ex) { - Logger.getLogger(XMLStreamWriterFactory.class.getName()).log(Level.INFO, null, ex); - } catch (NoSuchMethodException ex) { - Logger.getLogger(XMLStreamWriterFactory.class.getName()).log(Level.INFO, null, ex); + } + + if(f==null) { + // is this Woodstox? + if(xof.getClass().getName().equals("com.ctc.wstx.stax.WstxOutputFactory")) + f = new NoLock(xof); } + if (f == null) + f = new Default(xof); + + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, "XMLStreamWriterFactory instance is = {0}", f); + } + return f; } - - if(f==null) { - // is this Woodstox? - if(xof.getClass().getName().equals("com.ctc.wstx.stax.WstxOutputFactory")) - f = new NoLock(xof); - } - if (f == null) - f = new Default(xof); - - theInstance = f; - if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.log(Level.FINE, "XMLStreamWriterFactory instance is = {0}", f); - } - } + }; /** * See {@link #create(OutputStream)} for the contract. @@ -170,7 +172,7 @@ * Gets the singleton instance. */ public static @NotNull XMLStreamWriterFactory get() { - return theInstance; + return writerFactory.get(); } /** @@ -183,7 +185,7 @@ @SuppressWarnings({"null", "ConstantConditions"}) public static void set(@NotNull XMLStreamWriterFactory f) { if(f==null) throw new IllegalArgumentException(); - theInstance = f; + writerFactory.set(f); } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/BindingImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/BindingImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/binding/BindingImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -37,6 +37,9 @@ import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature; import com.sun.xml.internal.ws.developer.BindingTypeFeature; +import javax.activation.CommandInfo; +import javax.activation.CommandMap; +import javax.activation.MailcapCommandMap; import javax.xml.namespace.QName; import javax.xml.ws.Service; import javax.xml.ws.WebServiceFeature; @@ -151,12 +154,61 @@ return addressingVersion; } - public final @NotNull - Codec createCodec() { + public final Codec createCodec() { + + // initialization from here should cover most of cases; + // if not, it would be necessary to call + // BindingImpl.initializeJavaActivationHandlers() + // explicitly by programmer + initializeJavaActivationHandlers(); + return bindingId.createEncoder(this); } + public static void initializeJavaActivationHandlers() { + // DataHandler.writeTo() may search for DCH. So adding some default ones. + try { + CommandMap map = CommandMap.getDefaultCommandMap(); + if (map instanceof MailcapCommandMap) { + MailcapCommandMap mailMap = (MailcapCommandMap) map; + + // registering our DCH since javamail's DCH doesn't handle + if (!cmdMapInitialized(mailMap)) { + mailMap.addMailcap("text/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler"); + mailMap.addMailcap("application/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler"); + mailMap.addMailcap("image/*;;x-java-content-handler=com.sun.xml.internal.ws.encoding.ImageDataContentHandler"); + mailMap.addMailcap("text/plain;;x-java-content-handler=com.sun.xml.internal.ws.encoding.StringDataContentHandler"); + } + } + } catch (Throwable t) { + // ignore the exception. + } + } + + private static boolean cmdMapInitialized(MailcapCommandMap mailMap) { + CommandInfo[] commands = mailMap.getAllCommands("text/xml"); + if (commands == null || commands.length == 0) { + return false; + } + + // SAAJ RI implements it's own DataHandlers which can be used for JAX-WS too; + // see com.sun.xml.internal.messaging.saaj.soap.AttachmentPartImpl#initializeJavaActivationHandlers + // so if found any of SAAJ or our own handler registered, we are ok; anyway using SAAJ directly here + // is not good idea since we don't want standalone JAX-WS to depend on specific SAAJ impl. + // This is also reason for duplication of Handler's code by JAX-WS + String saajClassName = "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler"; + String jaxwsClassName = "com.sun.xml.internal.ws.encoding.XmlDataContentHandler"; + for (CommandInfo command : commands) { + String commandClass = command.getCommandClass(); + if (saajClassName.equals(commandClass) || + jaxwsClassName.equals(commandClass)) { + return true; + } + } + return false; + } + public static BindingImpl create(@NotNull BindingID bindingId) { if (bindingId.equals(BindingID.XML_HTTP)) return new HTTPBindingImpl(); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.ws.commons.xmlutil; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/Converter.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/Converter.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/Converter.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -53,7 +53,12 @@ // prevents instantiation } private static final Logger LOGGER = Logger.getLogger(Converter.class); - private static final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); + private static final ContextClassloaderLocal xmlOutputFactory = new ContextClassloaderLocal() { + @Override + protected XMLOutputFactory initialValue() throws Exception { + return XMLOutputFactory.newInstance(); + } + }; private static final AtomicBoolean logMissingStaxUtilsWarning = new AtomicBoolean(false); /** @@ -110,7 +115,7 @@ stringOut = new StringWriter(); XMLStreamWriter writer = null; try { - writer = xmlOutputFactory.createXMLStreamWriter(stringOut); + writer = xmlOutputFactory.get().createXMLStreamWriter(stringOut); if (createIndenter) { writer = createIndenter(writer); } @@ -143,7 +148,7 @@ try { if (message != null) { - XMLStreamWriter xsw = xmlOutputFactory.createXMLStreamWriter(baos, encoding); + XMLStreamWriter xsw = xmlOutputFactory.get().createXMLStreamWriter(baos, encoding); try { message.writeTo(xsw); } finally { diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.ws.developer; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionEndpointReference.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionEndpointReference.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/MemberSubmissionEndpointReference.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -64,7 +64,12 @@ @XmlType(name = "EndpointReferenceType", namespace = MemberSubmissionEndpointReference.MSNS) public final class MemberSubmissionEndpointReference extends EndpointReference implements MemberSubmissionAddressingConstants { - private final static JAXBContext msjc = MemberSubmissionEndpointReference.getMSJaxbContext(); + private final static ContextClassloaderLocal msjc = new ContextClassloaderLocal() { + @Override + protected JAXBContext initialValue() throws Exception { + return MemberSubmissionEndpointReference.getMSJaxbContext(); + } + }; public MemberSubmissionEndpointReference() { } @@ -86,7 +91,7 @@ } try { - Unmarshaller unmarshaller = MemberSubmissionEndpointReference.msjc.createUnmarshaller(); + Unmarshaller unmarshaller = MemberSubmissionEndpointReference.msjc.get().createUnmarshaller(); MemberSubmissionEndpointReference epr = unmarshaller.unmarshal(source,MemberSubmissionEndpointReference.class).getValue(); this.addr = epr.addr; @@ -106,7 +111,7 @@ @Override public void writeTo(Result result) { try { - Marshaller marshaller = MemberSubmissionEndpointReference.msjc.createMarshaller(); + Marshaller marshaller = MemberSubmissionEndpointReference.msjc.get().createMarshaller(); //marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.marshal(this, result); } catch (JAXBException e) { diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeCodec.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeCodec.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeCodec.java Wed Jul 05 19:37:43 2017 +0200 @@ -34,8 +34,6 @@ import com.sun.xml.internal.ws.api.pipe.Codec; import com.sun.xml.internal.ws.api.pipe.ContentType; import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature; -import javax.activation.CommandMap; -import javax.activation.MailcapCommandMap; import java.io.IOException; import java.io.InputStream; @@ -63,33 +61,6 @@ */ abstract class MimeCodec implements Codec { - static { - // DataHandler.writeTo() may search for DCH. So adding some default ones. - try { - CommandMap map = CommandMap.getDefaultCommandMap(); - if (map instanceof MailcapCommandMap) { - MailcapCommandMap mailMap = (MailcapCommandMap) map; - String hndlrStr = ";;x-java-content-handler="; - // registering our DCH since javamail's DCH doesn't handle - // Source - mailMap.addMailcap( - "text/xml" + hndlrStr + XmlDataContentHandler.class.getName()); - mailMap.addMailcap( - "application/xml" + hndlrStr + XmlDataContentHandler.class.getName()); - if (map.createDataContentHandler("image/*") == null) { - mailMap.addMailcap( - "image/*" + hndlrStr + ImageDataContentHandler.class.getName()); - } - if (map.createDataContentHandler("text/plain") == null) { - mailMap.addMailcap( - "text/plain" + hndlrStr + StringDataContentHandler.class.getName()); - } - } - } catch (Throwable t) { - // ignore the exception. - } - } - public static final String MULTIPART_RELATED_MIME_TYPE = "multipart/related"; protected Codec mimeRootCodec; diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,84 @@ +/* + * 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 com.sun.xml.internal.ws.policy.sourcemodel.attach; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,27 @@ +# +# 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. +# + +# Error messages for ContextClassloaderLocal utility class +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ExternalAttachmentsUnmarshaller.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ExternalAttachmentsUnmarshaller.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ExternalAttachmentsUnmarshaller.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -83,7 +83,13 @@ private static final QName POLICY = new QName("http://www.w3.org/ns/ws-policy", "Policy"); private static final QName URI = new QName("http://www.w3.org/ns/ws-policy", "URI"); private static final QName POLICIES = new QName(PolicyConstants.SUN_MANAGEMENT_NAMESPACE, "Policies"); - private static final XMLInputFactory XML_INPUT_FACTORY = XMLInputFactory.newInstance(); + private static final ContextClassloaderLocal XML_INPUT_FACTORY = new ContextClassloaderLocal() { + @Override + protected XMLInputFactory initialValue() throws Exception { + return XMLInputFactory.newInstance(); + } + }; + private static final PolicyModelUnmarshaller POLICY_UNMARSHALLER = PolicyModelUnmarshaller.getXmlUnmarshaller(); private final Map map = new HashMap(); @@ -93,7 +99,7 @@ public static Map unmarshal(final Reader source) throws PolicyException { LOGGER.entering(source); try { - XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(source); + XMLEventReader reader = XML_INPUT_FACTORY.get().createXMLEventReader(source); ExternalAttachmentsUnmarshaller instance = new ExternalAttachmentsUnmarshaller(); final Map map = instance.unmarshal(reader, null); LOGGER.exiting(map); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.ws.spi; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ProviderImpl.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ProviderImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ProviderImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -80,7 +80,12 @@ */ public class ProviderImpl extends Provider { - private final static JAXBContext eprjc = getEPRJaxbContext(); + private final static ContextClassloaderLocal eprjc = new ContextClassloaderLocal() { + @Override + protected JAXBContext initialValue() throws Exception { + return getEPRJaxbContext(); + } + }; /** * Convenient singleton instance. @@ -148,7 +153,7 @@ return AccessController.doPrivileged(new PrivilegedAction() { public EndpointReference run() { try { - Unmarshaller unmarshaller = eprjc.createUnmarshaller(); + Unmarshaller unmarshaller = eprjc.get().createUnmarshaller(); return (EndpointReference) unmarshaller.unmarshal(eprInfoset); } catch (JAXBException e) { throw new WebServiceException("Error creating Marshaller or marshalling.", e); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.ws.util.xml; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -215,20 +215,28 @@ } } - static final TransformerFactory transformerFactory = newTransformerFactory(); - - static final SAXParserFactory saxParserFactory = newSAXParserFactory(true); + static final ContextClassloaderLocal transformerFactory = new ContextClassloaderLocal() { + @Override + protected TransformerFactory initialValue() throws Exception { + return TransformerFactory.newInstance(); + } + }; - static { - saxParserFactory.setNamespaceAware(true); - } + static final ContextClassloaderLocal saxParserFactory = new ContextClassloaderLocal() { + @Override + protected SAXParserFactory initialValue() throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + return factory; + } + }; /** * Creates a new identity transformer. */ public static Transformer newTransformer() { try { - return transformerFactory.newTransformer(); + return transformerFactory.get().newTransformer(); } catch (TransformerConfigurationException tex) { throw new IllegalStateException("Unable to create a JAXP transformer"); } @@ -243,9 +251,9 @@ // work around a bug in JAXP in JDK6u4 and earlier where the namespace processing // is not turned on by default StreamSource ssrc = (StreamSource) src; - TransformerHandler th = ((SAXTransformerFactory) transformerFactory).newTransformerHandler(); + TransformerHandler th = ((SAXTransformerFactory) transformerFactory.get()).newTransformerHandler(); th.setResult(result); - XMLReader reader = saxParserFactory.newSAXParser().getXMLReader(); + XMLReader reader = saxParserFactory.get().newSAXParser().getXMLReader(); reader.setContentHandler(th); reader.setProperty(LEXICAL_HANDLER_PROPERTY, th); reader.parse(toInputSource(ssrc)); diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.sun.xml.internal.xsom.util; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import java.util.WeakHashMap; + +/** + * Simple utility ensuring that the value is cached only in case it is non-internal implementation + */ +abstract class ContextClassloaderLocal { + + private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE"; + + private WeakHashMap CACHE = new WeakHashMap(); + + public V get() throws Error { + ClassLoader tccl = getContextClassLoader(); + V instance = CACHE.get(tccl); + if (instance == null) { + instance = createNewInstance(); + CACHE.put(tccl, instance); + } + return instance; + } + + public void set(V instance) { + CACHE.put(getContextClassLoader(), instance); + } + + protected abstract V initialValue() throws Exception; + + private V createNewInstance() { + try { + return initialValue(); + } catch (Exception e) { + throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e); + } + } + + private static String format(String property, Object... args) { + String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property); + return MessageFormat.format(text, args); + } + + private static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + return cl; + } + }); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,26 @@ +# +# 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. +# + +FAILED_TO_CREATE_NEW_INSTANCE=Failed to create new instance of {0} diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DomAnnotationParserFactory.java --- a/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DomAnnotationParserFactory.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DomAnnotationParserFactory.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -63,10 +63,15 @@ } public AnnotationParser create(boolean disableSecureProcessing) { - return new AnnotationParserImpl(); + return new AnnotationParserImpl(disableSecureProcessing); } - private static final SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + private static final ContextClassloaderLocal stf = new ContextClassloaderLocal() { + @Override + protected SAXTransformerFactory initialValue() throws Exception { + return (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + } + }; private static class AnnotationParserImpl extends AnnotationParser { @@ -82,8 +87,9 @@ AnnotationParserImpl(boolean disableSecureProcessing) { try { - transformer = stf.newTransformerHandler(); - stf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, disableSecureProcessing); + SAXTransformerFactory factory = stf.get(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, disableSecureProcessing); + transformer = factory.newTransformerHandler(); } catch (TransformerConfigurationException e) { throw new Error(e); // impossible } diff -r 16ec7c58cdea -r cb2cf6e2958a jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/W3CEndpointReference.java --- a/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/W3CEndpointReference.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jaxws/src/share/jaxws_classes/javax/xml/ws/wsaddressing/W3CEndpointReference.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -69,7 +69,7 @@ @XmlType(name="EndpointReferenceType",namespace=W3CEndpointReference.NS) public final class W3CEndpointReference extends EndpointReference { - private final static JAXBContext w3cjc = getW3CJaxbContext(); + private final JAXBContext w3cjc = getW3CJaxbContext(); // should be changed to package private, keeping original modifier to keep backwards compatibility protected static final String NS = "http://www.w3.org/2005/08/addressing"; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/.hgtags --- a/jdk/.hgtags Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/.hgtags Wed Jul 05 19:37:43 2017 +0200 @@ -251,3 +251,4 @@ cac7b28b8b1e0e11d7a8e1ac1fe75a03b3749eab jdk9-b06 f4e624447514f12dd7c51f1e5b0cb97efcd15be2 jdk9-b07 9e7bd44ea85c72318130379c34b98716b9c7c248 jdk9-b08 +2cef452ba711b17950da275fd15931925799f07c jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/CompileDemos.gmk --- a/jdk/make/CompileDemos.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/CompileDemos.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -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/,*)) diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/CopyFiles.gmk --- a/jdk/make/CopyFiles.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/CopyFiles.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -183,9 +174,9 @@ ########################################################################################## -ifeq ($(OPENJDK_TARGET_OS), windows) +ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),) - TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib + TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS)/lib $(LIBDIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings $(call install-file) diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/CopyIntoClasses.gmk --- a/jdk/make/CopyIntoClasses.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/CopyIntoClasses.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -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 += \ diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/CreateJars.gmk --- a/jdk/make/CreateJars.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/CreateJars.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -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. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/data/jdwp/jdwp.spec --- a/jdk/make/data/jdwp/jdwp.spec Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/data/jdwp/jdwp.spec Wed Jul 05 19:37:43 2017 +0200 @@ -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." "

" diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/mapfiles/libnet/mapfile-vers --- a/jdk/make/mapfiles/libnet/mapfile-vers Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/mapfiles/libnet/mapfile-vers Wed Jul 05 19:37:43 2017 +0200 @@ -94,6 +94,10 @@ Java_sun_net_sdp_SdpSupport_create0; Java_sun_net_spi_DefaultProxySelector_init; Java_sun_net_spi_DefaultProxySelector_getSystemProxy; + Java_sun_net_ExtendedOptionsImpl_init; + Java_sun_net_ExtendedOptionsImpl_setFlowOption; + Java_sun_net_ExtendedOptionsImpl_getFlowOption; + Java_sun_net_ExtendedOptionsImpl_flowSupported; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/make/profile-includes.txt --- a/jdk/make/profile-includes.txt Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/make/profile-includes.txt Wed Jul 05 19:37:43 2017 +0200 @@ -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 \ diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/aix/lib/tzmappings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/aix/lib/tzmappings Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,586 @@ +# +# +# Copyright (c) 1994, 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. +# + +# +# Portions Copyright (c) 2014 IBM Corporation +# + +# This table describes mappings between AIX time zone IDs and Java time zone +# IDs. Fields are separated by a single TAB ('\t'). Lines must be in the ascending +# order in ASCII. (non-ASCII characters can't be used.) +# NOTE +# This table format is not a public interface of any Java +# platforms. No applications should depend on this file in any form. +# This file has been generated using programs. Do not edit this file manually. +# +# Solaris Java + +ACST-9:30ACDT Australia/Adelaide +AST4 America/Curacao +AST4ADT America/Halifax +AST9 Pacific/Gambier +AST9ADT America/Anchorage +AZOREST1 Atlantic/Cape_Verde +AZOREST1AZOREDT Atlantic/Azores +Africa/Abidjan Africa/Abidjan +Africa/Accra Africa/Accra +Africa/Addis_Ababa Africa/Addis_Ababa +Africa/Algiers Africa/Algiers +Africa/Asmera Africa/Asmera +Africa/Bamako GMT +Africa/Bangui Africa/Bangui +Africa/Banjul Africa/Banjul +Africa/Bissau Africa/Bissau +Africa/Blantyre Africa/Blantyre +Africa/Brazzaville Africa/Luanda +Africa/Bujumbura Africa/Bujumbura +Africa/Cairo Africa/Cairo +Africa/Casablanca Africa/Casablanca +Africa/Ceuta Europe/Paris +Africa/Conakry Africa/Conakry +Africa/Dakar Africa/Dakar +Africa/Dar_es_Salaam Africa/Dar_es_Salaam +Africa/Djibouti Africa/Djibouti +Africa/Douala Africa/Douala +Africa/El_Aaiun Africa/Casablanca +Africa/Freetown Africa/Freetown +Africa/Gaborone Africa/Gaborone +Africa/Harare Africa/Harare +Africa/Johannesburg Africa/Johannesburg +Africa/Kampala Africa/Kampala +Africa/Khartoum Africa/Khartoum +Africa/Kigali Africa/Kigali +Africa/Kinshasa Africa/Kinshasa +Africa/Lagos Africa/Lagos +Africa/Libreville Africa/Libreville +Africa/Lome Africa/Lome +Africa/Luanda Africa/Luanda +Africa/Lubumbashi Africa/Lubumbashi +Africa/Lusaka Africa/Lusaka +Africa/Malabo Africa/Malabo +Africa/Maputo Africa/Maputo +Africa/Maseru Africa/Maseru +Africa/Mbabane Africa/Mbabane +Africa/Mogadishu Africa/Mogadishu +Africa/Monrovia Africa/Monrovia +Africa/Nairobi Africa/Nairobi +Africa/Ndjamena Africa/Ndjamena +Africa/Niamey Africa/Niamey +Africa/Nouakchott Africa/Nouakchott +Africa/Ouagadougou Africa/Ouagadougou +Africa/Porto-Novo Africa/Porto-Novo +Africa/Sao_Tome Africa/Sao_Tome +Africa/Timbuktu Africa/Timbuktu +Africa/Tripoli Africa/Tripoli +Africa/Tunis Africa/Tunis +Africa/Windhoek Africa/Windhoek +America/Adak America/Adak +America/Anchorage America/Anchorage +America/Anguilla America/Anguilla +America/Antigua America/Antigua +America/Araguaina America/Sao_Paulo +America/Argentina/Buenos_Aires America/Argentina/Buenos_Aires +America/Argentina/Catamarca America/Argentina/Catamarca +America/Argentina/ComodRivadavia America/Argentina/Catamarca +America/Argentina/Cordoba America/Argentina/Cordoba +America/Argentina/Jujuy America/Argentina/Jujuy +America/Argentina/La_Rioja America/Argentina/La_Rioja +America/Argentina/Mendoza America/Argentina/Mendoza +America/Argentina/Rio_Gallegos America/Argentina/Rio_Gallegos +America/Argentina/Salta America/Argentina/Salta +America/Argentina/San_Juan America/Argentina/San_Juan +America/Argentina/San_Luis America/Argentina/San_Luis +America/Argentina/Tucuman America/Argentina/Tucuman +America/Argentina/Ushuaia America/Argentina/Ushuaia +America/Aruba America/Aruba +America/Asuncion America/Asuncion +America/Atka America/Adak +America/Barbados America/Barbados +America/Belize America/Belize +America/Bogota America/Bogota +America/Boise America/Denver +America/Buenos_Aires America/Argentina/Buenos_Aires +America/Cancun America/Chicago +America/Caracas America/Caracas +America/Catamarca America/Argentina/Catamarca +America/Cayenne America/Cayenne +America/Cayman America/Cayman +America/Chicago America/Chicago +America/Chihuahua America/Denver +America/Coral_Harbour America/Atikokan +America/Cordoba America/Argentina/Cordoba +America/Costa_Rica America/Costa_Rica +America/Cuiaba America/Cuiaba +America/Curacao America/Curacao +America/Dawson America/Los_Angeles +America/Dawson_Creek America/Dawson_Creek +America/Denver America/Denver +America/Detroit America/New_York +America/Dominica America/Dominica +America/Edmonton America/Edmonton +America/El_Salvador America/El_Salvador +America/Ensenada America/Los_Angeles +America/Fort_Wayne America/Indiana/Indianapolis +America/Fortaleza America/Fortaleza +America/Glace_Bay America/Halifax +America/Godthab America/Godthab +America/Goose_Bay America/Thule +America/Grand_Turk America/Grand_Turk +America/Grenada America/Grenada +America/Guadeloupe America/Guadeloupe +America/Guatemala America/Guatemala +America/Guayaquil America/Guayaquil +America/Guyana America/Guyana +America/Halifax America/Halifax +America/Havana America/Havana +America/Indiana/Indianapolis America/Indianapolis +America/Indianapolis America/Indiana/Indianapolis +America/Inuvik America/Denver +America/Iqaluit America/New_York +America/Jamaica America/Jamaica +America/Jujuy America/Argentina/Jujuy +America/Juneau America/Anchorage +America/Knox_IN America/Indiana/Knox +America/La_Paz America/La_Paz +America/Lima America/Lima +America/Los_Angeles America/Los_Angeles +America/Louisville America/Kentucky/Louisville +America/Managua America/Managua +America/Manaus America/Manaus +America/Marigot America/Guadeloupe +America/Martinique America/Martinique +America/Mazatlan America/Mazatlan +America/Mendoza America/Argentina/Mendoza +America/Menominee America/Winnipeg +America/Mexico_City America/Mexico_City +America/Miquelon America/Miquelon +America/Moncton America/Moncton +America/Montevideo America/Montevideo +America/Montreal America/Montreal +America/Montserrat America/Montserrat +America/Nassau America/Nassau +America/New_York America/New_York +America/Nipigon America/New_York +America/Nome America/Anchorage +America/Noronha America/Noronha +America/Panama America/Panama +America/Pangnirtung America/Thule +America/Paramaribo America/Paramaribo +America/Phoenix America/Phoenix +America/Port-au-Prince America/Port-au-Prince +America/Port_of_Spain America/Port_of_Spain +America/Porto_Acre America/Rio_Branco +America/Puerto_Rico America/Puerto_Rico +America/Rainy_River America/Chicago +America/Rankin_Inlet America/Chicago +America/Regina America/Regina +America/Rio_Branco America/Rio_Branco +America/Rosario America/Argentina/Cordoba +America/Santiago America/Santiago +America/Santo_Domingo America/Santo_Domingo +America/Sao_Paulo America/Sao_Paulo +America/Scoresbysund America/Scoresbysund +America/Shiprock America/Denver +America/St_Barthelemy America/Guadeloupe +America/St_Johns America/St_Johns +America/St_Kitts America/St_Kitts +America/St_Lucia America/St_Lucia +America/St_Thomas America/St_Thomas +America/St_Vincent America/St_Vincent +America/Tegucigalpa America/Tegucigalpa +America/Thule America/Thule +America/Thunder_Bay America/New_York +America/Tijuana America/Tijuana +America/Toronto America/Toronto +America/Tortola America/Tortola +America/Vancouver America/Vancouver +America/Virgin America/St_Thomas +America/Whitehorse America/Los_Angeles +America/Winnipeg America/Winnipeg +America/Yakutat America/Anchorage +America/Yellowknife America/Denver +Antarctica/Casey Antarctica/Casey +Antarctica/DumontDUrville Antarctica/DumontDUrville +Antarctica/Mawson Antarctica/Mawson +Antarctica/McMurdo Antarctica/McMurdo +Antarctica/Palmer Antarctica/Palmer +Antarctica/South_Pole Antarctica/McMurdo +Arctic/Longyearbyen Europe/Oslo +Asia/Aden Asia/Aden +Asia/Almaty Asia/Almaty +Asia/Amman Asia/Amman +Asia/Anadyr Asia/Anadyr +Asia/Aqtau Asia/Aqtau +Asia/Aqtobe Asia/Aqtobe +Asia/Ashkhabad Asia/Ashkhabad +Asia/Baghdad Asia/Baghdad +Asia/Bahrain Asia/Bahrain +Asia/Baku Asia/Baku +Asia/Bangkok Asia/Bangkok +Asia/Beirut Asia/Beirut +Asia/Bishkek Asia/Bishkek +Asia/Brunei Asia/Brunei +Asia/Calcutta Asia/Calcutta +Asia/Chungking Asia/Shanghai +Asia/Colombo Asia/Colombo +Asia/Dacca Asia/Dacca +Asia/Damascus Asia/Damascus +Asia/Dhaka Asia/Dhaka +Asia/Dubai Asia/Dubai +Asia/Dushanbe Asia/Dushanbe +Asia/Gaza Asia/Amman +Asia/Harbin Asia/Shanghai +Asia/Hong_Kong Asia/Hong_Kong +Asia/Irkutsk Asia/Irkutsk +Asia/Istanbul Europe/Istanbul +Asia/Jakarta Asia/Jakarta +Asia/Jayapura Asia/Jayapura +Asia/Jerusalem Asia/Jerusalem +Asia/Kabul Asia/Kabul +Asia/Kamchatka Asia/Kamchatka +Asia/Karachi Asia/Karachi +Asia/Kashgar Asia/Shanghai +Asia/Katmandu Asia/Katmandu +Asia/Kolkata Asia/Kolkata +Asia/Krasnoyarsk Asia/Krasnoyarsk +Asia/Kuala_Lumpur Asia/Kuala_Lumpur +Asia/Kuwait Asia/Kuwait +Asia/Macao Asia/Macao +Asia/Magadan Asia/Magadan +Asia/Manila Asia/Manila +Asia/Muscat Asia/Muscat +Asia/Nicosia Asia/Nicosia +Asia/Novosibirsk Asia/Novosibirsk +Asia/Omsk Asia/Novosibirsk +Asia/Phnom_Penh Asia/Phnom_Penh +Asia/Pyongyang Asia/Pyongyang +Asia/Qatar Asia/Qatar +Asia/Rangoon Asia/Rangoon +Asia/Riyadh Asia/Riyadh +Asia/Saigon Asia/Ho_Chi_Minh +Asia/Seoul Asia/Seoul +Asia/Shanghai Asia/Shanghai +Asia/Singapore Asia/Singapore +Asia/Taipei Asia/Taipei +Asia/Tashkent Asia/Tashkent +Asia/Tbilisi Asia/Tbilisi +Asia/Tehran Asia/Tehran +Asia/Tel_Aviv Asia/Jerusalem +Asia/Thimbu Asia/Thimbu +Asia/Tokyo Asia/Tokyo +Asia/Ujung_Pandang Asia/Ujung_Pandang +Asia/Ulan_Bator Asia/Ulaanbaatar +Asia/Urumqi Asia/Shanghai +Asia/Vientiane Asia/Vientiane +Asia/Vladivostok Asia/Vladivostok +Asia/Yakutsk Asia/Yakutsk +Asia/Yekaterinburg Asia/Yekaterinburg +Asia/Yerevan Asia/Yerevan +Atlantic/Azores Atlantic/Azores +Atlantic/Bermuda Atlantic/Bermuda +Atlantic/Canary Atlantic/Canary +Atlantic/Cape_Verde Atlantic/Cape_Verde +Atlantic/Faeroe Atlantic/Faeroe +Atlantic/Jan_Mayen Atlantic/Jan_Mayen +Atlantic/Madeira Europe/London +Atlantic/Reykjavik Atlantic/Reykjavik +Atlantic/South_Georgia Atlantic/South_Georgia +Atlantic/St_Helena Atlantic/St_Helena +Atlantic/Stanley Atlantic/Stanley +Australia/ACT Australia/Sydney +Australia/Adelaide Australia/Adelaide +Australia/Brisbane Australia/Brisbane +Australia/Broken_Hill Australia/Broken_Hill +Australia/Canberra Australia/Sydney +Australia/Darwin Australia/Darwin +Australia/Hobart Australia/Hobart +Australia/LHI Australia/Lord_Howe +Australia/Lord_Howe Australia/Lord_Howe +Australia/Melbourne Australia/Sydney +Australia/NSW Australia/Sydney +Australia/North Australia/Darwin +Australia/Perth Australia/Perth +Australia/Queensland Australia/Brisbane +Australia/South Australia/Adelaide +Australia/Sydney Australia/Sydney +Australia/Tasmania Australia/Hobart +Australia/Victoria Australia/Melbourne +Australia/West Australia/Perth +Australia/Yancowinna Australia/Broken_Hill +BRT3BRST America/Sao_Paulo +BST11 Pacific/Apia +BST11BDT Pacific/Apia +Brazil/Acre America/Rio_Branco +Brazil/DeNoronha America/Noronha +Brazil/East America/Sao_Paulo +Brazil/West America/Manaus +CET Europe/Paris +CET-1CEST Europe/Paris +CET-1CEST-2 Europe/Berlin +CET-1CET-2 Europe/Paris +CST6 America/Costa_Rica +CST6CDT America/Chicago +CUT0 UTC +CUT0GDT Europe/London +Canada/Atlantic America/Halifax +Canada/Central America/Winnipeg +Canada/East-Saskatchewan America/Regina +Canada/Eastern America/Montreal +Canada/Mountain America/Edmonton +Canada/Newfoundland America/St_Johns +Canada/Pacific America/Vancouver +Canada/Saskatchewan America/Regina +Canada/Yukon America/Whitehorse +Chile/Continental America/Santiago +Chile/EasterIsland Pacific/Easter +Cuba America/Havana +EET Europe/Istanbul +EET-10 Australia/Brisbane +EET-10EETDT Australia/Sydney +EST America/Indianapolis +EST5 America/Indianapolis +EST5EDT America/New_York +Egypt Africa/Cairo +Eire Europe/Dublin +Etc/GMT GMT +Etc/GMT0 GMT +Etc/Greenwich GMT +Etc/UCT UTC +Etc/UTC UTC +Etc/Universal UTC +Etc/Zulu UTC +Europe/Amsterdam Europe/Amsterdam +Europe/Andorra Europe/Andorra +Europe/Athens Europe/Athens +Europe/Belfast Europe/London +Europe/Belgrade Europe/Belgrade +Europe/Berlin Europe/Berlin +Europe/Bratislava Europe/Prague +Europe/Brussels Europe/Brussels +Europe/Bucharest Europe/Bucharest +Europe/Budapest Europe/Budapest +Europe/Chisinau Europe/Chisinau +Europe/Copenhagen Europe/Copenhagen +Europe/Dublin Europe/Dublin +Europe/Gibraltar Europe/Gibraltar +Europe/Guernsey Europe/London +Europe/Helsinki Europe/Helsinki +Europe/Isle_of_Man Europe/London +Europe/Istanbul Europe/Istanbul +Europe/Jersey Europe/London +Europe/Kaliningrad Europe/Kaliningrad +Europe/Kiev Europe/Kiev +Europe/Lisbon Europe/Lisbon +Europe/Ljubljana Europe/Belgrade +Europe/London Europe/London +Europe/Luxembourg Europe/Luxembourg +Europe/Madrid Europe/Madrid +Europe/Malta Europe/Malta +Europe/Mariehamn Europe/Helsinki +Europe/Minsk Europe/Minsk +Europe/Monaco Europe/Monaco +Europe/Moscow Europe/Moscow +Europe/Nicosia Asia/Nicosia +Europe/Oslo Europe/Oslo +Europe/Paris Europe/Paris +Europe/Podgorica Europe/Belgrade +Europe/Prague Europe/Prague +Europe/Riga Europe/Riga +Europe/Rome Europe/Rome +Europe/Samara Europe/Samara +Europe/San_Marino Europe/Rome +Europe/Sarajevo Europe/Belgrade +Europe/Simferopol Europe/Simferopol +Europe/Skopje Europe/Belgrade +Europe/Sofia Europe/Sofia +Europe/Stockholm Europe/Stockholm +Europe/Tallinn Europe/Tallinn +Europe/Tirane Europe/Tirane +Europe/Vaduz Europe/Vaduz +Europe/Vatican Europe/Rome +Europe/Vienna Europe/Vienna +Europe/Vilnius Europe/Vilnius +Europe/Warsaw Europe/Warsaw +Europe/Zagreb Europe/Belgrade +Europe/Zurich Europe/Zurich +FALKST2 Atlantic/South_Georgia +FALKST2FALKDT Atlantic/South_Georgia +Factory GMT +GB Europe/London +GB-Eire Europe/London +GMT GMT +GMT0 GMT +GMT0BST Europe/London +GMT0BST-1 Europe/London +GMT0WET Europe/Lisbon +GRNLNDST3 America/Buenos_Aires +GRNLNDST3GRNLNDDT America/Godthab +Greenwich GMT +HST Pacific/Honolulu +HST10 Pacific/Honolulu +HST10HDT America/Adak +Hongkong Asia/Hong_Kong +Iceland Atlantic/Reykjavik +Indian/Antananarivo Indian/Antananarivo +Indian/Chagos Indian/Chagos +Indian/Christmas Indian/Christmas +Indian/Cocos Indian/Cocos +Indian/Comoro Indian/Comoro +Indian/Kerguelen Indian/Kerguelen +Indian/Mahe Indian/Mahe +Indian/Maldives Indian/Maldives +Indian/Mauritius Indian/Mauritius +Indian/Mayotte Indian/Mayotte +Indian/Reunion Indian/Reunion +Iran Asia/Tehran +Israel Asia/Jerusalem +JST-9 Asia/Tokyo +JST-9JSTDT Asia/Tokyo +Jamaica America/Jamaica +Japan Asia/Tokyo +KORST-9 Asia/Seoul +KORST-9KORDT Asia/Seoul +Kwajalein Pacific/Kwajalein +Libya Africa/Tripoli +MEST-2 Europe/Istanbul +MEST-2MEDT Europe/Istanbul +MEST-3 Asia/Riyadh +MEST-3MEDT Europe/Moscow +MET Europe/Paris +MET-11 Pacific/Guadalcanal +MET-11METDT Asia/Magadan +MET-1MEST Europe/Paris +MET-1MST-2 Europe/Berlin +MEZ-1MESZ Europe/Berlin +MEZ-1MESZ-2 Europe/Berlin +MSK-3MSD Europe/Moscow +MST America/Phoenix +MST7 America/Phoenix +MST7MDT America/Denver +Mexico/BajaNorte America/Tijuana +Mexico/BajaSur America/Mazatlan +Mexico/General America/Mexico_City +Mideast/Riyadh87 Asia/Riyadh87 +Mideast/Riyadh88 Asia/Riyadh88 +Mideast/Riyadh89 Asia/Riyadh89 +NFT-1 Africa/Algiers +NFT-1DFT Europe/Paris +NFT-1DST Europe/Paris +NZ Pacific/Auckland +NZ-CHAT Pacific/Chatham +NZST-12 Pacific/Fiji +NZST-12NZDT Pacific/Auckland +Navajo America/Denver +PAKST-5 Asia/Karachi +PAKST-5PAKDT Asia/Yekaterinburg +PRC Asia/Shanghai +PST8 Pacific/Pitcairn +PST8PDT America/Los_Angeles +PST8PDT7 America/Tijuana +Pacific/Apia Pacific/Apia +Pacific/Auckland Pacific/Auckland +Pacific/Chatham Pacific/Chatham +Pacific/Easter Pacific/Easter +Pacific/Efate Pacific/Efate +Pacific/Enderbury Pacific/Enderbury +Pacific/Fakaofo Pacific/Fakaofo +Pacific/Fiji Pacific/Fiji +Pacific/Funafuti Pacific/Funafuti +Pacific/Galapagos Pacific/Galapagos +Pacific/Gambier Pacific/Gambier +Pacific/Guadalcanal Pacific/Guadalcanal +Pacific/Guam Pacific/Guam +Pacific/Honolulu Pacific/Honolulu +Pacific/Kiritimati Pacific/Kiritimati +Pacific/Kosrae Pacific/Kosrae +Pacific/Majuro Pacific/Majuro +Pacific/Marquesas Pacific/Marquesas +Pacific/Nauru Pacific/Nauru +Pacific/Niue Pacific/Niue +Pacific/Norfolk Pacific/Norfolk +Pacific/Noumea Pacific/Noumea +Pacific/Pago_Pago Pacific/Pago_Pago +Pacific/Palau Pacific/Palau +Pacific/Pitcairn Pacific/Pitcairn +Pacific/Ponape Pacific/Ponape +Pacific/Port_Moresby Pacific/Port_Moresby +Pacific/Rarotonga Pacific/Rarotonga +Pacific/Saipan Pacific/Saipan +Pacific/Samoa Pacific/Pago_Pago +Pacific/Tahiti Pacific/Tahiti +Pacific/Tarawa Pacific/Tarawa +Pacific/Tongatapu Pacific/Tongatapu +Pacific/Truk Pacific/Truk +Pacific/Wake Pacific/Wake +Pacific/Wallis Pacific/Wallis +Poland Europe/Warsaw +Portugal Europe/Lisbon +ROC Asia/Taipei +ROK Asia/Seoul +SAUST-3 Asia/Riyadh +SAUST-3SAUDT Europe/Moscow +Singapore Asia/Singapore +SystemV/AST4ADT America/Thule +SystemV/CST6CDT America/Chicago +SystemV/EST5EDT America/New_York +SystemV/MST7MDT America/Denver +SystemV/PST8PDT America/Los_Angeles +SystemV/YST9YDT America/Anchorage +TAIST-8 Asia/Taipei +TAIST-8TAIDT Asia/Irkutsk +TASHST-6 Asia/Dacca +TASHST-6TASHDT Asia/Novosibirsk +THAIST-7 Asia/Bangkok +THAIST-7THAIDT Asia/Krasnoyarsk +Turkey Europe/Istanbul +UCT UTC +US/Alaska America/Anchorage +US/Aleutian America/Adak +US/Arizona America/Phoenix +US/Central America/Chicago +US/East-Indiana America/Indiana/Indianapolis +US/Eastern America/New_York +US/Hawaii Pacific/Honolulu +US/Indiana-Starke America/Indiana/Knox +US/Michigan America/New_York +US/Mountain America/Denver +US/Pacific America/Los_Angeles +US/Pacific-New America/Los_Angeles +US/Samoa Pacific/Pago_Pago +USAST-2 Africa/Johannesburg +USAST-2USADT Europe/Istanbul +UTC UTC +UYT3UYST America/Montevideo +Universal UTC +W-SU Europe/Moscow +WAUST-8 Australia/Perth +WAUST-8WAUDT Australia/Perth +WET WET +WET-2 Africa/Johannesburg +WET-2WET Europe/Helsinki +WST-4 Asia/Dubai +WST-4WDT Europe/Samara +Zulu UTC diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/classes/sun/font/CFontManager.java --- a/jdk/src/macosx/classes/sun/font/CFontManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/classes/sun/font/CFontManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - 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) () -> { + /* 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; + } + ); } } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/classes/sun/lwawt/LWToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - 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) 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(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java Wed Jul 05 19:37:43 2017 +0200 @@ -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. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Jul 05 19:37:43 2017 +0200 @@ -478,8 +478,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) () -> { + Thread.currentThread().setContextClassLoader(null); + return null; + }); } @Override diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/lib/content-types.properties --- a/jdk/src/macosx/lib/content-types.properties Thu Apr 17 15:23:23 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' '=' -# ::= 'file_extensions' '=' -# ::= 'icon' '=' -# ::= 'browser' | 'application' | 'save' | 'unknown' -# ::= 'application' '=' -# - -# -# 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 - - - diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/native/sun/awt/LWCToolkit.m --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Wed Jul 05 19:37:43 2017 +0200 @@ -221,15 +221,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"); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/native/sun/awt/awt.m --- a/jdk/src/macosx/native/sun/awt/awt.m Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/native/sun/awt/awt.m Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java --- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Jul 05 19:37:43 2017 +0200 @@ -1220,7 +1220,7 @@ throw new RuntimeOperationsException(new IllegalArgumentException(listener.getCanonicalName()), "The MBean " + listener.getCanonicalName() + - "does not implement the NotificationListener interface") ; + " does not implement the NotificationListener interface") ; } // ---------------- diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java --- a/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(PRINCIPALS_CACHE_SIZE); + new CacheMap<>(PRINCIPALS_CACHE_SIZE); accCache = - new CacheMap(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 permissions = new ArrayList<>(dp.length); + for(Principal p : dp) { + final String pname = p.getClass().getName() + "." + p.getName(); + permissions.add(new SubjectDelegationPermission(pname)); + } PrivilegedAction action = new PrivilegedAction() { 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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java --- a/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 reqs; + private Map reqs; // Responses received private Map resps; @@ -134,7 +137,8 @@ throw ne; } } - reqs = Collections.synchronizedSet(new HashSet()); + reqs = Collections.synchronizedMap( + new HashMap()); resps = Collections.synchronizedMap(new HashMap()); } @@ -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); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java Wed Jul 05 19:37:43 2017 +0200 @@ -188,7 +188,7 @@ if(syntaxAttr == null || syntaxAttr.size() == 0) { throw new NameNotFoundException( - getID() + "does not have a syntax associated with it"); + getID() + " does not have a syntax associated with it"); } String syntaxName = (String)syntaxAttr.get(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 { + 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() { + @Override + public Object run() throws NamingException { + return Obj.decodeObject(attrs); + } + }, acc); + } catch (PrivilegedActionException e) { + throw (NamingException)e.getException(); + } } if (obj == null) { // DirContext object diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java --- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { + @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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/media/sound/JDK13Services.java --- a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java Wed Jul 05 19:37:43 2017 +0200 @@ -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. + *

* 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; - } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java --- a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -185,8 +185,8 @@ return thread; } - static List getProviders(final Class providerClass) { - List p = new ArrayList<>(); + static synchronized List getProviders(final Class providerClass) { + List 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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java Wed Jul 05 19:37:43 2017 +0200 @@ -922,7 +922,7 @@ Element foundElement = null; String id = value.trim(); - if (id.charAt(0) == '#') { + if (!id.isEmpty() && id.charAt(0) == '#') { id = id.substring(1); } @@ -982,7 +982,7 @@ Node processedNode = null; String id = value.trim(); - if (id.charAt(0) == '#') { + if (!id.isEmpty() && id.charAt(0) == '#') { id = id.substring(1); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java --- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 CachedRowSet 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java --- a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/awt/EventQueue.java --- a/jdk/src/share/classes/java/awt/EventQueue.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/awt/EventQueue.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java --- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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() { - 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() { + 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/io/ObjectOutputStream.java --- a/jdk/src/share/classes/java/io/ObjectOutputStream.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java Wed Jul 05 19:37:43 2017 +0200 @@ -1254,7 +1254,7 @@ } bout.setBlockDataMode(true); - if (isCustomSubclass()) { + if (cl != null && isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateProxyClass(cl); @@ -1283,7 +1283,7 @@ Class cl = desc.forClass(); bout.setBlockDataMode(true); - if (isCustomSubclass()) { + if (cl != null && isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateClass(cl); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/lang/Thread.java --- a/jdk/src/share/classes/java/lang/Thread.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/lang/Thread.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java --- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Jul 05 19:37:43 2017 +0200 @@ -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, "", makeSignature(types, true), null, null); + mv = cw.visitMethod(NOT_ACC_PUBLIC, "", 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, "", VOID_SIG, null, null); + mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "", VOID_SIG, null, null); mv.visitCode(); mv.visitLdcInsn(types); mv.visitLdcInsn(Type.getObjectType(className)); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/lang/invoke/MethodHandles.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Wed Jul 05 19:37:43 2017 +0200 @@ -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> 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); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/math/BigDecimal.java --- a/jdk/src/share/classes/java/math/BigDecimal.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/math/BigDecimal.java Wed Jul 05 19:37:43 2017 +0200 @@ -29,8 +29,8 @@ package java.math; +import static java.math.BigInteger.LONG_MASK; import java.util.Arrays; -import static java.math.BigInteger.LONG_MASK; /** * Immutable, arbitrary-precision signed decimal numbers. A @@ -283,7 +283,7 @@ }; // Cache of common small BigDecimal values. - private static final BigDecimal zeroThroughTen[] = { + private static final BigDecimal ZERO_THROUGH_TEN[] = { new BigDecimal(BigInteger.ZERO, 0, 0, 1), new BigDecimal(BigInteger.ONE, 1, 0, 1), new BigDecimal(BigInteger.valueOf(2), 2, 0, 1), @@ -299,7 +299,7 @@ // Cache of zero scaled by 0 - 15 private static final BigDecimal[] ZERO_SCALED_BY = { - zeroThroughTen[0], + ZERO_THROUGH_TEN[0], new BigDecimal(BigInteger.ZERO, 0, 1, 1), new BigDecimal(BigInteger.ZERO, 0, 2, 1), new BigDecimal(BigInteger.ZERO, 0, 3, 1), @@ -328,7 +328,7 @@ * @since 1.5 */ public static final BigDecimal ZERO = - zeroThroughTen[0]; + ZERO_THROUGH_TEN[0]; /** * The value 1, with a scale of 0. @@ -336,7 +336,7 @@ * @since 1.5 */ public static final BigDecimal ONE = - zeroThroughTen[1]; + ZERO_THROUGH_TEN[1]; /** * The value 10, with a scale of 0. @@ -344,7 +344,7 @@ * @since 1.5 */ public static final BigDecimal TEN = - zeroThroughTen[10]; + ZERO_THROUGH_TEN[10]; // Constructors @@ -920,20 +920,20 @@ significand >>= 1; exponent++; } - int scale = 0; + int scl = 0; // Calculate intVal and scale - BigInteger intVal; + BigInteger rb; long compactVal = sign * significand; if (exponent == 0) { - intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null; + rb = (compactVal == INFLATED) ? INFLATED_BIGINT : null; } else { if (exponent < 0) { - intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal); - scale = -exponent; + rb = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal); + scl = -exponent; } else { // (exponent > 0) - intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal); + rb = BigInteger.valueOf(2).pow(exponent).multiply(compactVal); } - compactVal = compactValFor(intVal); + compactVal = compactValFor(rb); } int prec = 0; int mcp = mc.precision; @@ -941,16 +941,16 @@ int mode = mc.roundingMode.oldMode; int drop; if (compactVal == INFLATED) { - prec = bigDigitLength(intVal); + prec = bigDigitLength(rb); drop = prec - mcp; while (drop > 0) { - scale = checkScaleNonZero((long) scale - drop); - intVal = divideAndRoundByTenPow(intVal, drop, mode); - compactVal = compactValFor(intVal); + scl = checkScaleNonZero((long) scl - drop); + rb = divideAndRoundByTenPow(rb, drop, mode); + compactVal = compactValFor(rb); if (compactVal != INFLATED) { break; } - prec = bigDigitLength(intVal); + prec = bigDigitLength(rb); drop = prec - mcp; } } @@ -958,17 +958,17 @@ prec = longDigitLength(compactVal); drop = prec - mcp; while (drop > 0) { - scale = checkScaleNonZero((long) scale - drop); + scl = checkScaleNonZero((long) scl - drop); compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); prec = longDigitLength(compactVal); drop = prec - mcp; } - intVal = null; + rb = null; } } - this.intVal = intVal; + this.intVal = rb; this.intCompact = compactVal; - this.scale = scale; + this.scale = scl; this.precision = prec; } @@ -1098,13 +1098,13 @@ public BigDecimal(int val, MathContext mc) { int mcp = mc.precision; long compactVal = val; - int scale = 0; + int scl = 0; int prec = 0; if (mcp > 0) { // do rounding prec = longDigitLength(compactVal); int drop = prec - mcp; // drop can't be more than 18 while (drop > 0) { - scale = checkScaleNonZero((long) scale - drop); + scl = checkScaleNonZero((long) scl - drop); compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); prec = longDigitLength(compactVal); drop = prec - mcp; @@ -1112,7 +1112,7 @@ } this.intVal = null; this.intCompact = compactVal; - this.scale = scale; + this.scale = scl; this.precision = prec; } @@ -1144,20 +1144,20 @@ int mcp = mc.precision; int mode = mc.roundingMode.oldMode; int prec = 0; - int scale = 0; - BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null; + int scl = 0; + BigInteger rb = (val == INFLATED) ? INFLATED_BIGINT : null; if (mcp > 0) { // do rounding if (val == INFLATED) { prec = 19; int drop = prec - mcp; while (drop > 0) { - scale = checkScaleNonZero((long) scale - drop); - intVal = divideAndRoundByTenPow(intVal, drop, mode); - val = compactValFor(intVal); + scl = checkScaleNonZero((long) scl - drop); + rb = divideAndRoundByTenPow(rb, drop, mode); + val = compactValFor(rb); if (val != INFLATED) { break; } - prec = bigDigitLength(intVal); + prec = bigDigitLength(rb); drop = prec - mcp; } } @@ -1165,17 +1165,17 @@ prec = longDigitLength(val); int drop = prec - mcp; while (drop > 0) { - scale = checkScaleNonZero((long) scale - drop); + scl = checkScaleNonZero((long) scl - drop); val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); prec = longDigitLength(val); drop = prec - mcp; } - intVal = null; + rb = null; } } - this.intVal = intVal; + this.intVal = rb; this.intCompact = val; - this.scale = scale; + this.scale = scl; this.precision = prec; } @@ -1215,16 +1215,16 @@ * @return a {@code BigDecimal} whose value is {@code val}. */ public static BigDecimal valueOf(long val) { - if (val >= 0 && val < zeroThroughTen.length) - return zeroThroughTen[(int)val]; + if (val >= 0 && val < ZERO_THROUGH_TEN.length) + return ZERO_THROUGH_TEN[(int)val]; else if (val != INFLATED) return new BigDecimal(null, val, 0, 0); return new BigDecimal(INFLATED_BIGINT, val, 0, 0); } static BigDecimal valueOf(long unscaledVal, int scale, int prec) { - if (scale == 0 && unscaledVal >= 0 && unscaledVal < zeroThroughTen.length) { - return zeroThroughTen[(int) unscaledVal]; + if (scale == 0 && unscaledVal >= 0 && unscaledVal < ZERO_THROUGH_TEN.length) { + return ZERO_THROUGH_TEN[(int) unscaledVal]; } else if (unscaledVal == 0) { return zeroValueOf(scale); } @@ -1236,8 +1236,8 @@ long val = compactValFor(intVal); if (val == 0) { return zeroValueOf(scale); - } else if (scale == 0 && val >= 0 && val < zeroThroughTen.length) { - return zeroThroughTen[(int) val]; + } else if (scale == 0 && val >= 0 && val < ZERO_THROUGH_TEN.length) { + return ZERO_THROUGH_TEN[(int) val]; } return new BigDecimal(intVal, val, scale, prec); } @@ -2620,6 +2620,7 @@ * @return -1, 0, or 1 as this {@code BigDecimal} is numerically * less than, equal to, or greater than {@code val}. */ + @Override public int compareTo(BigDecimal val) { // Quick path for equal scale and non-inflated case. if (scale == val.scale) { @@ -2659,14 +2660,13 @@ return -1; if (xae > yae) return 1; - BigInteger rb = null; if (sdiff < 0) { // The cases sdiff <= Integer.MIN_VALUE intentionally fall through. if ( sdiff > Integer.MIN_VALUE && (xs == INFLATED || (xs = longMultiplyPowerTen(xs, (int)-sdiff)) == INFLATED) && ys == INFLATED) { - rb = bigMultiplyPowerTen((int)-sdiff); + BigInteger rb = bigMultiplyPowerTen((int)-sdiff); return rb.compareMagnitude(val.intVal); } } else { // sdiff > 0 @@ -2675,7 +2675,7 @@ (ys == INFLATED || (ys = longMultiplyPowerTen(ys, (int)sdiff)) == INFLATED) && xs == INFLATED) { - rb = val.bigMultiplyPowerTen((int)sdiff); + BigInteger rb = val.bigMultiplyPowerTen((int)sdiff); return this.intVal.compareMagnitude(rb); } } @@ -2880,8 +2880,9 @@ @Override public String toString() { String sc = stringCache; - if (sc == null) + if (sc == null) { stringCache = sc = layoutChars(true); + } return sc; } @@ -2958,18 +2959,19 @@ if(signum()==0) { return "0"; } - int tailingZeros = checkScaleNonZero((-(long)scale)); + int trailingZeros = checkScaleNonZero((-(long)scale)); StringBuilder buf; if(intCompact!=INFLATED) { - buf = new StringBuilder(20+tailingZeros); + buf = new StringBuilder(20+trailingZeros); buf.append(intCompact); } else { String str = intVal.toString(); - buf = new StringBuilder(str.length()+tailingZeros); + buf = new StringBuilder(str.length()+trailingZeros); buf.append(str); } - for (int i = 0; i < tailingZeros; i++) + for (int i = 0; i < trailingZeros; i++) { buf.append('0'); + } return buf.toString(); } String str ; @@ -2996,8 +2998,9 @@ } else { /* We must insert zeros between point and intVal */ buf = new StringBuilder(3-insertionPoint + intString.length()); buf.append(signum<0 ? "-0." : "0."); - for (int i=0; i<-insertionPoint; i++) + for (int i=0; i<-insertionPoint; i++) { buf.append('0'); + } buf.append(intString); } return buf.toString(); @@ -3056,6 +3059,7 @@ * * @return this {@code BigDecimal} converted to a {@code long}. */ + @Override public long longValue(){ return (intCompact != INFLATED && scale == 0) ? intCompact: @@ -3124,6 +3128,7 @@ * * @return this {@code BigDecimal} converted to an {@code int}. */ + @Override public int intValue() { return (intCompact != INFLATED && scale == 0) ? (int)intCompact : @@ -3206,6 +3211,7 @@ * * @return this {@code BigDecimal} converted to a {@code float}. */ + @Override public float floatValue(){ if(intCompact != INFLATED) { if (scale == 0) { @@ -3221,10 +3227,10 @@ // Don't have too guard against // Math.abs(MIN_VALUE) because of outer check // against INFLATED. - if (scale > 0 && scale < float10pow.length) { - return (float)intCompact / float10pow[scale]; - } else if (scale < 0 && scale > -float10pow.length) { - return (float)intCompact * float10pow[-scale]; + if (scale > 0 && scale < FLOAT_10_POW.length) { + return (float)intCompact / FLOAT_10_POW[scale]; + } else if (scale < 0 && scale > -FLOAT_10_POW.length) { + return (float)intCompact * FLOAT_10_POW[-scale]; } } } @@ -3249,6 +3255,7 @@ * * @return this {@code BigDecimal} converted to a {@code double}. */ + @Override public double doubleValue(){ if(intCompact != INFLATED) { if (scale == 0) { @@ -3264,10 +3271,10 @@ // Don't have too guard against // Math.abs(MIN_VALUE) because of outer check // against INFLATED. - if (scale > 0 && scale < double10pow.length) { - return (double)intCompact / double10pow[scale]; - } else if (scale < 0 && scale > -double10pow.length) { - return (double)intCompact * double10pow[-scale]; + if (scale > 0 && scale < DOUBLE_10_POW.length) { + return (double)intCompact / DOUBLE_10_POW[scale]; + } else if (scale < 0 && scale > -DOUBLE_10_POW.length) { + return (double)intCompact * DOUBLE_10_POW[-scale]; } } } @@ -3280,7 +3287,7 @@ * Powers of 10 which can be represented exactly in {@code * double}. */ - private static final double double10pow[] = { + private static final double DOUBLE_10_POW[] = { 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, @@ -3291,7 +3298,7 @@ * Powers of 10 which can be represented exactly in {@code * float}. */ - private static final float float10pow[] = { + private static final float FLOAT_10_POW[] = { 1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f }; @@ -3504,8 +3511,9 @@ } else if (sig >= coeffLen) { // significand all in integer buf.append(coeff, offset, coeffLen); // may need some zeros, too - for (int i = sig - coeffLen; i > 0; i--) + for (int i = sig - coeffLen; i > 0; i--) { buf.append('0'); + } } else { // xx.xxE form buf.append(coeff, offset, sig); buf.append('.'); @@ -3559,11 +3567,13 @@ // to prevent multiple threads from expanding the same array. if (curLen <= n) { int newLen = curLen << 1; - while (newLen <= n) + while (newLen <= n) { newLen <<= 1; + } pows = Arrays.copyOf(pows, newLen); - for (int i = curLen; i < newLen; i++) + for (int i = curLen; i < newLen; i++) { pows[i] = pows[i - 1].multiply(BigInteger.TEN); + } // Based on the following facts: // 1. pows is a private local varible; // 2. the following store is a volatile store. @@ -3703,9 +3713,7 @@ * {@code BigDecimal}s to be aligned. */ private static void matchScale(BigDecimal[] val) { - if (val[0].scale == val[1].scale) { - return; - } else if (val[0].scale < val[1].scale) { + if (val[0].scale < val[1].scale) { val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY); } else if (val[1].scale < val[0].scale) { val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY); @@ -4209,16 +4217,16 @@ * do rounding based on the passed in roundingMode. */ private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) { - boolean isRemainderZero; // record remainder is zero or not - int qsign; // quotient sign - long r = 0; // store quotient & remainder in long - MutableBigInteger mq = null; // store quotient // Descend into mutables for faster remainder checks MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); - mq = new MutableBigInteger(); - r = mdividend.divide(ldivisor, mq); - isRemainderZero = (r == 0); - qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; + // store quotient + MutableBigInteger mq = new MutableBigInteger(); + // store quotient & remainder in long + long r = mdividend.divide(ldivisor, mq); + // record remainder is zero or not + boolean isRemainderZero = (r == 0); + // quotient sign + int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; if (!isRemainderZero) { if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) { mq.add(MutableBigInteger.ONE); @@ -4238,16 +4246,16 @@ */ private static BigDecimal divideAndRound(BigInteger bdividend, long ldivisor, int scale, int roundingMode, int preferredScale) { - boolean isRemainderZero; // record remainder is zero or not - int qsign; // quotient sign - long r = 0; // store quotient & remainder in long - MutableBigInteger mq = null; // store quotient // Descend into mutables for faster remainder checks MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); - mq = new MutableBigInteger(); - r = mdividend.divide(ldivisor, mq); - isRemainderZero = (r == 0); - qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; + // store quotient + MutableBigInteger mq = new MutableBigInteger(); + // store quotient & remainder in long + long r = mdividend.divide(ldivisor, mq); + // record remainder is zero or not + boolean isRemainderZero = (r == 0); + // quotient sign + int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; if (!isRemainderZero) { if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) { mq.add(MutableBigInteger.ONE); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/DatagramSocket.java --- a/jdk/src/share/classes/java/net/DatagramSocket.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/DatagramSocket.java Wed Jul 05 19:37:43 2017 +0200 @@ -29,6 +29,8 @@ import java.nio.channels.DatagramChannel; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import java.util.Set; +import java.util.Collections; /** * This class represents a socket for sending and receiving datagram packets. @@ -315,6 +317,7 @@ } // creates a udp socket impl.create(); + impl.setDatagramSocket(this); created = true; } @@ -445,7 +448,7 @@ * *

If given an {@link InetSocketAddress InetSocketAddress}, this method * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)} - * with the the given socket addresses IP address and port number. + * with the given socket addresses IP address and port number. * * @param addr The remote address. * @@ -1258,4 +1261,94 @@ } factory = fac; } + + /** + * Sets the value of a socket option. + * + * @param name The socket option + * @param value The value of the socket option. A value of {@code null} + * may be valid for some options. + * + * @return this DatagramSocket + * + * @throws UnsupportedOperationException if the datagram socket + * does not support the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @throws NullPointerException if name is {@code null} + * + * @since 1.9 + */ + public DatagramSocket setOption(SocketOption name, T value) + throws IOException + { + getImpl().setOption(name, value); + return this; + } + + /** + * Returns the value of a socket option. + * + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the datagram socket + * does not support the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws NullPointerException if name is {@code null} + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @since 1.9 + */ + public T getOption(SocketOption name) throws IOException { + return getImpl().getOption(name); + } + + private static Set> options; + private static boolean optionsSet = false; + + /** + * Returns a set of the socket options supported by this socket. + * + * This method will continue to return the set of options even after + * the socket has been closed. + * + * @return A set of the socket options supported by this socket. This set + * may be empty if the socket's DatagramSocketImpl cannot be created. + * + * @since 1.9 + */ + public Set> supportedOptions() { + synchronized(DatagramSocket.class) { + if (optionsSet) { + return options; + } + try { + DatagramSocketImpl impl = getImpl(); + options = Collections.unmodifiableSet(impl.supportedOptions()); + } catch (IOException e) { + options = Collections.emptySet(); + } + optionsSet = true; + return options; + } + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/DatagramSocketImpl.java --- a/jdk/src/share/classes/java/net/DatagramSocketImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/DatagramSocketImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -28,6 +28,8 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.InterruptedIOException; +import java.util.Set; +import java.util.HashSet; /** * Abstract datagram and multicast socket implementation base class. @@ -48,6 +50,20 @@ protected FileDescriptor fd; /** + * The DatagramSocket or MulticastSocket + * that owns this impl + */ + DatagramSocket socket; + + void setDatagramSocket(DatagramSocket socket) { + this.socket = socket; + } + + DatagramSocket getDatagramSocket() { + return socket; + } + + /** * Creates a datagram socket. * @exception SocketException if there is an error in the * underlying protocol, such as a TCP error. @@ -241,4 +257,116 @@ protected FileDescriptor getFileDescriptor() { return fd; } + + /** + * Called to set a socket option. + * + * @param name The socket option + * + * @param value The value of the socket option. A value of {@code null} + * may be valid for some options. + * + * @throws UnsupportedOperationException if the DatagramSocketImpl does not + * support the option + * + * @throws NullPointerException if name is {@code null} + * + * @since 1.9 + */ + protected void setOption(SocketOption name, T value) throws IOException { + if (name == StandardSocketOptions.SO_SNDBUF) { + setOption(SocketOptions.SO_SNDBUF, value); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + setOption(SocketOptions.SO_RCVBUF, value); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.IP_TOS) { + setOption(SocketOptions.IP_TOS, value); + } else if (name == StandardSocketOptions.IP_MULTICAST_IF && + (getDatagramSocket() instanceof MulticastSocket)) { + setOption(SocketOptions.IP_MULTICAST_IF2, value); + } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && + (getDatagramSocket() instanceof MulticastSocket)) { + if (! (value instanceof Integer)) { + throw new IllegalArgumentException("not an integer"); + } + setTimeToLive((Integer)value); + } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && + (getDatagramSocket() instanceof MulticastSocket)) { + setOption(SocketOptions.IP_MULTICAST_LOOP, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + /** + * Called to get a socket option. + * + * @param name The socket option + * + * @throws UnsupportedOperationException if the DatagramSocketImpl does not + * support the option + * + * @throws NullPointerException if name is {@code null} + * + * @since 1.9 + */ + protected T getOption(SocketOption name) throws IOException { + if (name == StandardSocketOptions.SO_SNDBUF) { + return (T) getOption(SocketOptions.SO_SNDBUF); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + return (T) getOption(SocketOptions.SO_RCVBUF); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + return (T) getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.IP_TOS) { + return (T) getOption(SocketOptions.IP_TOS); + } else if (name == StandardSocketOptions.IP_MULTICAST_IF && + (getDatagramSocket() instanceof MulticastSocket)) { + return (T) getOption(SocketOptions.IP_MULTICAST_IF2); + } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && + (getDatagramSocket() instanceof MulticastSocket)) { + Integer ttl = getTimeToLive(); + return (T)ttl; + } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && + (getDatagramSocket() instanceof MulticastSocket)) { + return (T) getOption(SocketOptions.IP_MULTICAST_LOOP); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + private static final Set> dgSocketOptions = + new HashSet<>(); + + private static final Set> mcSocketOptions = + new HashSet<>(); + + static { + dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF); + dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF); + dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); + dgSocketOptions.add(StandardSocketOptions.IP_TOS); + + mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF); + mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF); + mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); + mcSocketOptions.add(StandardSocketOptions.IP_TOS); + mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); + mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); + mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); + }; + + /** + * Returns a set of SocketOptions supported by this impl + * and by this impl's socket (DatagramSocket or MulticastSocket) + * + * @return a Set of SocketOptions + */ + protected Set> supportedOptions() { + if (getDatagramSocket() instanceof MulticastSocket) { + return mcSocketOptions; + } else { + return dgSocketOptions; + } + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/HttpCookie.java --- a/jdk/src/share/classes/java/net/HttpCookie.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/HttpCookie.java Wed Jul 05 19:37:43 2017 +0200 @@ -74,7 +74,7 @@ private boolean httpOnly; // HttpOnly ... i.e. not accessible to scripts private int version = 1; // Version=1 ... RFC 2965 style - // The original header this cookie was consructed from, if it was + // The original header this cookie was constructed from, if it was // constructed by parsing a header, otherwise null. private final String header; @@ -985,7 +985,7 @@ } /* - * Returns the original header this cookie was consructed from, if it was + * Returns the original header this cookie was constructed from, if it was * constructed by parsing a header, otherwise null. */ private String header() { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/InetAddress.java --- a/jdk/src/share/classes/java/net/InetAddress.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/InetAddress.java Wed Jul 05 19:37:43 2017 +0200 @@ -159,7 +159,7 @@ *

*
networkaddress.cache.ttl
*
Indicates the caching policy for successful name lookups from - * the name service. The value is specified as as integer to indicate + * the name service. The value is specified as an integer to indicate * the number of seconds to cache the successful lookup. The default * setting is to cache for an implementation specific period of time. *

@@ -167,7 +167,7 @@ *

*
networkaddress.cache.negative.ttl (default: 10)
*
Indicates the caching policy for un-successful name lookups - * from the name service. The value is specified as as integer to + * from the name service. The value is specified as an integer to * indicate the number of seconds to cache the failure for * un-successful lookups. *

diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/ServerSocket.java --- a/jdk/src/share/classes/java/net/ServerSocket.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/ServerSocket.java Wed Jul 05 19:37:43 2017 +0200 @@ -30,6 +30,8 @@ import java.nio.channels.ServerSocketChannel; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import java.util.Set; +import java.util.Collections; /** * This class implements server sockets. A server socket waits for @@ -919,4 +921,92 @@ /* Not implemented yet */ } + /** + * Sets the value of a socket option. + * + * @param name The socket option + * @param value The value of the socket option. A value of {@code null} + * may be valid for some options. + * @return this ServerSocket + * + * @throws UnsupportedOperationException if the server socket does not + * support the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws NullPointerException if name is {@code null} + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @since 1.9 + */ + public ServerSocket setOption(SocketOption name, T value) + throws IOException + { + getImpl().setOption(name, value); + return this; + } + + /** + * Returns the value of a socket option. + * + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the server socket does not + * support the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws NullPointerException if name is {@code null} + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @since 1.9 + */ + public T getOption(SocketOption name) throws IOException { + return getImpl().getOption(name); + } + + private static Set> options; + private static boolean optionsSet = false; + + /** + * Returns a set of the socket options supported by this server socket. + * + * This method will continue to return the set of options even after + * the socket has been closed. + * + * @return A set of the socket options supported by this socket. This set + * may be empty if the socket's SocketImpl cannot be created. + * + * @since 1.9 + */ + public Set> supportedOptions() { + synchronized (ServerSocket.class) { + if (optionsSet) { + return options; + } + try { + SocketImpl impl = getImpl(); + options = Collections.unmodifiableSet(impl.supportedOptions()); + } catch (IOException e) { + options = Collections.emptySet(); + } + optionsSet = true; + return options; + } + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/Socket.java --- a/jdk/src/share/classes/java/net/Socket.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/Socket.java Wed Jul 05 19:37:43 2017 +0200 @@ -32,6 +32,8 @@ import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedAction; +import java.util.Set; +import java.util.Collections; /** * This class implements client sockets (also called just @@ -1720,4 +1722,93 @@ { /* Not implemented yet */ } + + + /** + * Sets the value of a socket option. + * + * @param name The socket option + * @param value The value of the socket option. A value of {@code null} + * may be valid for some options. + * @return this Socket + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws NullPointerException if name is {@code null} + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @since 1.9 + */ + public Socket setOption(SocketOption name, T value) throws IOException { + getImpl().setOption(name, value); + return this; + } + + /** + * Returns the value of a socket option. + * + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @throws NullPointerException if name is {@code null} + * + * @throws SecurityException if a security manager is set and if the socket + * option requires a security permission and if the caller does + * not have the required permission. + * {@link java.net.StandardSocketOptions StandardSocketOptions} + * do not require any security permission. + * + * @since 1.9 + */ + @SuppressWarnings("unchecked") + public T getOption(SocketOption name) throws IOException { + return getImpl().getOption(name); + } + + private static Set> options; + private static boolean optionsSet = false; + + /** + * Returns a set of the socket options supported by this socket. + * + * This method will continue to return the set of options even after + * the socket has been closed. + * + * @return A set of the socket options supported by this socket. This set + * may be empty if the socket's SocketImpl cannot be created. + * + * @since 1.9 + */ + public Set> supportedOptions() { + synchronized (Socket.class) { + if (optionsSet) { + return options; + } + try { + SocketImpl impl = getImpl(); + options = Collections.unmodifiableSet(impl.supportedOptions()); + } catch (IOException e) { + options = Collections.emptySet(); + } + optionsSet = true; + return options; + } + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/net/SocketImpl.java --- a/jdk/src/share/classes/java/net/SocketImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/net/SocketImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -29,6 +29,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.FileDescriptor; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; /** * The abstract class {@code SocketImpl} is a common superclass @@ -355,4 +358,106 @@ { /* Not implemented yet */ } + + /** + * Called to set a socket option. + * + * @param name The socket option + * + * @param value The value of the socket option. A value of {@code null} + * may be valid for some options. + * + * @throws UnsupportedOperationException if the SocketImpl does not + * support the option + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @since 1.9 + */ + protected void setOption(SocketOption name, T value) throws IOException { + if (name == StandardSocketOptions.SO_KEEPALIVE) { + setOption(SocketOptions.SO_KEEPALIVE, value); + } else if (name == StandardSocketOptions.SO_SNDBUF) { + setOption(SocketOptions.SO_SNDBUF, value); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + setOption(SocketOptions.SO_RCVBUF, value); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_LINGER) { + setOption(SocketOptions.SO_LINGER, value); + } else if (name == StandardSocketOptions.IP_TOS) { + setOption(SocketOptions.IP_TOS, value); + } else if (name == StandardSocketOptions.TCP_NODELAY) { + setOption(SocketOptions.TCP_NODELAY, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + /** + * Called to get a socket option. + * + * @param name The socket option + * + * @return the value of the named option + * + * @throws UnsupportedOperationException if the SocketImpl does not + * support the option. + * + * @throws IOException if an I/O error occurs, or if the socket is closed. + * + * @since 1.9 + */ + protected T getOption(SocketOption name) throws IOException { + if (name == StandardSocketOptions.SO_KEEPALIVE) { + return (T)getOption(SocketOptions.SO_KEEPALIVE); + } else if (name == StandardSocketOptions.SO_SNDBUF) { + return (T)getOption(SocketOptions.SO_SNDBUF); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + return (T)getOption(SocketOptions.SO_RCVBUF); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + return (T)getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_LINGER) { + return (T)getOption(SocketOptions.SO_LINGER); + } else if (name == StandardSocketOptions.IP_TOS) { + return (T)getOption(SocketOptions.IP_TOS); + } else if (name == StandardSocketOptions.TCP_NODELAY) { + return (T)getOption(SocketOptions.TCP_NODELAY); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + private static final Set> socketOptions = + new HashSet<>(); + + private static final Set> serverSocketOptions = + new HashSet<>(); + + static { + socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); + socketOptions.add(StandardSocketOptions.SO_SNDBUF); + socketOptions.add(StandardSocketOptions.SO_RCVBUF); + socketOptions.add(StandardSocketOptions.SO_REUSEADDR); + socketOptions.add(StandardSocketOptions.SO_LINGER); + socketOptions.add(StandardSocketOptions.IP_TOS); + socketOptions.add(StandardSocketOptions.TCP_NODELAY); + + serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF); + serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); + }; + + /** + * Returns a set of SocketOptions supported by this impl + * and by this impl's socket (Socket or ServerSocket) + * + * @return a Set of SocketOptions + */ + protected Set> supportedOptions() { + if (getSocket() != null) { + return socketOptions; + } else { + return serverSocketOptions; + } + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/nio/file/Files.java --- a/jdk/src/share/classes/java/nio/file/Files.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/nio/file/Files.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 (optional operation). @@ -1535,7 +1534,7 @@ private static class FileTypeDetectors{ static final FileTypeDetector defaultFileTypeDetector = createDefaultFileTypeDetector(); - static final List installeDetectors = + static final List 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 @@ * * * {@code "posix:permissions,owner,size"} - * Reads the POSX file permissions, owner, and file size. + * Reads the POSIX file permissions, owner, and file size. * * * @@ -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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java --- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java Wed Jul 05 19:37:43 2017 +0200 @@ -81,7 +81,7 @@ // installed providers private static volatile List 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() { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/security/Provider.java --- a/jdk/src/share/classes/java/security/Provider.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/security/Provider.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/Locale.java --- a/jdk/src/share/classes/java/util/Locale.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/Locale.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ -3040,6 +3040,7 @@ * 2616 * @param map a map containing information to customize language ranges * @return a Language Priority List with customization. The list is + * modifiable. * @throws NullPointerException if {@code ranges} is null * @throws IllegalArgumentException if a language range or a weight * found in the given {@code ranges} is ill-formed diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/Random.java --- a/jdk/src/share/classes/java/util/Random.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/Random.java Wed Jul 05 19:37:43 2017 +0200 @@ -874,7 +874,7 @@ * (inclusive) and one (exclusive). * *

A pseudorandom {@code double} value is generated as if it's the result - * of calling the method {@link #nextDouble()}}. + * of calling the method {@link #nextDouble()}. * * @param streamSize the number of values to generate * @return a stream of {@code double} values @@ -897,7 +897,7 @@ * (exclusive). * *

A pseudorandom {@code double} value is generated as if it's the result - * of calling the method {@link #nextDouble()}}. + * of calling the method {@link #nextDouble()}. * * @implNote This method is implemented to be equivalent to {@code * doubles(Long.MAX_VALUE)}. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/ServiceLoader.java --- a/jdk/src/share/classes/java/util/ServiceLoader.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/ServiceLoader.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/jar/JarVerifier.java --- a/jdk/src/share/classes/java/util/jar/JarVerifier.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 unsignedEntryNames(JarFile jar) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/logging/LogManager.java --- a/jdk/src/share/classes/java/util/logging/LogManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/logging/LogManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { @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(); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/logging/Logger.java --- a/jdk/src/share/classes/java/util/logging/Logger.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Jul 05 19:37:43 2017 +0200 @@ -277,6 +277,7 @@ private volatile Level levelObject; private volatile int levelValue; // current effective level value private WeakReference 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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/java/util/logging/Logging.java --- a/jdk/src/share/classes/java/util/logging/Logging.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/java/util/logging/Logging.java Wed Jul 05 19:37:43 2017 +0200 @@ -87,7 +87,7 @@ Logger logger = logManager.getLogger(loggerName); if (logger == null) { throw new IllegalArgumentException("Logger " + loggerName + - "does not exist"); + " does not exist"); } Level level = null; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/naming/NameImpl.java --- a/jdk/src/share/classes/javax/naming/NameImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/naming/NameImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -232,7 +232,7 @@ syntaxDirection = FLAT; } else { throw new IllegalArgumentException(syntaxDirectionStr + - "is not a valid value for the jndi.syntax.direction property"); + " is not a valid value for the jndi.syntax.direction property"); } if (syntaxDirection != FLAT) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/script/ScriptEngineManager.java --- a/jdk/src/share/classes/javax/script/ScriptEngineManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/script/ScriptEngineManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -81,23 +81,28 @@ nameAssociations = new HashMap(); extensionAssociations = new HashMap(); mimeTypeAssociations = new HashMap(); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - initEngines(loader); - return null; - } - }); + initEngines(loader); + } + + private ServiceLoader 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 itr = null; try { - ServiceLoader sl; - if (loader != null) { - sl = ServiceLoader.load(ScriptEngineFactory.class, loader); - } else { - sl = ServiceLoader.loadInstalled(ScriptEngineFactory.class); - } + ServiceLoader sl = AccessController.doPrivileged( + new PrivilegedAction>() { + @Override + public ServiceLoader run() { + return getServiceLoader(loader); + } + }); + itr = sl.iterator(); } catch (ServiceConfigurationError err) { System.err.println("Can't find ScriptEngineFactory providers: " + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/security/auth/Subject.java --- a/jdk/src/share/classes/javax/security/auth/Subject.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/security/auth/Subject.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 inputPrincs = (Set)gf.get("principals", null); // Rewrap the principals into a SecureSet - principals = Collections.synchronizedSet(new SecureSet - (this, PRINCIPAL_SET, principals)); + if (inputPrincs == null) { + throw new NullPointerException + (ResourcesMgr.getString("invalid.null.input.s.")); + } + try { + principals = Collections.synchronizedSet(new SecureSet + (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(this, PRINCIPAL_SET)); + } // The Credential {@code Set} is not serialized, but we do not // want the default deserialization routine to set it to null. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java --- a/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java --- a/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java --- a/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 SyncProvider @@ -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) () -> { + 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java Wed Jul 05 19:37:43 2017 +0200 @@ -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. 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.net; + +import java.net.SocketOption; + +/** + * Defines extended socket options, beyond those defined in + * {@link java.net.StandardSocketOptions}. These options may be platform + * specific. + * + * @since 1.9 + */ +@jdk.Exported +public final class ExtendedSocketOptions { + + private static class ExtSocketOption implements SocketOption { + private final String name; + private final Class type; + ExtSocketOption(String name, Class type) { + this.name = name; + this.type = type; + } + @Override public String name() { return name; } + @Override public Class type() { return type; } + @Override public String toString() { return name; } + } + + private ExtendedSocketOptions() {} + + /** + * Service level properties. When a security manager is installed, + * setting or getting this option requires a {@link NetworkPermission} + * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} + * respectively. + */ + public static final SocketOption SO_FLOW_SLA = new + ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/net/NetworkPermission.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/net/NetworkPermission.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,93 @@ +/* + * 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 jdk.net; + +import java.security.BasicPermission; + +/** + * Represents permission to access the extended networking capabilities + * defined in the jdk.net package. These permissions contain a target + * name, but no actions list. Callers either possess the permission or not. + *

+ * The following targets are defined: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
setOption.SO_FLOW_SLAset the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option + * on any socket that supports itallows caller to set a higher priority or bandwidth allocation + * to sockets it creates, than they might otherwise be allowed.
getOption.SO_FLOW_SLAretrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} + * setting from any socket that supports the optionallows caller access to SLA information that it might not + * otherwise have
+ * + * @see jdk.net.ExtendedSocketOptions + * + * @since 1.9 + */ + +@jdk.Exported +public final class NetworkPermission extends BasicPermission { + + private static final long serialVersionUID = -2012939586906722291L; + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name) + { + super(name); + } + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @param actions should be {@code null}. Is ignored if not. + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name, String actions) + { + super(name, actions); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/net/SocketFlow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/net/SocketFlow.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,169 @@ +/* + * 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 jdk.net; + +import java.lang.annotation.Native; + +/** + * Represents the service level properties for the platform specific socket + * option {@link ExtendedSocketOptions#SO_FLOW_SLA}. + *

+ * The priority and bandwidth parameters must be set before + * setting the socket option. + *

+ * When the {@code SO_FLOW_SLA} option is set then it may not take effect + * immediately. If the value of the socket option is obtained with + * {@code getOption()} then the status may be returned as {@code INPROGRESS} + * until it takes effect. The priority and bandwidth values are only valid when + * the status is returned as OK. + *

+ * When a security manager is installed, a {@link NetworkPermission} + * is required to set or get this option. + * + * @since 1.9 + */ +@jdk.Exported +public class SocketFlow { + + private static final int UNSET = -1; + @Native public static final int NORMAL_PRIORITY = 1; + @Native public static final int HIGH_PRIORITY = 2; + + private int priority = NORMAL_PRIORITY; + + private long bandwidth = UNSET; + + private Status status = Status.NO_STATUS; + + private SocketFlow() {} + + /** + * Enumeration of the return values from the SO_FLOW_SLA + * socket option. Both setting and getting the option return + * one of these statuses, which reflect the state of socket's + * flow. + * + * @since 1.9 + */ + @jdk.Exported + public enum Status { + /** + * Set or get socket option has not been called yet. Status + * values can only be retrieved after calling set or get. + */ + NO_STATUS, + /** + * Flow successfully created. + */ + OK, + /** + * Caller has no permission to create flow. + */ + NO_PERMISSION, + /** + * Flow can not be created because socket is not connected. + */ + NOT_CONNECTED, + /** + * Flow creation not supported for this socket. + */ + NOT_SUPPORTED, + /** + * A flow already exists with identical attributes. + */ + ALREADY_CREATED, + /** + * A flow is being created. + */ + IN_PROGRESS, + /** + * Some other unspecified error. + */ + OTHER + } + + /** + * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA + * socket option and create a socket flow. + */ + public static SocketFlow create() { + return new SocketFlow(); + } + + /** + * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY + * HIGH_PRIORITY. If not set, a flow's priority is normal. + * + * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or + * HIGH_PRIORITY. + */ + public SocketFlow priority(int priority) { + if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) { + throw new IllegalArgumentException("invalid priority"); + } + this.priority = priority; + return this; + } + + /** + * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero. + * A value of zero drops all packets for the socket. + * + * @throws IllegalArgumentException if bandwidth is less than zero. + */ + public SocketFlow bandwidth(long bandwidth) { + if (bandwidth < 0) { + throw new IllegalArgumentException("invalid bandwidth"); + } else { + this.bandwidth = bandwidth; + } + return this; + } + + /** + * Returns this SocketFlow's priority. + */ + public int priority() { + return priority; + } + + /** + * Returns this SocketFlow's bandwidth. + * + * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK. + */ + public long bandwidth() { + return bandwidth; + } + + /** + * Returns the Status value of this SocketFlow. NO_STATUS is returned + * if the object was not used in a call to set or get the option. + */ + public Status status() { + return status; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/net/Sockets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/net/Sockets.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,311 @@ +/* + * 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 jdk.net; + +import java.net.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.lang.reflect.Field; +import java.util.Set; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Collections; +import sun.net.ExtendedOptionsImpl; + +/** + * Defines static methods to set and get socket options defined by the + * {@link java.net.SocketOption} interface. All of the standard options defined + * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and + * {@link java.net.DatagramSocket} can be set this way, as well as additional + * or platform specific options supported by each socket type. + *

+ * The {@link #supportedOptions(Class)} method can be called to determine + * the complete set of options available (per socket type) on the + * current system. + *

+ * When a security manager is installed, some non-standard socket options + * may require a security permission before being set or get. + * The details are specified in {@link ExtendedSocketOptions}. No permission + * is required for {@link java.net.StandardSocketOption}s. + * + * @see java.nio.channels.NetworkChannel + */ +@jdk.Exported +public class Sockets { + + private final static HashMap,Set>> + options = new HashMap<>(); + + static { + initOptionSets(); + } + + private Sockets() {} + + /** + * Sets the value of a socket option on a {@link java.net.Socket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. May be null for some + * options. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs, or socket is closed. + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @throws NullPointerException if name is null + * + * @see java.net.StandardSocketOptions + */ + public static void setOption(Socket s, SocketOption name, T value) throws IOException + { + s.setOption(name, value); + } + + /** + * Returns the value of a socket option from a {@link java.net.Socket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @throws NullPointerException if name is null + * + * @see java.net.StandardSocketOptions + */ + public static T getOption(Socket s, SocketOption name) throws IOException + { + return s.getOption(name); + } + + /** + * Sets the value of a socket option on a {@link java.net.ServerSocket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static void setOption(ServerSocket s, SocketOption name, T value) throws IOException + { + s.setOption(name, value); + } + + /** + * Returns the value of a socket option from a {@link java.net.ServerSocket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static T getOption(ServerSocket s, SocketOption name) throws IOException + { + return s.getOption(name); + } + + /** + * Sets the value of a socket option on a {@link java.net.DatagramSocket} + * or {@link java.net.MulticastSocket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static void setOption(DatagramSocket s, SocketOption name, T value) throws IOException + { + s.setOption(name, value); + } + + /** + * Returns the value of a socket option from a + * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static T getOption(DatagramSocket s, SocketOption name) throws IOException + { + return s.getOption(name); + } + + /** + * Returns a set of {@link java.net.SocketOption}s supported by the + * given socket type. This set may include standard options and also + * non standard extended options. + * + * @param socketType the type of java.net socket + * + * @throws IllegalArgumentException if socketType is not a valid + * socket type from the java.net package. + */ + public static Set> supportedOptions(Class socketType) { + Set> set = options.get(socketType); + if (set == null) { + throw new IllegalArgumentException("unknown socket type"); + } + return set; + } + + private static void checkValueType(Object value, Class type) { + if (!type.isAssignableFrom(value.getClass())) { + String s = "Found: " + value.getClass().toString() + " Expected: " + + type.toString(); + throw new IllegalArgumentException(s); + } + } + + private static void initOptionSets() { + boolean flowsupported = ExtendedOptionsImpl.flowSupported(); + + // Socket + + Set> set = new HashSet<>(); + set.add(StandardSocketOptions.SO_KEEPALIVE); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.SO_LINGER); + set.add(StandardSocketOptions.IP_TOS); + set.add(StandardSocketOptions.TCP_NODELAY); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(Socket.class, set); + + // ServerSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set = Collections.unmodifiableSet(set); + options.put(ServerSocket.class, set); + + // DatagramSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.IP_TOS); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(DatagramSocket.class, set); + + // MulticastSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.IP_TOS); + set.add(StandardSocketOptions.IP_MULTICAST_IF); + set.add(StandardSocketOptions.IP_MULTICAST_TTL); + set.add(StandardSocketOptions.IP_MULTICAST_LOOP); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(MulticastSocket.class, set); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/net/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/net/package-info.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/** + * Platform specific socket options for the {@code java.net} and {@code java.nio.channels} + * socket classes. + * + * @since 1.9 + */ + +@jdk.Exported +package jdk.net; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/JarFileSystemProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/JarFileSystemProvider.java Wed Jul 05 19:37:43 2017 +0200 @@ -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"); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider --- /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 Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,2 @@ +jdk.nio.zipfs.ZipFileSystemProvider + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipCoder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipCoder.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 decTL = new ThreadLocal<>(); + private final ThreadLocal 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; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipConstants.java Wed Jul 05 19:37:43 2017 +0200 @@ -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; +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 { + + private final ZipFileSystem zipfs; + private final byte[] path; + private final DirectoryStream.Filter filter; + private volatile boolean isClosed; + private volatile Iterator itr; + + ZipDirectoryStream(ZipPath zipPath, + DirectoryStream.Filter 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 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() { + 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; + } + + +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributeView.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributeView.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 get(ZipPath path, Class 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 readAttributes(String attributes) + throws IOException + { + ZipFileAttributes zfas = readAttributes(); + LinkedHashMap 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; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributes.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipFileStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileStore.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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 getFileStoreAttributeView(Class 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; + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) () -> System.getProperty("os.name") + .startsWith("Windows")); + + ZipFileSystem(ZipFileSystemProvider provider, + Path zfpath, + Map 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 getRootDirectories() { + ArrayList 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 getFileStores() { + ArrayList list = new ArrayList<>(1); + list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'}))); + return list; + } + + private static final Set supportedFileAttributeViews = + Collections.unmodifiableSet( + new HashSet(Arrays.asList("basic", "zip"))); + + @Override + public Set 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 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 iteratorOf(byte[] path, + DirectoryStream.Filter 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 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 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 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 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 streams = + Collections.synchronizedSet(new HashSet()); + + // the ex-channel and ex-path that need to close when their outstanding + // input streams are all closed by the obtainers. + private Set exChClosers = new HashSet<>(); + + private Set tmppaths = Collections.synchronizedSet(new HashSet()); + 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 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 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()); + } 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 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 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 streams; + ExChannelCloser(Path path, + SeekableByteChannel ch, + Set 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 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 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(); + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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 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 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 + getFileAttributeView(Path path, Class 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 options, + ExecutorService exec, + FileAttribute... attrs) + throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public SeekableByteChannel newByteChannel(Path path, + Set options, + FileAttribute... attrs) + throws IOException + { + return toZipPath(path).newByteChannel(options, attrs); + } + + @Override + public DirectoryStream newDirectoryStream( + Path path, Filter filter) throws IOException + { + return toZipPath(path).newDirectoryStream(filter); + } + + @Override + public FileChannel newFileChannel(Path path, + Set 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 + readAttributes(Path path, Class type, LinkOption... options) + throws IOException + { + if (type == BasicFileAttributes.class || type == ZipFileAttributes.class) + return (A)toZipPath(path).getAttributes(); + return null; + } + + @Override + public Map + 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); + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipInfo.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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; + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipPath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipPath.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 iterator() { + return new Iterator() { + 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 newDirectoryStream(Filter 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 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 options, + FileAttribute... attrs) + throws IOException + { + return zfs.newByteChannel(getResolvedPath(), options, attrs); + } + + + FileChannel newFileChannel(Set 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; + } + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/jdk/nio/zipfs/ZipUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipUtils.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/awt/AWTAutoShutdown.java --- a/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) () -> { + 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(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/awt/SunToolkit.java --- a/jdk/src/share/classes/sun/awt/SunToolkit.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java --- a/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java Wed Jul 05 19:37:43 2017 +0200 @@ -85,7 +85,7 @@ // read it. Map 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()); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java --- a/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java Wed Jul 05 19:37:43 2017 +0200 @@ -64,9 +64,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; @@ -172,7 +169,7 @@ long[] formats = getClipboardFormatsOpenClose(); return DataTransferer.getInstance(). - getFlavorsForFormatsAsArray(formats, flavorMap); + getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable()); } /** @@ -218,7 +215,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); @@ -349,7 +346,7 @@ private static Set formatArrayAsDataFlavorSet(long[] formats) { return (formats == null) ? null : DataTransferer.getInstance(). - getFlavorsForFormatsAsSet(formats, flavorMap); + getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable()); } @@ -469,4 +466,7 @@ } } + public static FlavorTable getDefaultFlavorTable() { + return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap(); + } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/font/CreatedFontTracker.java --- a/jdk/src/share/classes/sun/font/CreatedFontTracker.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/font/CreatedFontTracker.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - 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) () -> { + /* 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; + }); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/font/SunFontManager.java --- a/jdk/src/share/classes/sun/font/SunFontManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/font/SunFontManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - 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) () -> { + /* 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; + }); } } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/java2d/Disposer.java --- a/jdk/src/share/classes/sun/java2d/Disposer.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/java2d/Disposer.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - 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) () -> { + /* 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; + } + ); } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java --- a/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - public QueueFlusher run() { - ThreadGroup rootThreadGroup = Thread.currentThread().getThreadGroup(); - while (rootThreadGroup.getParent() != null) { - rootThreadGroup = rootThreadGroup.getParent(); - } - return new QueueFlusher(rootThreadGroup); - } + flusher = AccessController.doPrivileged((PrivilegedAction) () -> { + return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup()); }); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/misc/InnocuousThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/misc/InnocuousThread.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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; + +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); + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java --- a/jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java Wed Jul 05 19:37:43 2017 +0200 @@ -36,7 +36,7 @@ public List parse(String header); /* - * Returns the original header this cookie was consructed from, if it was + * Returns the original header this cookie was constructed from, if it was * constructed by parsing a header, otherwise null. */ public String header(HttpCookie cookie); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/misc/ThreadGroupUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/misc/ThreadGroupUtils.java Wed Jul 05 19:37:43 2017 +0200 @@ -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; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,92 @@ +/* + * 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.net; + +import java.net.*; +import jdk.net.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.lang.reflect.Field; +import java.util.Set; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Collections; + +/** + * Contains the native implementation for extended socket options + * together with some other static utilities + */ +public class ExtendedOptionsImpl { + + static { + AccessController.doPrivileged((PrivilegedAction)() -> { + System.loadLibrary("net"); + return null; + }); + init(); + } + + private ExtendedOptionsImpl() {} + + public static void checkSetOptionPermission(SocketOption option) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return; + } + String check = "setOption." + option.name(); + sm.checkPermission(new NetworkPermission(check)); + } + + public static void checkGetOptionPermission(SocketOption option) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return; + } + String check = "getOption." + option.name(); + sm.checkPermission(new NetworkPermission(check)); + } + + public static void checkValueType(Object value, Class type) { + if (!type.isAssignableFrom(value.getClass())) { + String s = "Found: " + value.getClass().toString() + " Expected: " + + type.toString(); + throw new IllegalArgumentException(s); + } + } + + private static native void init(); + + /* + * Extension native implementations + * + * SO_FLOW_SLA + */ + public static native void setFlowOption(FileDescriptor fd, SocketFlow f); + public static native void getFlowOption(FileDescriptor fd, SocketFlow f); + public static native boolean flowSupported(); +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/net/www/MimeTable.java --- a/jdk/src/share/classes/sun/net/www/MimeTable.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/net/www/MimeTable.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 e = elements(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -39,6 +39,7 @@ import java.util.concurrent.*; import java.util.concurrent.locks.*; import sun.net.NetHooks; +import sun.net.ExtendedOptionsImpl; /** * Base implementation of AsynchronousSocketChannel @@ -508,6 +509,9 @@ set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); set.add(StandardSocketOptions.TCP_NODELAY); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -33,6 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.ResourceManager; +import sun.net.ExtendedOptionsImpl; /** * An implementation of DatagramChannels. @@ -317,6 +318,9 @@ set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/Invoker.java --- a/jdk/src/share/classes/sun/nio/ch/Invoker.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/Invoker.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); + } + } + } } /** diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/Net.java --- a/jdk/src/share/classes/sun/nio/ch/Net.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/Net.java Wed Jul 05 19:37:43 2017 +0200 @@ -27,11 +27,13 @@ import java.io.*; import java.net.*; +import jdk.net.*; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; +import sun.net.ExtendedOptionsImpl; public class Net { @@ -297,6 +299,16 @@ // only simple values supported by this method Class type = name.type(); + + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); + } + ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + return; + } + if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here"); @@ -349,6 +361,16 @@ { Class type = name.type(); + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); + } + SocketFlow flow = SocketFlow.create(); + ExtendedOptionsImpl.getFlowOption(fd, flow); + return flow; + } + // only simple values supported by this method if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here"); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -33,6 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; +import sun.net.ExtendedOptionsImpl; /** @@ -237,6 +238,9 @@ // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/ch/ThreadPool.java --- a/jdk/src/share/classes/sun/nio/ch/ThreadPool.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/ThreadPool.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/nio/cs/UTF_8.java --- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java Wed Jul 05 19:37:43 2017 +0200 @@ -111,12 +111,18 @@ (b4 & 0xc0) != 0x80; } - // only used when there is less than 4 bytes left in src buffer + // only used when there is less than 4 bytes left in src buffer. + // both b1 and b2 should be "& 0xff" before passed in. private static boolean isMalformed4_2(int b1, int b2) { - return (b1 == 0xf0 && b2 == 0x90) || + return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) || + (b1 == 0xf4 && (b2 & 0xf0) != 0x80) || (b2 & 0xc0) != 0x80; } + // tests if b1 and b2 are malformed as the first 2 bytes of a + // legal`4-byte utf-8 byte sequence. + // only used when there is less than 4 bytes left in src buffer, + // after isMalformed4_2 has been invoked. private static boolean isMalformed4_3(int b3) { return (b3 & 0xc0) != 0x80; } @@ -280,7 +286,9 @@ // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx int srcRemaining = sl - sp; if (srcRemaining < 4 || dl - dp < 2) { - if (srcRemaining > 1 && isMalformed4_2(b1, sa[sp + 1])) + b1 &= 0xff; + if (b1 > 0xf4 || + srcRemaining > 1 && isMalformed4_2(b1, sa[sp + 1] & 0xff)) return malformedForLength(src, sp, dst, dp, 1); if (srcRemaining > 2 && isMalformed4_3(sa[sp + 2])) return malformedForLength(src, sp, dst, dp, 2); @@ -363,7 +371,9 @@ // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx int srcRemaining = limit - mark; if (srcRemaining < 4 || dst.remaining() < 2) { - if (srcRemaining > 1 && isMalformed4_2(b1, src.get())) + b1 &= 0xff; + if (b1 > 0xf4 || + srcRemaining > 1 && isMalformed4_2(b1, src.get() & 0xff)) return malformedForLength(src, mark, 1); if (srcRemaining > 2 && isMalformed4_3(src.get())) return malformedForLength(src, mark, 2); @@ -518,8 +528,9 @@ } if (malformedInputAction() != CodingErrorAction.REPLACE) return -1; - - if (sp < sl && isMalformed4_2(b1, sa[sp])) { + b1 &= 0xff; + if (b1 > 0xf4 || + sp < sl && isMalformed4_2(b1, sa[sp] & 0xff)) { da[dp++] = replacement().charAt(0); continue; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/provider/SeedGenerator.java --- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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). diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Wed Jul 05 19:37:43 2017 +0200 @@ -75,7 +75,7 @@ private PublicKey prevPubKey; private final static Set SIGNATURE_PRIMITIVE_SET = - EnumSet.of(CryptoPrimitive.SIGNATURE); + Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); private final static DisabledAlgorithmConstraints certPathDefaultConstraints = new DisabledAlgorithmConstraints( diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/rsa/RSAPadding.java --- a/jdk/src/share/classes/sun/security/rsa/RSAPadding.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/rsa/RSAPadding.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 @@ } } } - } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java --- a/jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -28,6 +28,7 @@ import java.io.*; import java.nio.channels.SocketChannel; import java.net.*; +import java.util.Set; import javax.net.ssl.*; @@ -634,6 +635,34 @@ } } + @Override + public Socket setOption(SocketOption name, + T value) throws IOException { + if (self == this) { + return super.setOption(name, value); + } else { + return self.setOption(name, value); + } + } + + @Override + public T getOption(SocketOption name) throws IOException { + if (self == this) { + return super.getOption(name); + } else { + return self.getOption(name); + } + } + + @Override + public Set> supportedOptions() { + if (self == this) { + return super.supportedOptions(); + } else { + return self.supportedOptions(); + } + } + boolean isLayered() { return (self != this); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java --- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Wed Jul 05 19:37:43 2017 +0200 @@ -68,7 +68,7 @@ // performance optimization private final static Set SIGNATURE_PRIMITIVE_SET = - EnumSet.of(CryptoPrimitive.SIGNATURE); + Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); // supported pairs of signature and hash algorithm private final static Map supportedMap; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/tools/jarsigner/Main.java --- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 cacheForSignerInfo = new IdentityHashMap<>(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java --- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/classes/sun/tools/jinfo/JInfo.java --- a/jdk/src/share/classes/sun/tools/jinfo/JInfo.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/classes/sun/tools/jinfo/JInfo.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -39,42 +39,73 @@ * and decides if the command should be satisfied using the VM attach mechanism * or an SA tool. */ -public class JInfo { +final public class JInfo { + private boolean useSA = false; + private String[] args = null; - @SuppressWarnings("fallthrough") - public static void main(String[] args) throws Exception { + private JInfo(String[] args) throws IllegalArgumentException { if (args.length == 0) { - usage(1); // no arguments + throw new IllegalArgumentException(); } + int argCopyIndex = 0; // First determine if we should launch SA or not - boolean useSA = false; if (args[0].equals("-F")) { // delete the -F - args = Arrays.copyOfRange(args, 1, args.length); + argCopyIndex = 1; useSA = true; } else if (args[0].equals("-flags") - || args[0].equals("-sysprops")) + || args[0].equals("-sysprops")) { if (args.length == 2) { - if (!args[1].matches("[0-9]+")) { + if (!isPid(args[1])) { // If args[1] doesn't parse to a number then // it must be the SA debug server // (otherwise it is the pid) useSA = true; } - } - if (args.length == 3) { + } else if (args.length == 3) { // arguments include an executable and a core file useSA = true; + } else { + throw new IllegalArgumentException(); } } else if (!args[0].startsWith("-")) { if (args.length == 2) { // the only arguments are an executable and a core file useSA = true; + } else if (args.length == 1) { + if (!isPid(args[0])) { + // The only argument is not a PID; it must be SA debug + // server + useSA = true; + } + } else { + throw new IllegalArgumentException(); } - } else if (args[0].equals("-h") - || args[0].equals("-help")) { + } else if (args[0].equals("-h") || args[0].equals("-help")) { + if (args.length > 1) { + throw new IllegalArgumentException(); + } + } else if (args[0].equals("-flag")) { + if (args.length == 3) { + if (!isPid(args[2])) { + throw new IllegalArgumentException(); + } + } else { + throw new IllegalArgumentException(); + } + } else { + throw new IllegalArgumentException(); + } + + this.args = Arrays.copyOfRange(args, argCopyIndex, args.length); + } + + @SuppressWarnings("fallthrough") + private void execute() throws Exception { + if (args[0].equals("-h") + || args[0].equals("-help")) { usage(0); } @@ -87,55 +118,69 @@ } // invoke SA which does it's own argument parsing - runTool(args); + runTool(); } else { // Now we can parse arguments for the non-SA case String pid = null; switch(args[0]) { - case "-flag": - if (args.length != 3) { - usage(1); - } - String option = args[1]; - pid = args[2]; - flag(pid, option); - break; - case "-flags": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - flags(pid); - break; - case "-sysprops": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - sysprops(pid); - break; - case "-help": - case "-h": - usage(0); - // Fall through - default: - if (args.length == 1) { - // no flags specified, we do -sysprops and -flags - pid = args[0]; - sysprops(pid); - System.out.println(); - flags(pid); - } else { - usage(1); - } + case "-flag": + if (args.length != 3) { + usage(1); + } + String option = args[1]; + pid = args[2]; + flag(pid, option); + break; + case "-flags": + if (args.length != 2) { + usage(1); + } + pid = args[1]; + flags(pid); + break; + case "-sysprops": + if (args.length != 2) { + usage(1); + } + pid = args[1]; + sysprops(pid); + break; + case "-help": + case "-h": + usage(0); + // Fall through + default: + if (args.length == 1) { + // no flags specified, we do -sysprops and -flags + pid = args[0]; + sysprops(pid); + System.out.println(); + flags(pid); + } else { + usage(1); + } } } } + public static void main(String[] args) throws Exception { + JInfo jinfo = null; + try { + jinfo = new JInfo(args); + jinfo.execute(); + } catch (IllegalArgumentException e) { + usage(1); + } + } + + private static boolean isPid(String arg) { + return arg.matches("[0-9]+"); + } + // Invoke SA tool with the given arguments - private static void runTool(String args[]) throws Exception { + private void runTool() throws Exception { String tool = "sun.jvm.hotspot.tools.JInfo"; // Tool not available on this platform. Class c = loadClass(tool); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/Demo.java --- a/jdk/src/share/demo/nio/zipfs/Demo.java Thu Apr 17 15:23:23 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, // - // rename entry src to dst inside zipfile - - movein, // - // move an external src file into zipfile - // as entry dst - - moveout, // - // move a zipfile entry src out to dst - - copy, // - // copy entry src to dst inside zipfile - - copyin, // - // copy an external src file into zipfile - // as entry dst - - copyin_attrs, // - // copy an external src file into zipfile - // as entry dst, with attributes (timestamp) - - copyout, // - // copy zipfile entry src" out to file dst - - copyout_attrs, // - - zzmove, // - // move entry path/dir from zfsrc to zfdst - - zzcopy, // - // copy path from zipfile zfsrc to zipfile - // zfdst - - attrs, // - // printout the attributes of entry path - - attrsspace, // - // printout the storespace attrs of entry path - - setmtime, // - // set the lastModifiedTime of entry path - - setatime, // - setctime, // - - lsdir, // - // list dir's direct child files/dirs - - mkdir, // - - mkdirs, // - - rmdirs, // - - list, // - // recursively list all entries of dir - // via DirectoryStream - - tlist, // - // list with buildDirTree=true - - vlist, // - // recursively verbose list all entries of - // dir via DirectoryStream - - walk, // - // recursively walk all entries of dir - // via Files.walkFileTree - - twalk, // - // walk with buildDirTree=true - - extract, // - - update, // - - delete, // - - add, // - - create, // - // create a new zipfile if it doesn't exit - // and then add the file(s) into it. - - attrs2, // - // 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 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 ds = Files.newDirectoryStream(path, - new DirectoryStream.Filter() { - @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 map = Files.readAttributes(path, "zip:*"); - for (Map.Entry 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 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() { - 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 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 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 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() { - - @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 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 read = new HashSet<>(); - read.add(READ); - Set 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 read = new HashSet<>(); - read.add(READ); - Set 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); - } - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/README.txt --- a/jdk/src/share/demo/nio/zipfs/README.txt Thu Apr 17 15:23:23 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 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. - - diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider --- a/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider Thu Apr 17 15:23:23 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -com.sun.nio.zipfs.ZipFileSystemProvider - diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java Thu Apr 17 15:23:23 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"); - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java Thu Apr 17 15:23:23 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 decTL = new ThreadLocal<>(); - private final ThreadLocal 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; - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java Thu Apr 17 15:23:23 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; -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java Thu Apr 17 15:23:23 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 { - - private final ZipFileSystem zipfs; - private final byte[] path; - private final DirectoryStream.Filter filter; - private volatile boolean isClosed; - private volatile Iterator itr; - - ZipDirectoryStream(ZipPath zipPath, - DirectoryStream.Filter 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 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() { - 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; - } - - -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java Thu Apr 17 15:23:23 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 get(ZipPath path, Class 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 readAttributes(String attributes) - throws IOException - { - ZipFileAttributes zfas = readAttributes(); - LinkedHashMap 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; - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java Thu Apr 17 15:23:23 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(); - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java Thu Apr 17 15:23:23 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 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 getFileStoreAttributeView(Class 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; - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Thu Apr 17 15:23:23 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 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 getRootDirectories() { - ArrayList 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 getFileStores() { - ArrayList list = new ArrayList<>(1); - list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'}))); - return list; - } - - private static final Set supportedFileAttributeViews = - Collections.unmodifiableSet( - new HashSet(Arrays.asList("basic", "zip"))); - - @Override - public Set 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 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 iteratorOf(byte[] path, - DirectoryStream.Filter 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 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 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 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 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 streams = - Collections.synchronizedSet(new HashSet()); - - // the ex-channel and ex-path that need to close when their outstanding - // input streams are all closed by the obtainers. - private Set exChClosers = new HashSet<>(); - - private Set tmppaths = Collections.synchronizedSet(new HashSet()); - 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 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 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()); - } 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 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 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 streams; - ExChannelCloser(Path path, - SeekableByteChannel ch, - Set 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 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 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(); - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java Thu Apr 17 15:23:23 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 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 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 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 - getFileAttributeView(Path path, Class 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 options, - ExecutorService exec, - FileAttribute... attrs) - throws IOException - { - throw new UnsupportedOperationException(); - } - - @Override - public SeekableByteChannel newByteChannel(Path path, - Set options, - FileAttribute... attrs) - throws IOException - { - return toZipPath(path).newByteChannel(options, attrs); - } - - @Override - public DirectoryStream newDirectoryStream( - Path path, Filter filter) throws IOException - { - return toZipPath(path).newDirectoryStream(filter); - } - - @Override - public FileChannel newFileChannel(Path path, - Set 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 - readAttributes(Path path, Class type, LinkOption... options) - throws IOException - { - if (type == BasicFileAttributes.class || type == ZipFileAttributes.class) - return (A)toZipPath(path).getAttributes(); - return null; - } - - @Override - public Map - 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); - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java Thu Apr 17 15:23:23 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 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; - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Thu Apr 17 15:23:23 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 iterator() { - return new Iterator() { - 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 newDirectoryStream(Filter 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 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 options, - FileAttribute... attrs) - throws IOException - { - return zfs.newByteChannel(getResolvedPath(), options, attrs); - } - - - FileChannel newFileChannel(Set 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; - } - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java Thu Apr 17 15:23:23 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(); - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/java/net/net_util.h --- a/jdk/src/share/native/java/net/net_util.h Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/java/net/net_util.h Wed Jul 05 19:37:43 2017 +0200 @@ -40,7 +40,7 @@ #define IPv6 2 #define NET_ERROR(env, ex, msg) \ -{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg) } +{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); } /************************************************************************ * Cached field IDs diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/giflib/dgif_lib.c --- a/jdk/src/share/native/sun/awt/giflib/dgif_lib.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/giflib/dgif_lib.c Wed Jul 05 19:37:43 2017 +0200 @@ -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. */ } /****************************************************************************** diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/image/gif/gifdecoder.c --- a/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c --- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c --- a/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Wed Jul 05 19:37:43 2017 +0200 @@ -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. */ diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c --- a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/libpng/pngrtran.c --- a/jdk/src/share/native/sun/awt/libpng/pngrtran.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/libpng/pngrtran.c Wed Jul 05 19:37:43 2017 +0200 @@ -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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/libpng/pngset.c --- a/jdk/src/share/native/sun/awt/libpng/pngset.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/libpng/pngset.c Wed Jul 05 19:37:43 2017 +0200 @@ -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. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c --- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Wed Jul 05 19:37:43 2017 +0200 @@ -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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp --- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -154,6 +154,7 @@ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { LEReferenceToArrayOf valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount); + if (LE_FAILURE(success)) { return newGlyph; } newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success)); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp --- a/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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 inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2); + if (LE_FAILURE(success)) { return 0; } if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) { LEReferenceToArrayOf substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount); @@ -315,6 +318,7 @@ LEReferenceToArrayOf classArray(base, success, subClassRuleTable->classArray, matchCount+1); + if (LE_FAILURE(success)) { return 0; } if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) { LEReferenceToArrayOf substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount); @@ -573,7 +577,7 @@ if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) { LEReferenceToArrayOf 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 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 lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2); if( LE_FAILURE(success) ) { return 0; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp --- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -95,7 +95,7 @@ if (actionOffset != 0) { LEReferenceTo 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 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) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/LookupProcessor.cpp --- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -282,6 +282,7 @@ for (le_uint16 feature = 0; feature < featureCount; feature += 1) { LEReferenceToArrayOf 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... diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp --- a/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -67,6 +67,7 @@ LEPoint markAnchor; LEReferenceTo 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp --- a/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -79,8 +79,8 @@ Offset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf &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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp --- a/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -73,6 +73,7 @@ if (offset != 0) { LEReferenceToArrayOf 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); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp --- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -97,6 +97,7 @@ LEReferenceToArrayOf 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Wed Jul 05 19:37:43 2017 +0200 @@ -302,8 +302,6 @@ return NULL; } - - chunk ->BlockSize = Initial; chunk ->Used = 0; chunk ->next = NULL; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Wed Jul 05 19:37:43 2017 +0200 @@ -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++) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; } // --------------------------------------------------------------------------------------------------------------- diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Wed Jul 05 19:37:43 2017 +0200 @@ -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) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Wed Jul 05 19:37:43 2017 +0200 @@ -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) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Wed Jul 05 19:37:43 2017 +0200 @@ -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: diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Wed Jul 05 19:37:43 2017 +0200 @@ -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)) diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h --- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h --- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/management/Flag.c --- a/jdk/src/share/native/sun/management/Flag.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/management/Flag.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/share/native/sun/management/GcInfoBuilder.c --- a/jdk/src/share/native/sun/management/GcInfoBuilder.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/share/native/sun/management/GcInfoBuilder.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java --- a/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -25,6 +25,11 @@ package java.net; import java.io.IOException; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import jdk.net.*; +import static sun.net.ExtendedOptionsImpl.*; /* * On Unix systems we simply delegate to native methods. @@ -38,6 +43,42 @@ init(); } + protected void setOption(SocketOption name, T value) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + super.setOption(name, value); + } else { + if (isClosed()) { + throw new SocketException("Socket closed"); + } + checkSetOptionPermission(name); + checkValueType(value, SocketFlow.class); + setFlowOption(getFileDescriptor(), (SocketFlow)value); + } + } + + protected T getOption(SocketOption name) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + return super.getOption(name); + } + if (isClosed()) { + throw new SocketException("Socket closed"); + } + checkGetOptionPermission(name); + SocketFlow flow = SocketFlow.create(); + getFlowOption(getFileDescriptor(), flow); + return (T)flow; + } + + protected Set> supportedOptions() { + HashSet> options = new HashSet( + super.supportedOptions()); + + if (flowSupported()) { + options.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + return options; + } + protected synchronized native void bind0(int lport, InetAddress laddr) throws SocketException; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/java/net/PlainSocketImpl.java --- a/jdk/src/solaris/classes/java/net/PlainSocketImpl.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/java/net/PlainSocketImpl.java Wed Jul 05 19:37:43 2017 +0200 @@ -26,6 +26,12 @@ import java.io.IOException; import java.io.FileDescriptor; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import jdk.net.*; + +import static sun.net.ExtendedOptionsImpl.*; /* * On Unix systems we simply delegate to native methods. @@ -51,6 +57,42 @@ this.fd = fd; } + protected void setOption(SocketOption name, T value) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + super.setOption(name, value); + } else { + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + checkSetOptionPermission(name); + checkValueType(value, SocketFlow.class); + setFlowOption(getFileDescriptor(), (SocketFlow)value); + } + } + + protected T getOption(SocketOption name) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + return super.getOption(name); + } + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + checkGetOptionPermission(name); + SocketFlow flow = SocketFlow.create(); + getFlowOption(getFileDescriptor(), flow); + return (T)flow; + } + + protected Set> supportedOptions() { + HashSet> options = new HashSet( + super.supportedOptions()); + + if (getSocket() != null && flowSupported()) { + options.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + return options; + } + native void socketCreate(boolean isServer) throws IOException; native void socketConnect(InetAddress address, int port, int timeout) @@ -77,5 +119,4 @@ native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; native void socketSendUrgentData(int data) throws IOException; - } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/awt/X11/XClipboard.java --- a/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java Wed Jul 05 19:37:43 2017 +0200 @@ -86,7 +86,7 @@ protected synchronized void setContentsNative(Transferable contents) { SortedMap 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())); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/awt/X11/XToolkit.java --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 a = new PrivilegedAction() { - 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 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 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 = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, "AWT-XAWT"); + thread.setContextClassLoader(null); + thread.setPriority(Thread.NORM_PRIORITY + 1); + thread.setDaemon(true); + return thread; + }); toolkitThread.start(); } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java --- a/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 a = new PrivilegedAction() { - public Void run() { - ThreadGroup mainTG = Thread.currentThread().getThreadGroup(); - ThreadGroup parentTG = mainTG.getParent(); - while (parentTG != null) { - mainTG = parentTG; - parentTG = mainTG.getParent(); + PrivilegedAction 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); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/net/www/content-types.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/classes/sun/net/www/content-types.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,280 @@ +#sun.net.www MIME content-types table +# +# Property fields: +# +# ::= 'description' '=' +# ::= 'file_extensions' '=' +# ::= 'icon' '=' +# ::= 'browser' | 'application' | 'save' | 'unknown' +# ::= 'application' '=' +# + +# +# 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 + + + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java --- a/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Wed Jul 05 19:37:43 2017 +0200 @@ -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> 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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java --- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java Wed Jul 05 19:37:43 2017 +0200 @@ -48,7 +48,7 @@ // filter (may be null) private final DirectoryStream.Filter filter; - // used to coorindate closing of directory stream + // used to coordinate closing of directory stream private final ReentrantReadWriteLock streamLock = new ReentrantReadWriteLock(true); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 posixAttributeNames = Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/demo/jni/Poller/Poller.c --- a/jdk/src/solaris/demo/jni/Poller/Poller.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/demo/jni/Poller/Poller.c Wed Jul 05 19:37:43 2017 +0200 @@ -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]; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/lib/content-types.properties --- a/jdk/src/solaris/lib/content-types.properties Thu Apr 17 15:23:23 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' '=' -# ::= 'file_extensions' '=' -# ::= 'icon' '=' -# ::= 'browser' | 'application' | 'save' | 'unknown' -# ::= 'application' '=' -# - -# -# 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 - - - diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c Wed Jul 05 19:37:43 2017 +0200 @@ -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); } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/native/java/net/ExtendedOptionsImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/native/java/net/ExtendedOptionsImpl.c Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,337 @@ +/* + * 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. + */ + +#include +#include + +#include "net_util.h" +#include "jdk_net_SocketFlow.h" + +static jclass sf_status_class; /* Status enum type */ + +static jfieldID sf_status; +static jfieldID sf_priority; +static jfieldID sf_bandwidth; + +static jfieldID sf_fd_fdID; /* FileDescriptor.fd */ + +/* References to the literal enum values */ + +static jobject sfs_NOSTATUS; +static jobject sfs_OK; +static jobject sfs_NOPERMISSION; +static jobject sfs_NOTCONNECTED; +static jobject sfs_NOTSUPPORTED; +static jobject sfs_ALREADYCREATED; +static jobject sfs_INPROGRESS; +static jobject sfs_OTHER; + +static jobject getEnumField(JNIEnv *env, char *name); +static void setStatus(JNIEnv *env, jobject obj, int errval); + +/* OS specific code is implemented in these three functions */ + +static jboolean flowSupported0() ; + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init + (JNIEnv *env, jclass UNUSED) +{ + static int initialized = 0; + jclass c; + + /* Global class references */ + + if (initialized) { + return; + } + + c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status"); + CHECK_NULL(c); + sf_status_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL(sf_status_class); + + /* int "fd" field of java.io.FileDescriptor */ + + c = (*env)->FindClass(env, "java/io/FileDescriptor"); + CHECK_NULL(c); + sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I"); + CHECK_NULL(sf_fd_fdID); + + + /* SocketFlow fields */ + + c = (*env)->FindClass(env, "jdk/net/SocketFlow"); + + /* status */ + + sf_status = (*env)->GetFieldID(env, c, "status", + "Ljdk/net/SocketFlow$Status;"); + CHECK_NULL(sf_status); + + /* priority */ + + sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); + CHECK_NULL(sf_priority); + + /* bandwidth */ + + sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); + CHECK_NULL(sf_bandwidth); + + /* Initialize the static enum values */ + + sfs_NOSTATUS = getEnumField(env, "NO_STATUS"); + CHECK_NULL(sfs_NOSTATUS); + sfs_OK = getEnumField(env, "OK"); + CHECK_NULL(sfs_OK); + sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION"); + CHECK_NULL(sfs_NOPERMISSION); + sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED"); + CHECK_NULL(sfs_NOTCONNECTED); + sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED"); + CHECK_NULL(sfs_NOTSUPPORTED); + sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED"); + CHECK_NULL(sfs_ALREADYCREATED); + sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS"); + CHECK_NULL(sfs_INPROGRESS); + sfs_OTHER = getEnumField(env, "OTHER"); + CHECK_NULL(sfs_OTHER); + initialized = JNI_TRUE; +} + +static jobject getEnumField(JNIEnv *env, char *name) +{ + jobject f; + jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name, + "Ljdk/net/SocketFlow$Status;"); + CHECK_NULL_RETURN(fID, NULL); + + f = (*env)->GetStaticObjectField(env, sf_status_class, fID); + CHECK_NULL_RETURN(f, NULL); + f = (*env)->NewGlobalRef(env, f); + CHECK_NULL_RETURN(f, NULL); + return f; +} + +/* + * Retrieve the int file-descriptor from a public socket type object. + * Gets impl, then the FileDescriptor from the impl, and then the fd + * from that. + */ +static int getFD(JNIEnv *env, jobject fileDesc) { + return (*env)->GetIntField(env, fileDesc, sf_fd_fdID); +} + +/** + * Sets the status field of a SocketFlow to one of the + * canned enum values + */ +static void setStatus (JNIEnv *env, jobject obj, int errval) +{ + switch (errval) { + case 0: /* OK */ + (*env)->SetObjectField(env, obj, sf_status, sfs_OK); + break; + case EPERM: + (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION); + break; + case ENOTCONN: + (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED); + break; + case EOPNOTSUPP: + (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED); + break; + case EALREADY: + (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED); + break; + case EINPROGRESS: + (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS); + break; + default: + (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER); + break; + } +} + +#ifdef __solaris__ + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: setFlowOption + * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + int fd = getFD(env, fileDesc); + + if (fd < 0) { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return; + } else { + sock_flow_props_t props; + jlong bandwidth; + int rv; + + jint priority = (*env)->GetIntField(env, flow, sf_priority); + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + + if (priority != jdk_net_SocketFlow_UNSET) { + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = priority; + } + bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth); + if (bandwidth > -1) { + props.sfp_mask |= SFP_MAXBW; + props.sfp_maxbw = (uint64_t) bandwidth; + } + rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", + "set option SO_FLOW_SLA failed"); + } + return; + } + setStatus(env, flow, props.sfp_status); + } +} + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: getFlowOption + * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + int fd = getFD(env, fileDesc); + + if (fd < 0) { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return; + } else { + sock_flow_props_t props; + int status; + socklen_t sz = sizeof(props); + + int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else { + NET_ERROR(env, JNU_JAVANETPKG "SocketException", + "set option SO_FLOW_SLA failed"); + } + return; + } + /* first check status to see if flow exists */ + status = props.sfp_status; + setStatus(env, flow, status); + if (status == 0) { /* OK */ + /* can set the other fields now */ + if (props.sfp_mask & SFP_PRIORITY) { + (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); + } + if (props.sfp_mask & SFP_MAXBW) { + (*env)->SetLongField(env, flow, sf_bandwidth, + (jlong)props.sfp_maxbw); + } + } + } +} + +static jboolean flowsupported; +static jboolean flowsupported_set = JNI_FALSE; + +static jboolean flowSupported0() +{ + /* Do a simple dummy call, and try to figure out from that */ + sock_flow_props_t props; + int rv, s; + if (flowsupported_set) { + return flowsupported; + } + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + flowsupported = JNI_FALSE; + flowsupported_set = JNI_TRUE; + return JNI_FALSE; + } + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = SFP_PRIO_NORMAL; + rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + flowsupported = rv; + flowsupported_set = JNI_TRUE; + return flowsupported; +} + +#else /* __solaris__ */ + +/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ + +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +static jboolean flowSupported0() { + return JNI_FALSE; +} + +#endif /* __solaris__ */ + +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported + (JNIEnv *env, jclass UNUSED) +{ + return flowSupported0(); +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/native/java/net/net_util_md.h --- a/jdk/src/solaris/native/java/net/net_util_md.h Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/native/java/net/net_util_md.h Wed Jul 05 19:37:43 2017 +0200 @@ -107,6 +107,47 @@ #ifdef __solaris__ int net_getParam(char *driver, char *param); + +#ifndef SO_FLOW_SLA +#define SO_FLOW_SLA 0x1018 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) #endif +/* + * Used with the setsockopt(SO_FLOW_SLA, ...) call to set + * per socket service level properties. + * When the application uses per-socket API, we will enforce the properties + * on both outbound and inbound packets. + * + * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. + */ +typedef struct sock_flow_props_s { + int sfp_version; + uint32_t sfp_mask; + int sfp_priority; /* flow priority */ + uint64_t sfp_maxbw; /* bandwidth limit in bps */ + int sfp_status; /* flow create status for getsockopt */ +} sock_flow_props_t; + +#define SOCK_FLOW_PROP_VERSION1 1 + +/* bit mask values for sfp_mask */ +#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ +#define SFP_PRIORITY 0x00000008 /* Flow priority */ + +/* possible values for sfp_priority */ +#define SFP_PRIO_NORMAL 1 +#define SFP_PRIO_HIGH 2 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif /* _LONG_LONG_ALIGNMENT */ + +#endif /* SO_FLOW_SLA */ +#endif /* __solaris__ */ + +JNIEXPORT jboolean JNICALL NET_IsFlowSupported(); + #endif /* NET_UTILS_MD_H */ diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/solaris/native/java/util/TimeZone_md.c --- a/jdk/src/solaris/native/java/util/TimeZone_md.c Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/solaris/native/java/util/TimeZone_md.c Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -56,6 +56,9 @@ static const char *ZONEINFO_DIR = "/usr/share/zoneinfo"; static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime"; #else +#ifdef _AIX +static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; +#endif static const char *SYS_INIT_FILE = "/etc/default/init"; static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; @@ -619,8 +622,29 @@ static char * getPlatformTimeZoneID() { - return NULL; + FILE *fp; + char *tz = NULL; + char *tz_key = "TZ="; + char line[256]; + size_t tz_key_len = strlen(tz_key); + + if ((fp = fopen(ETC_ENVIRONMENT_FILE, "r")) != NULL) { + while (fgets(line, sizeof(line), fp) != NULL) { + char *p = strchr(line, '\n'); + if (p != NULL) { + *p = '\0'; + } + if (0 == strncmp(line, tz_key, tz_key_len)) { + tz = strdup(line + tz_key_len); + break; + } + } + (void) fclose(fp); + } + + return tz; } +static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz); #endif /* @@ -678,9 +702,19 @@ if (freetz != NULL) { free((void *) freetz); } + +#ifdef _AIX + freetz = mapPlatformToJavaTimezone(java_home_dir, javatz); + if (javatz != NULL) { + free((void *) javatz); + } + javatz = freetz; +#endif } + return javatz; } + /** * Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00") */ @@ -747,3 +781,101 @@ return strdup(buf); } #endif /* MACOSX */ + +#ifdef _AIX +static char * +mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { + FILE *tzmapf; + char mapfilename[PATH_MAX+1]; + char line[256]; + int linecount = 0; + char temp[100], *temp_tz; + char *javatz = NULL; + char *str_tmp = NULL; + size_t temp_tz_len = 0; + + /* On AIX, the TZ environment variable may end with a comma + * followed by modifier fields. These are ignored here. + */ + strncpy(temp, tz, 100); + temp_tz = strtok_r(temp, ",", &str_tmp); + + if(temp_tz == NULL) + goto tzerr; + + temp_tz_len = strlen(temp_tz); + + if (strlen(java_home_dir) >= (PATH_MAX - 15)) { + jio_fprintf(stderr, "java.home longer than maximum path length \n"); + goto tzerr; + } + + strncpy(mapfilename, java_home_dir, PATH_MAX); + strcat(mapfilename, "/lib/tzmappings"); + + if ((tzmapf = fopen(mapfilename, "r")) == NULL) { + jio_fprintf(stderr, "can't open %s\n", mapfilename); + goto tzerr; + } + + while (fgets(line, sizeof(line), tzmapf) != NULL) { + char *p = line; + char *sol = line; + char *java; + int result; + + linecount++; + /* + * Skip comments and blank lines + */ + if (*p == '#' || *p == '\n') { + continue; + } + + /* + * Get the first field, platform zone ID + */ + while (*p != '\0' && *p != '\t') { + p++; + } + if (*p == '\0') { + /* mapping table is broken! */ + jio_fprintf(stderr, "tzmappings: Illegal format at near line %d.\n", linecount); + break; + } + + *p++ = '\0'; + if ((result = strncmp(temp_tz, sol, temp_tz_len)) == 0) { + /* + * If this is the current platform zone ID, + * take the Java time zone ID (2nd field). + */ + java = p; + while (*p != '\0' && *p != '\n') { + p++; + } + + if (*p == '\0') { + /* mapping table is broken! */ + jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", linecount); + break; + } + + *p = '\0'; + javatz = strdup(java); + break; + } else if (result < 0) { + break; + } + } + (void) fclose(tzmapf); + +tzerr: + if (javatz == NULL) { + return getGMTOffsetID(); + } + + return javatz; +} +#endif + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java --- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Jul 05 19:37:43 2017 +0200 @@ -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() { - public Thread run() { + comThread = AccessController.doPrivileged((PrivilegedAction) () -> { /* 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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/awt/windows/WClipboard.java --- a/jdk/src/windows/classes/sun/awt/windows/WClipboard.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/awt/windows/WClipboard.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 formatMap = WDataTransferer.getInstance(). - getFormatsForTransferable(contents, flavorMap); + getFormatsForTransferable(contents, getDefaultFlavorTable()); openClipboard(this); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/awt/windows/WToolkit.java --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) 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() { - @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) () -> { + 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) () -> { + Thread.currentThread().setContextClassLoader(null); + return null; + }); + Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1); boolean startPump = init(); if (startPump) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java --- a/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) () -> { + 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) () -> { + 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(); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/net/www/content-types.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/windows/classes/sun/net/www/content-types.properties Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,276 @@ +#sun.net.www MIME content-types table +# +# Property fields: +# +# ::= 'description' '=' +# ::= 'file_extensions' '=' +# ::= 'icon' '=' +# ::= 'browser' | 'application' | 'save' | 'unknown' +# ::= 'application' '=' +# + +# +# 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 + + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Wed Jul 05 19:37:43 2017 +0200 @@ -61,7 +61,7 @@ this.followLinks = followLinks; } - // permision check + // permission check private void checkAccess(WindowsPath file, boolean checkRead, boolean checkWrite) diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Wed Jul 05 19:37:43 2017 +0200 @@ -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; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Wed Jul 05 19:37:43 2017 +0200 @@ -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). */ diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Wed Jul 05 19:37:43 2017 +0200 @@ -917,7 +917,7 @@ } } private static native void CreateHardLink0(long newFileBuffer, - long existingFiletBuffer) throws WindowsException; + long existingFileBuffer) throws WindowsException; /** * GetFullPathName( diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsPath.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java Wed Jul 05 19:37:43 2017 +0200 @@ -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) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java Wed Jul 05 19:37:43 2017 +0200 @@ -200,7 +200,7 @@ public List 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 { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java --- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Wed Jul 05 19:37:43 2017 +0200 @@ -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. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/classes/sun/print/Win32PrintService.java --- a/jdk/src/windows/classes/sun/print/Win32PrintService.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java Wed Jul 05 19:37:43 2017 +0200 @@ -1585,7 +1585,7 @@ if (flavor != null && !isDocFlavorSupported(flavor)) { throw new IllegalArgumentException("flavor " + flavor + - "is not supported"); + " is not supported"); } if (attributes == null) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/lib/content-types.properties --- a/jdk/src/windows/lib/content-types.properties Thu Apr 17 15:23:23 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' '=' -# ::= 'file_extensions' '=' -# ::= 'icon' '=' -# ::= 'browser' | 'application' | 'save' | 'unknown' -# ::= 'application' '=' -# - -# -# 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 - - diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/native/java/net/ExtendedOptionsImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/windows/native/java/net/ExtendedOptionsImpl.c Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#include +#include + +#include "net_util.h" + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init + (JNIEnv *env, jclass UNUSED) +{ +} + +/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ + +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption + (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) +{ + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); +} + +static jboolean flowSupported0() { + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported + (JNIEnv *env, jclass UNUSED) +{ + return JNI_FALSE; +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/src/windows/native/sun/windows/awt_Toolkit.cpp --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Jul 05 19:37:43 2017 +0200 @@ -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; } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/TEST.groups --- a/jdk/test/TEST.groups Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/TEST.groups Wed Jul 05 19:37:43 2017 +0200 @@ -102,7 +102,8 @@ jdk_net = \ java/net \ com/sun/net/httpserver \ - sun/net + sun/net \ + jdk/net jdk_time = \ java/time @@ -284,7 +285,7 @@ javax/accessibility \ com/sun/java/swing \ sun/pisces \ - com/sun/awt + com/sun/awt ############################################################################### @@ -294,7 +295,7 @@ # - compact1, compact2, compact3, full JRE, JDK # # In addition they support testing of the minimal VM on compact1 and compact2. -# Essentially this defines groups based around the specified API's and VM +# Essentially this defines groups based around the specified API's and VM # services available in the runtime. # # The groups are defined hierarchically in two forms: @@ -506,7 +507,7 @@ -:needs_jdk # Tests that require compact2 API's and a full VM -# +# needs_full_vm_compact2 = # Minimal VM on Compact 2 adds in some compact2 tests @@ -590,7 +591,7 @@ javax/crypto/Cipher/CipherStreamClose.java \ sun/misc/URLClassPath/ClassnameCharTest.java \ sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \ - sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java + sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java # Compact 1 adds full VM tests # diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/com/sun/jdi/ShellScaffold.sh --- a/jdk/test/com/sun/jdi/ShellScaffold.sh Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh Wed Jul 05 19:37:43 2017 +0200 @@ -199,30 +199,26 @@ return 1 fi - if [ -z "$isWin98" ] ; then - if [ "$osname" = SunOS ] ; then - # Solaris and OpenSolaris use pgrep and not ps in psCmd - findPidCmd="$psCmd" - elif [ "$osname" = AIX ] ; then - findPidCmd="$psCmd" - else + case "$osname" in + SunOS | AIX) + $psCmd | $grep '^ *'"$1 " > $devnull 2>&1 + res=$? + ;; + Windows* | CYGWIN*) + # Don't use ps on cygwin since it sometimes misses + # some processes (!). + tasklist /NH | $grep " $1 " > $devnull 2>&1 + res=$? + ;; + *) # Never use plain 'ps', which requires a "controlling terminal" # and will fail with a "ps: no controlling terminal" error. # Running under 'rsh' will cause this ps error. - # cygwin ps puts an I in column 1 for some reason. - findPidCmd="$psCmd -e" - fi - $findPidCmd | $grep '^I* *'"$1 " > $devnull 2>&1 - return $? - fi - - # mks 6.2a on win98 has $! getting a negative - # number and in ps, it shows up as 0x... - # Thus, we can't search in ps output for - # PIDs gotten via $! - # We don't know if it is running or not - assume it is. - # We don't really care about win98 anymore. - return 0 + $psCmd -e | $grep '^ *'"$1 " > $devnull 2>&1 + res=$? + ;; + esac + return $res } setup() @@ -252,16 +248,10 @@ ulimitCmd= osname=`uname -s` - isWin98= isCygwin= case "$osname" in Windows* | CYGWIN*) devnull=NUL - if [ "$osname" = Windows_98 -o "$osname" = Windows_ME ]; then - isWin98=1 - debuggeeKeyword='we_cant_kill_debuggees_on_win98' - jdbKeyword='jdb\.exe' - fi case "$osname" in CYGWIN*) isCygwin=1 @@ -772,7 +762,7 @@ sleep ${sleep_seconds} findPid $topPid if [ $? != 0 ] ; then - # Top process is dead. We better die too + echo "--Top process ($topPid) is dead. We better die too" >&2 dojstack exit 1 fi @@ -977,19 +967,12 @@ break fi - if [ ! -z "$isWin98" ] ; then - $psCmd | $grep -i 'JDB\.EXE' >$devnull 2>&1 - if [ $? != 0 ] ; then - break - fi - fi - # (Don't use jdbFailIfPresent here since it is not safe # to call from different processes) - $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 - if [ $? = 0 ] ; then + $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 + if [ $? = 0 ] ; then dofail "jdb input stream closed prematurely" - fi + fi # If a failure has occured, quit if [ -r "$failFile" ] ; then diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/demo/zipfs/Basic.java --- a/jdk/test/demo/zipfs/Basic.java Thu Apr 17 15:23:23 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 env = new HashMap(); - 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 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 { - private int indent = 0; - - private void indent() { - StringBuilder sb = new StringBuilder(indent); - for (int i=0; i %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(); - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/demo/zipfs/ZFSTests.java --- a/jdk/test/demo/zipfs/ZFSTests.java Thu Apr 17 15:23:23 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 env = new HashMap(); - env.put("create", "true"); - try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {} - } finally { - Files.deleteIfExists(path); - Files.deleteIfExists(dir); - } - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/demo/zipfs/ZipFSTester.java --- a/jdk/test/demo/zipfs/ZipFSTester.java Thu Apr 17 15:23:23 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())) - { - test0(fs); - test1(fs); - test2(fs); // more tests - testTime(Paths.get(args[0])); - } - } - - static void test0(FileSystem fs) - throws Exception - { - List list = new LinkedList<>(); - try (ZipFile zf = new ZipFile(fs.toString())) { - Enumeration 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 env = new HashMap(); - env.put("create", "true"); - try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) { - z2zcopy(fs0, copy, "/", 0); - } - - try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap())) { - - FileSystemProvider provider = fs.provider(); - // newFileSystem(path...) should not throw exception - try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap())){} - try (FileSystem fsUri = provider.newFileSystem( - new URI("jar", tmpfsPath.toUri().toString(), null), - new HashMap())) - { - 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()); - throw new RuntimeException("newFileSystem() opens a directory as zipfs"); - } catch (UnsupportedOperationException uoe) {} - - try { - provider.newFileSystem(src, new HashMap()); - 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 env = new HashMap(); - 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(); - final FileSystem fs1 = newZipFileSystem(fs1Path, env); - - System.out.println("listing..."); - final ArrayList files = new ArrayList<>(); - final ArrayList dirs = new ArrayList<>(); - list(fs1.getPath("/"), files, dirs); - - Thread t0 = new Thread(new Runnable() { - public void run() { - List 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 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 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 list = new ArrayList<>(files); - Collections.shuffle(list); - while (!list.isEmpty()) { - Iterator 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 files2 = new ArrayList<>(); - ArrayList 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 env = new HashMap(); - 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 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 files, List dirs ) - throws IOException - { - if (Files.isDirectory(path)) { - try (DirectoryStream 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 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 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() { - 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 read = new HashSet<>(); - read.add(READ); - Set 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 read = new HashSet<>(); - read.add(READ); - Set 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 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; - } -} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/demo/zipfs/basic.sh --- a/jdk/test/demo/zipfs/basic.sh Thu Apr 17 15:23:23 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 diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/awt/Toolkit/LoadAWTCrashTest/LoadAWTCrashTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Toolkit/LoadAWTCrashTest/LoadAWTCrashTest.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/awt/font/TextLayout/TestAATMorxFont.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/TextLayout/TestAATMorxFont.java Wed Jul 05 19:37:43 2017 +0200 @@ -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); + + } +} + diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 8039396 + * @run main UnresolvableObjectStreamClass serialize + * @clean MySerializable + * @run main UnresolvableObjectStreamClass deserialize + * + * @summary NPE when writing a class descriptor object to a custom + * ObjectOutputStream + */ + +import java.io.*; + +public class UnresolvableObjectStreamClass { + public static void main(String[] args) throws Throwable { + if (args.length > 0 && args[0].equals("serialize")) { + try (FileOutputStream fos = new FileOutputStream("temp1.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos)) { + ObjectStreamClass osc = + ObjectStreamClass.lookup(MySerializable.class); + oos.writeObject(osc); + } + } else if (args.length > 0 && args[0].equals("deserialize")) { + try (FileInputStream fis = new FileInputStream("temp1.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + FileOutputStream fos = new FileOutputStream("temp2.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos) { + /*must be subclassed*/}) { + ObjectStreamClass osc = (ObjectStreamClass)ois.readObject(); + // serialize it again + try { + oos.writeObject(osc); + } catch (NullPointerException e) { + throw new RuntimeException("Failed to write" + + " unresolvable ObjectStreamClass", e); + } + } + } else { + throw new RuntimeException("The command line option must be" + + " one of: serialize or deserialize"); + } + } +} + +class MySerializable implements Serializable { +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java --- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java Wed Jul 05 19:37:43 2017 +0200 @@ -30,11 +30,9 @@ * * @author Mandy Chung * - * @build CollectionUsageThreshold MemoryUtil - * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseSerialGC CollectionUsageThreshold - * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseParallelGC CollectionUsageThreshold - * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseG1GC CollectionUsageThreshold - * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC CollectionUsageThreshold + * @library /lib/testlibrary/ + * @build CollectionUsageThreshold MemoryUtil RunUtil + * @run main/timeout=300 CollectionUsageThreshold */ import java.util.*; @@ -61,6 +59,20 @@ // finishes checking the low memory notification result private static final CyclicBarrier barrier = new CyclicBarrier(2); + /** + * Run the test multiple times with different GC versions. + * First with default command line specified by the framework. + * Then with GC versions specified by the test. + */ + public static void main(String a[]) throws Throwable { + final String main = "CollectionUsageThreshold$TestMain"; + RunUtil.runTestKeepGcOpts(main); + RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC"); + } + static class PoolRecord { private final MemoryPoolMXBean pool; private final AtomicInteger listenerInvoked = new AtomicInteger(0); @@ -110,88 +122,90 @@ } } - public static void main(String args[]) throws Exception { - if (args.length > 0 && args[0].equals("trace")) { - trace = true; - } + private static class TestMain { + public static void main(String args[]) throws Exception { + if (args.length > 0 && args[0].equals("trace")) { + trace = true; + } - List pools = getMemoryPoolMXBeans(); - List managers = getMemoryManagerMXBeans(); + List pools = getMemoryPoolMXBeans(); + List managers = getMemoryManagerMXBeans(); - if (trace) { - MemoryUtil.printMemoryPools(pools); - MemoryUtil.printMemoryManagers(managers); - } + if (trace) { + MemoryUtil.printMemoryPools(pools); + MemoryUtil.printMemoryManagers(managers); + } - // Find the Old generation which supports low memory detection - for (MemoryPoolMXBean p : pools) { - if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) { - if (p.getName().toLowerCase().contains("perm")) { - // if we have a "perm gen" pool increase the number of expected - // memory pools by one. - numMemoryPools++; - } - PoolRecord pr = new PoolRecord(p); - result.put(p.getName(), pr); - if (result.size() == numMemoryPools) { - break; + // Find the Old generation which supports low memory detection + for (MemoryPoolMXBean p : pools) { + if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) { + if (p.getName().toLowerCase().contains("perm")) { + // if we have a "perm gen" pool increase the number of expected + // memory pools by one. + numMemoryPools++; + } + PoolRecord pr = new PoolRecord(p); + result.put(p.getName(), pr); + if (result.size() == numMemoryPools) { + break; + } } } - } - if (result.size() != numMemoryPools) { - throw new RuntimeException("Unexpected number of selected pools"); + if (result.size() != numMemoryPools) { + throw new RuntimeException("Unexpected number of selected pools"); + } + + try { + // This test creates a checker thread responsible for checking + // the low memory notifications. It blocks until a permit + // from the signals semaphore is available. + Checker checker = new Checker("Checker thread"); + checker.setDaemon(true); + checker.start(); + + for (PoolRecord pr : result.values()) { + pr.getPool().setCollectionUsageThreshold(THRESHOLD); + System.out.println("Collection usage threshold of " + + pr.getPool().getName() + " set to " + THRESHOLD); + } + + SensorListener listener = new SensorListener(); + NotificationEmitter emitter = (NotificationEmitter) mm; + emitter.addNotificationListener(listener, null, null); + + // The main thread invokes GC to trigger the VM to perform + // low memory detection and then waits until the checker thread + // finishes its work to check for a low-memory notification. + // + // At GC time, VM will issue low-memory notification and invoke + // the listener which will release a permit to the signals semaphore. + // When the checker thread acquires the permit and finishes + // checking the low-memory notification, it will also call + // barrier.await() to signal the main thread to resume its work. + for (int i = 0; i < NUM_GCS; i++) { + invokeGC(); + barrier.await(); + } + } finally { + // restore the default + for (PoolRecord pr : result.values()) { + pr.getPool().setCollectionUsageThreshold(0); + } + } + System.out.println(RunUtil.successMessage); } - try { - // This test creates a checker thread responsible for checking - // the low memory notifications. It blocks until a permit - // from the signals semaphore is available. - Checker checker = new Checker("Checker thread"); - checker.setDaemon(true); - checker.start(); - for (PoolRecord pr : result.values()) { - pr.getPool().setCollectionUsageThreshold(THRESHOLD); - System.out.println("Collection usage threshold of " + - pr.getPool().getName() + " set to " + THRESHOLD); - } - - SensorListener listener = new SensorListener(); - NotificationEmitter emitter = (NotificationEmitter) mm; - emitter.addNotificationListener(listener, null, null); + private static void invokeGC() { + System.out.println("Calling System.gc()"); + numGCs++; + mm.gc(); - // The main thread invokes GC to trigger the VM to perform - // low memory detection and then waits until the checker thread - // finishes its work to check for a low-memory notification. - // - // At GC time, VM will issue low-memory notification and invoke - // the listener which will release a permit to the signals semaphore. - // When the checker thread acquires the permit and finishes - // checking the low-memory notification, it will also call - // barrier.await() to signal the main thread to resume its work. - for (int i = 0; i < NUM_GCS; i++) { - invokeGC(); - barrier.await(); - } - } finally { - // restore the default - for (PoolRecord pr : result.values()) { - pr.getPool().setCollectionUsageThreshold(0); - } - } - System.out.println("Test passed."); - } - - - private static void invokeGC() { - System.out.println("Calling System.gc()"); - numGCs++; - mm.gc(); - - if (trace) { - for (PoolRecord pr : result.values()) { - System.out.println("Usage after GC for: " + pr.getPool().getName()); - MemoryUtil.printMemoryUsage(pr.getPool().getUsage()); + if (trace) { + for (PoolRecord pr : result.values()) { + System.out.println("Usage after GC for: " + pr.getPool().getName()); + MemoryUtil.printMemoryUsage(pr.getPool().getUsage()); + } } } } diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java --- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Wed Jul 05 19:37:43 2017 +0200 @@ -30,11 +30,9 @@ * * @author Mandy Chung * - * @build LowMemoryTest MemoryUtil - * @run main/othervm/timeout=600 LowMemoryTest - * @run main/othervm/timeout=600 -XX:+UseConcMarkSweepGC LowMemoryTest - * @run main/othervm/timeout=600 -XX:+UseParallelGC LowMemoryTest - * @run main/othervm/timeout=600 -XX:+UseSerialGC LowMemoryTest + * @library /lib/testlibrary/ + * @build LowMemoryTest MemoryUtil RunUtil + * @run main/timeout=600 LowMemoryTest */ import java.lang.management.*; @@ -54,6 +52,20 @@ private static final int NUM_CHUNKS = 2; private static long chunkSize; + /** + * Run the test multiple times with different GC versions. + * First with default command line specified by the framework. + * Then with GC versions specified by the test. + */ + public static void main(String a[]) throws Throwable { + final String main = "LowMemoryTest$TestMain"; + RunUtil.runTestKeepGcOpts(main); + RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC"); + RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC"); + } + private static volatile boolean listenerInvoked = false; static class SensorListener implements NotificationListener { @Override @@ -107,77 +119,80 @@ } private static long newThreshold; - public static void main(String args[]) throws Exception { - if (args.length > 0 && args[0].equals("trace")) { - trace = true; - } - // Find the Old generation which supports low memory detection - ListIterator iter = pools.listIterator(); - while (iter.hasNext()) { - MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); - if (p.getType() == MemoryType.HEAP && - p.isUsageThresholdSupported()) { - mpool = p; - if (trace) { - System.out.println("Selected memory pool for low memory " + - "detection."); - MemoryUtil.printMemoryPool(mpool); - } - break; + private static class TestMain { + public static void main(String args[]) throws Exception { + if (args.length > 0 && args[0].equals("trace")) { + trace = true; } - } - TestListener listener = new TestListener(); - SensorListener l2 = new SensorListener(); - NotificationEmitter emitter = (NotificationEmitter) mm; - emitter.addNotificationListener(listener, null, null); - emitter.addNotificationListener(l2, null, null); - - Thread allocator = new AllocatorThread(); - Thread sweeper = new SweeperThread(); + // Find the Old generation which supports low memory detection + ListIterator iter = pools.listIterator(); + while (iter.hasNext()) { + MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); + if (p.getType() == MemoryType.HEAP && + p.isUsageThresholdSupported()) { + mpool = p; + if (trace) { + System.out.println("Selected memory pool for low memory " + + "detection."); + MemoryUtil.printMemoryPool(mpool); + } + break; + } + } - // Now set threshold - MemoryUsage mu = mpool.getUsage(); - chunkSize = (mu.getMax() - mu.getUsed()) / 20; - newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS); + TestListener listener = new TestListener(); + SensorListener l2 = new SensorListener(); + NotificationEmitter emitter = (NotificationEmitter) mm; + emitter.addNotificationListener(listener, null, null); + emitter.addNotificationListener(l2, null, null); + + Thread allocator = new AllocatorThread(); + Thread sweeper = new SweeperThread(); - System.out.println("Setting threshold for " + mpool.getName() + - " from " + mpool.getUsageThreshold() + " to " + newThreshold + - ". Current used = " + mu.getUsed()); - mpool.setUsageThreshold(newThreshold); + // Now set threshold + MemoryUsage mu = mpool.getUsage(); + chunkSize = (mu.getMax() - mu.getUsed()) / 20; + newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS); - if (mpool.getUsageThreshold() != newThreshold) { - throw new RuntimeException("TEST FAILED: " + + System.out.println("Setting threshold for " + mpool.getName() + + " from " + mpool.getUsageThreshold() + " to " + newThreshold + + ". Current used = " + mu.getUsed()); + mpool.setUsageThreshold(newThreshold); + + if (mpool.getUsageThreshold() != newThreshold) { + throw new RuntimeException("TEST FAILED: " + "Threshold for Memory pool " + mpool.getName() + "is " + mpool.getUsageThreshold() + " but expected to be" + newThreshold); - } + } - allocator.start(); - // Force Allocator start first - phaser.arriveAndAwaitAdvance(); - sweeper.start(); + allocator.start(); + // Force Allocator start first + phaser.arriveAndAwaitAdvance(); + sweeper.start(); - try { - allocator.join(); - // Wait until AllocatorThread's done - phaser.arriveAndAwaitAdvance(); - sweeper.join(); - } catch (InterruptedException e) { - System.out.println("Unexpected exception:" + e); - testFailed = true; + try { + allocator.join(); + // Wait until AllocatorThread's done + phaser.arriveAndAwaitAdvance(); + sweeper.join(); + } catch (InterruptedException e) { + System.out.println("Unexpected exception:" + e); + testFailed = true; + } + + listener.checkResult(); + + if (testFailed) + throw new RuntimeException("TEST FAILED."); + + System.out.println(RunUtil.successMessage); + } - - listener.checkResult(); - - if (testFailed) - throw new RuntimeException("TEST FAILED."); - - System.out.println("Test passed."); - } private static void goSleep(long ms) { diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java --- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Wed Jul 05 19:37:43 2017 +0200 @@ -32,11 +32,9 @@ * @summary Basic Test for MemoryPool.resetPeakUsage() * @author Mandy Chung * - * @build ResetPeakMemoryUsage MemoryUtil - * @run main/othervm -XX:+PrintGCDetails -XX:+UseSerialGC -Xms256m -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage - * @run main/othervm -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -Xms256m -Xmn8m ResetPeakMemoryUsage - * @run main/othervm -XX:+PrintGCDetails -XX:+UseParallelGC -Xms256m -Xmn8m ResetPeakMemoryUsage - * @run main/othervm -XX:+PrintGCDetails -XX:+UseG1GC -Xms256m -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage + * @library /lib/testlibrary/ + * @build ResetPeakMemoryUsage MemoryUtil RunUtil + * @run main ResetPeakMemoryUsage */ import java.lang.management.*; @@ -47,24 +45,42 @@ // make public so that it can't be optimized away easily public static Object[] obj; - public static void main(String[] argv) { - List pools = ManagementFactory.getMemoryPoolMXBeans(); - ListIterator iter = pools.listIterator(); - boolean found = false; - while (iter.hasNext()) { - MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); - // only check heap pools that support usage threshold - // this is typically only the old generation space - // since the other spaces are expected to get filled up - if (p.getType() == MemoryType.HEAP && - p.isUsageThresholdSupported()) - { - found = true; - testPool(p); + /** + * Run the test multiple times with different GC versions. + * First with default command line specified by the framework. + * Then with all GC versions specified by the test. + */ + public static void main(String a[]) throws Throwable { + final String main = "ResetPeakMemoryUsage$TestMain"; + final String ms = "-Xms256m"; + final String mn = "-Xmn8m"; + RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC"); + RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseParallelGC"); + RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1m"); + RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseSerialGC", + "-XX:MarkSweepAlwaysCompactCount=1"); + } + + private static class TestMain { + public static void main(String[] argv) { + List pools = ManagementFactory.getMemoryPoolMXBeans(); + ListIterator iter = pools.listIterator(); + boolean found = false; + while (iter.hasNext()) { + MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); + // only check heap pools that support usage threshold + // this is typically only the old generation space + // since the other spaces are expected to get filled up + if (p.getType() == MemoryType.HEAP && + p.isUsageThresholdSupported()) + { + found = true; + testPool(p); + } } - } - if (!found) { - throw new RuntimeException("No heap pool found"); + if (!found) { + throw new RuntimeException("No heap pool found"); + } } } @@ -142,7 +158,7 @@ formatSize("previous peak", peak2.getUsed())); } - System.out.println("Test passed."); + System.out.println(RunUtil.successMessage); } private static String INDENT = " "; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/lang/management/MemoryMXBean/RunUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/management/MemoryMXBean/RunUtil.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,84 @@ +/* + * 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. + */ + +/** + * Utility class for launching a test in a separate JVM. + */ + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.Utils; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.JDKToolFinder; + +public class RunUtil { + + // Used to mark that the test has passed successfully. + public static final String successMessage = "Test passed."; + + public static void runTestClearGcOpts(String main, String... testOpts) throws Throwable { + runTest(main, true, testOpts); + } + + public static void runTestKeepGcOpts(String main, String... testOpts) throws Throwable { + runTest(main, false, testOpts); + } + + /** + * Runs a test in a separate JVM. + * command line like: + * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main + * + * {defaultopts} are the default java options set by the framework. + * Default GC options in {defaultopts} may be removed. + * This is used when the test specifies its own GC options. + * + * @param main Name of the main class. + * @param clearGcOpts true if the default GC options should be removed. + * @param testOpts java options specified by the test. + */ + private static void runTest(String main, boolean clearGcOpts, String... testOpts) + throws Throwable { + List opts = new ArrayList<>(); + opts.add(JDKToolFinder.getJDKTool("java")); + opts.addAll(Arrays.asList(Utils.getTestJavaOpts())); + opts.add("-cp"); + opts.add(System.getProperty("test.class.path", "test.class.path")); + opts.add("-XX:+PrintGCDetails"); + + if (clearGcOpts) { + opts = Utils.removeGcOpts(opts); + } + opts.addAll(Arrays.asList(testOpts)); + opts.add(main); + + OutputAnalyzer output = ProcessTools.executeProcess(opts.toArray(new String[0])); + output.shouldHaveExitValue(0); + if (output.getStdout().indexOf(successMessage) < 0) { + throw new Exception("output missing '" + successMessage + "'"); + } + } + +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/net/SocketOption/OptionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/SocketOption/OptionsTest.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,244 @@ +/* + * 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 8036979 + * @run main/othervm -Xcheck:jni OptionsTest + */ + +import java.net.*; +import java.util.*; + +public class OptionsTest { + + static class Test { + Test(SocketOption option, Object testValue) { + this.option = option; + this.testValue = testValue; + } + static Test create (SocketOption option, Object testValue) { + return new Test(option, testValue); + } + Object option; + Object testValue; + }; + + // The tests set the option using the new API, read back the set value + // which could be diferent, and then use the legacy get API to check + // these values are the same + + static Test[] socketTests = new Test[] { + Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE), + Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), + Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), + Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), + Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) + }; + + static Test[] serverSocketTests = new Test[] { + Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), + Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE) + }; + + static Test[] dgSocketTests = new Test[] { + Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), + Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), + Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) + }; + + static Test[] mcSocketTests = new Test[] { + Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()), + Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)), + Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE) + }; + + static NetworkInterface getNetworkInterface() { + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + if (nifs.hasMoreElements()) { + return (NetworkInterface)nifs.nextElement(); + } + } catch (Exception e) { + } + return null; + } + + static void doSocketTests() throws Exception { + try ( + ServerSocket srv = new ServerSocket(0); + Socket c = new Socket("127.0.0.1", srv.getLocalPort()); + Socket s = srv.accept(); + ) { + for (int i=0; i type, Object s, Object option) + + throws Exception + { + if (type.equals(Socket.class)) { + Socket socket = (Socket)s; + + if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) { + return Boolean.valueOf(socket.getKeepAlive()); + } else if (option.equals(StandardSocketOptions.SO_SNDBUF)) { + return Integer.valueOf(socket.getSendBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { + return Integer.valueOf(socket.getReceiveBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { + return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_LINGER)) { + return Integer.valueOf(socket.getSoLinger()); + } else if (option.equals(StandardSocketOptions.IP_TOS)) { + return Integer.valueOf(socket.getTrafficClass()); + } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) { + return Boolean.valueOf(socket.getTcpNoDelay()); + } else { + throw new RuntimeException("unexecpted socket option"); + } + } else if (type.equals(ServerSocket.class)) { + ServerSocket socket = (ServerSocket)s; + if (option.equals(StandardSocketOptions.SO_RCVBUF)) { + return Integer.valueOf(socket.getReceiveBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { + return Boolean.valueOf(socket.getReuseAddress()); + } else { + throw new RuntimeException("unexecpted socket option"); + } + } else if (type.equals(DatagramSocket.class)) { + DatagramSocket socket = (DatagramSocket)s; + + if (option.equals(StandardSocketOptions.SO_SNDBUF)) { + return Integer.valueOf(socket.getSendBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { + return Integer.valueOf(socket.getReceiveBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { + return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.IP_TOS)) { + return Integer.valueOf(socket.getTrafficClass()); + } else { + throw new RuntimeException("unexecpted socket option"); + } + + } else if (type.equals(MulticastSocket.class)) { + MulticastSocket socket = (MulticastSocket)s; + + if (option.equals(StandardSocketOptions.SO_SNDBUF)) { + return Integer.valueOf(socket.getSendBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { + return Integer.valueOf(socket.getReceiveBufferSize()); + } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { + return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.IP_TOS)) { + return Integer.valueOf(socket.getTrafficClass()); + } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) { + return socket.getNetworkInterface(); + } else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) { + return Integer.valueOf(socket.getTimeToLive()); + } else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) { + return Boolean.valueOf(socket.getLoopbackMode()); + } else { + throw new RuntimeException("unexecpted socket option"); + } + } + throw new RuntimeException("unexecpted socket type"); + } + + public static void main(String args[]) throws Exception { + doSocketTests(); + doServerSocketTests(); + doDgSocketTests(); + doMcSocketTests(); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/net/URLPermission/nstest/lookup.sh --- a/jdk/test/java/net/URLPermission/nstest/lookup.sh Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/java/net/URLPermission/nstest/lookup.sh Wed Jul 05 19:37:43 2017 +0200 @@ -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 # diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/java/security/Provider/NewInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/Provider/NewInstance.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,65 @@ +/* + * 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 set = p.getServices(); + Iterator 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)) { + // Some engines require certain parameters to be + // present on creation. Calling newInstance(null) will + // trigger this exception and it's OK. + throw e; + } + } + } + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/javax/imageio/plugins/jpeg/TruncatedImageWarningTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/imageio/plugins/jpeg/TruncatedImageWarningTest.java Wed Jul 05 19:37:43 2017 +0200 @@ -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; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/javax/imageio/plugins/jpeg/truncated.jpg Binary file jdk/test/javax/imageio/plugins/jpeg/truncated.jpg has changed diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/javax/xml/crypto/dsig/GenerationTests.java --- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java Wed Jul 05 19:37:43 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 4635230 6283345 6303830 6824440 6867348 7094155 + * @bug 4635230 6283345 6303830 6824440 6867348 7094155 8038184 * @summary Basic unit tests for generating XML Signatures with JSR 105 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java * X509KeySelector.java GenerationTests.java @@ -135,6 +135,7 @@ test_create_signature_enveloping_sha512_rsa_sha512(); test_create_signature_reference_dependency(); test_create_signature_with_attr_in_no_namespace(); + test_create_signature_with_empty_id(); } private static void setup() throws Exception { @@ -509,6 +510,30 @@ System.out.println(); } + static void test_create_signature_with_empty_id() throws Exception { + System.out.println("* Generating signature-with-empty-id.xml"); + + // create references + List refs = Collections.singletonList + (fac.newReference("#", sha1)); + + // create SignedInfo + SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs); + + // create object with empty id + Document doc = db.newDocument(); + XMLObject obj = fac.newXMLObject(Collections.singletonList + (new DOMStructure(doc.createTextNode("I am the text."))), + "", "text/plain", null); + + // create XMLSignature + XMLSignature sig = fac.newXMLSignature(si, rsa, + Collections.singletonList(obj), + "signature", null); + DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc); + sig.sign(dsc); + } + static void test_create_signature() throws Exception { System.out.println("* Generating signature.xml"); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/net/Sockets/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/net/Sockets/Test.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,130 @@ +/* + * 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 8032808 + * @run main/othervm -Xcheck:jni Test + * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail + * @run main/othervm/policy=policy.success -Xcheck:jni Test success + */ + +import java.net.*; +import java.nio.channels.*; +import java.util.concurrent.*; +import jdk.net.*; + +public class Test { + + static boolean security; + static boolean success; + + interface Runner { + public void run() throws Exception; + } + + public static void main(String[] args) throws Exception { + + // quick check to see if supportedOptions() working before + // creating any sockets and libnet loaded + + Sockets.supportedOptions(Socket.class); + + security = System.getSecurityManager() != null; + success = security && args[0].equals("success"); + + // Main thing is to check for JNI problems + // Doesn't matter if current system does not support the option + // and currently setting the option with the loopback interface + // doesn't work either + + System.out.println ("Security Manager enabled: " + security); + if (security) { + System.out.println ("Success expected: " + success); + } + + final SocketFlow flowIn = SocketFlow.create() + .bandwidth(1000) + .priority(SocketFlow.HIGH_PRIORITY); + + ServerSocket ss = new ServerSocket(0); + int tcp_port = ss.getLocalPort(); + final InetAddress loop = InetAddress.getByName("127.0.0.1"); + final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port); + + DatagramSocket dg = new DatagramSocket(0); + final int udp_port = dg.getLocalPort(); + + final Socket s = new Socket("127.0.0.1", tcp_port); + final SocketChannel sc = SocketChannel.open(); + sc.connect (new InetSocketAddress("127.0.0.1", tcp_port)); + + doTest(()->{ + Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + doTest(()->{ + Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + }); + doTest(()->{ + sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + doTest(()->{ + sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA); + }); + doTest(()->{ + DatagramSocket dg1 = new DatagramSocket(0); + dg1.connect(loop, udp_port); + Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + doTest(()->{ + DatagramChannel dg2 = DatagramChannel.open(); + dg2.bind(new InetSocketAddress(loop, 0)); + dg2.connect(new InetSocketAddress(loop, udp_port)); + dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + doTest(()->{ + MulticastSocket mc1 = new MulticastSocket(0); + mc1.connect(loop, udp_port); + Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + doTest(()->{ + AsynchronousSocketChannel asc = AsynchronousSocketChannel.open(); + Future f = asc.connect(loopad); + f.get(); + asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + }); + } + + static void doTest(Runner func) throws Exception { + try { + func.run(); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/net/Sockets/policy.fail --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/net/Sockets/policy.fail Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,4 @@ +grant { + permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; + permission java.net.SocketPermission "localhost", "listen" ; +}; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/net/Sockets/policy.success --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/net/Sockets/policy.success Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,6 @@ +grant { + permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; + permission java.net.SocketPermission "localhost", "listen" ; + permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA"; + permission jdk.net.NetworkPermission "getOption.SO_FLOW_SLA"; +}; diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/nio/zipfs/Basic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/nio/zipfs/Basic.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 env = new HashMap(); + 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 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 { + private int indent = 0; + + private void indent() { + StringBuilder sb = new StringBuilder(indent); + for (int i=0; i + // rename entry src to dst inside zipfile + + movein, // + // move an external src file into zipfile + // as entry dst + + moveout, // + // move a zipfile entry src out to dst + + copy, // + // copy entry src to dst inside zipfile + + copyin, // + // copy an external src file into zipfile + // as entry dst + + copyin_attrs, // + // copy an external src file into zipfile + // as entry dst, with attributes (timestamp) + + copyout, // + // copy zipfile entry src" out to file dst + + copyout_attrs, // + + zzmove, // + // move entry path/dir from zfsrc to zfdst + + zzcopy, // + // copy path from zipfile zfsrc to zipfile + // zfdst + + attrs, // + // printout the attributes of entry path + + attrsspace, // + // printout the storespace attrs of entry path + + setmtime, // + // set the lastModifiedTime of entry path + + setatime, // + setctime, // + + lsdir, // + // list dir's direct child files/dirs + + mkdir, // + + mkdirs, // + + rmdirs, // + + list, // + // recursively list all entries of dir + // via DirectoryStream + + tlist, // + // list with buildDirTree=true + + vlist, // + // recursively verbose list all entries of + // dir via DirectoryStream + + walk, // + // recursively walk all entries of dir + // via Files.walkFileTree + + twalk, // + // walk with buildDirTree=true + + extract, // + + update, // + + delete, // + + add, // + + create, // + // create a new zipfile if it doesn't exit + // and then add the file(s) into it. + + attrs2, // + // 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 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 ds = Files.newDirectoryStream(path, + new DirectoryStream.Filter() { + @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 map = Files.readAttributes(path, "zip:*"); + for (Map.Entry 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 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() { + 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 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 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 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() { + + @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 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 read = new HashSet<>(); + read.add(READ); + Set 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 read = new HashSet<>(); + read.add(READ); + Set 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); + } + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/nio/zipfs/PathOps.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/nio/zipfs/PathOps.java Wed Jul 05 19:37:43 2017 +0200 @@ -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(); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/nio/zipfs/ZFSTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java Wed Jul 05 19:37:43 2017 +0200 @@ -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 env = new HashMap(); + env.put("create", "true"); + try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {} + } finally { + Files.deleteIfExists(path); + Files.deleteIfExists(dir); + } + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/jdk/nio/zipfs/ZipFSTester.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java Wed Jul 05 19:37:43 2017 +0200 @@ -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())) + { + 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 list = new LinkedList<>(); + try (ZipFile zf = new ZipFile(fs.toString())) { + Enumeration 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 env = new HashMap(); + env.put("create", "true"); + try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) { + z2zcopy(fs0, copy, "/", 0); + } + + try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap())) { + + FileSystemProvider provider = fs.provider(); + // newFileSystem(path...) should not throw exception + try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap())){} + try (FileSystem fsUri = provider.newFileSystem( + new URI("jar", tmpfsPath.toUri().toString(), null), + new HashMap())) + { + 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()); + throw new RuntimeException("newFileSystem() opens a directory as zipfs"); + } catch (UnsupportedOperationException uoe) {} + + try { + provider.newFileSystem(src, new HashMap()); + 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 env = new HashMap(); + 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(); + final FileSystem fs1 = newZipFileSystem(fs1Path, env); + + System.out.println("listing..."); + final ArrayList files = new ArrayList<>(); + final ArrayList dirs = new ArrayList<>(); + list(fs1.getPath("/"), files, dirs); + + Thread t0 = new Thread(new Runnable() { + public void run() { + List 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 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 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 list = new ArrayList<>(files); + Collections.shuffle(list); + while (!list.isEmpty()) { + Iterator 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 files2 = new ArrayList<>(); + ArrayList 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 env = new HashMap(); + 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 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 files, List dirs ) + throws IOException + { + if (Files.isDirectory(path)) { + try (DirectoryStream 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 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 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() { + 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 read = new HashSet<>(); + read.add(READ); + Set 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 read = new HashSet<>(); + read.add(READ); + Set 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 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; + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java --- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Wed Jul 05 19:37:43 2017 +0200 @@ -120,6 +120,26 @@ } /** + * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". + * Removes any options matching: -XX:(+/-)Use*GC + * Used when a test need to set its own GC version. Then any + * GC specified by the framework must first be removed. + * @return A copy of given opts with all GC options removed. + */ + private static final Pattern useGcPattern = Pattern.compile("\\-XX\\:[\\+\\-]Use.+GC"); + public static List removeGcOpts(List opts) { + List optsWithoutGC = new ArrayList(); + for (String opt : opts) { + if (useGcPattern.matcher(opt).matches()) { + System.out.println("removeGcOpts: removed " + opt); + } else { + optsWithoutGC.add(opt); + } + } + return optsWithoutGC; + } + + /** * Splits a string by white space. * Works like String.split(), but returns an empty array * if the string is null or empty. diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/sun/nio/cs/TestUTF8.java --- a/jdk/test/sun/nio/cs/TestUTF8.java Thu Apr 17 15:23:23 2014 -0700 +++ b/jdk/test/sun/nio/cs/TestUTF8.java Wed Jul 05 19:37:43 2017 +0200 @@ -23,7 +23,7 @@ /* * @test - * @bug 4486841 7040220 7096080 + * @bug 4486841 7040220 7096080 8039751 * @summary Test UTF-8 charset */ @@ -291,14 +291,18 @@ {1, (byte)0xE0, (byte)0xC0, (byte)0xBF }, // invalid second byte {2, (byte)0xE0, (byte)0xA0, (byte)0x7F }, // invalid third byte {2, (byte)0xE0, (byte)0xA0, (byte)0xC0 }, // invalid third byte + {2, (byte)0xE1, (byte)0x80, (byte)0x42}, // invalid third byte + {1, (byte)0xFF, (byte)0xFF, (byte)0xFF }, // all ones {1, (byte)0xE0, (byte)0xC0, (byte)0x80 }, // invalid second byte {1, (byte)0xE0, (byte)0x80, (byte)0xC0 }, // invalid first byte {1, (byte)0xE0, (byte)0x41,}, // invalid second byte & 2 bytes + {1, (byte)0xE1, (byte)0x40,}, // invalid second byte & 2 bytes {3, (byte)0xED, (byte)0xAE, (byte)0x80 }, // 3 bytes surrogate {3, (byte)0xED, (byte)0xB0, (byte)0x80 }, // 3 bytes surrogate + // Four-byte sequences {1, (byte)0xF0, (byte)0x80, (byte)0x80, (byte)0x80 }, // U+0000 zero-padded {1, (byte)0xF0, (byte)0x80, (byte)0x81, (byte)0xBF }, // U+007F zero-padded @@ -323,6 +327,32 @@ {1, (byte)0xF4, (byte)0xC0, (byte)0x80, (byte)0xC0 }, // out-range 4-byte {1, (byte)0xF5, (byte)0x80, (byte)0x80, (byte)0xC0 }, // out-range 4-byte + // #8039751 + {1, (byte)0xF6, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 1st byte + {1, (byte)0xF6, (byte)0x80, (byte)0x80, }, + {1, (byte)0xF6, (byte)0x80, }, + {1, (byte)0xF6, }, + {1, (byte)0xF5, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 1st byte + {1, (byte)0xF5, (byte)0x80, (byte)0x80, }, + {1, (byte)0xF5, (byte)0x80, }, + {1, (byte)0xF5 }, + + {1, (byte)0xF4, (byte)0x90, (byte)0x80, (byte)0x80 }, // out-range 2nd byte + {1, (byte)0xF4, (byte)0x90, (byte)0x80 }, + {1, (byte)0xF4, (byte)0x90 }, + + {1, (byte)0xF4, (byte)0x7f, (byte)0x80, (byte)0x80 }, // out-range/ascii 2nd byte + {1, (byte)0xF4, (byte)0x7f, (byte)0x80 }, + {1, (byte)0xF4, (byte)0x7f }, + + {1, (byte)0xF0, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 2nd byte + {1, (byte)0xF0, (byte)0x80, (byte)0x80 }, + {1, (byte)0xF0, (byte)0x80 }, + + {1, (byte)0xF0, (byte)0xc0, (byte)0x80, (byte)0x80 }, // out-range 2nd byte + {1, (byte)0xF0, (byte)0xc0, (byte)0x80 }, + {1, (byte)0xF0, (byte)0xc0 }, + // Five-byte sequences {1, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80}, // invalid first byte {1, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80 }, // U+0000 zero-padded @@ -553,7 +583,6 @@ check4ByteSurrs("UTF-8"); checkMalformed("UTF-8", malformed); checkUnderOverflow("UTF-8"); - checkRoundtrip("CESU-8"); check6ByteSurrs("CESU-8"); checkMalformed("CESU-8", malformed_cesu8); diff -r 16ec7c58cdea -r cb2cf6e2958a jdk/test/sun/tools/jinfo/JInfoLauncherTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,342 @@ +/* + * 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. + */ + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeClass; +import sun.tools.jinfo.JInfo; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Arrays; + +import static org.testng.Assert.*; + +/** + * @test + * @bug 8039080 + * @run testng JInfoLauncherTest + * @summary Test JInfo launcher argument parsing + */ +@Test +public class JInfoLauncherTest { + public static final String VALIDATION_EXCEPTION_CLSNAME = + IllegalArgumentException.class.getName(); + + private Constructor jInfoConstructor; + private Field fldUseSA; + + @BeforeClass + public void setup() throws Exception { + jInfoConstructor = JInfo.class.getDeclaredConstructor(String[].class); + jInfoConstructor.setAccessible(true); + fldUseSA = JInfo.class.getDeclaredField("useSA"); + fldUseSA.setAccessible(true); + } + + private JInfo newJInfo(String[] args) throws Exception { + try { + return jInfoConstructor.newInstance((Object) args); + } catch (Exception e) { + if (isValidationException(e.getCause())) { + throw (Exception)e.getCause(); + } + throw e; + } + } + + private boolean getUseSA(JInfo jinfo) throws Exception { + return fldUseSA.getBoolean(jinfo); + } + + private void cmdPID(String cmd, String ... params) throws Exception { + int offset = (cmd != null ? 1 : 0); + String[] args = new String[offset + params.length]; + args[0] = cmd; + System.arraycopy(params, 0, args, offset, params.length); + JInfo j = newJInfo(args); + assertFalse(getUseSA(j), "Local jinfo must not forward to SA"); + } + + private void cmdCore(String cmd, String ... params) throws Exception { + int offset = (cmd != null ? 1 : 0); + String[] args = new String[offset + params.length]; + args[0] = cmd; + System.arraycopy(params, 0, args, offset, params.length); + JInfo j = newJInfo(args); + assertTrue(getUseSA(j), "Core jinfo must forward to SA"); + } + + private void cmdRemote(String cmd, String ... params) throws Exception { + int offset = (cmd != null ? 1 : 0); + String[] args = new String[offset + params.length]; + args[0] = cmd; + System.arraycopy(params, 0, args, offset, params.length); + JInfo j = newJInfo(args); + assertTrue(getUseSA(j), "Remote jinfo must forward to SA"); + } + + private void cmdExtraArgs(String cmd, int argsLen) throws Exception { + String[] args = new String[argsLen + 1 + (cmd != null ? 1 : 0)]; + Arrays.fill(args, "a"); + if (cmd != null) { + args[0] = cmd; + } else { + cmd = "default"; + } + try { + JInfo j = newJInfo(args); + fail("\"" + cmd + "\" does not support more than " + argsLen + + " arguments"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + private void cmdMissingArgs(String cmd, int reqArgs) throws Exception { + String[] args = new String[reqArgs - 1 + (cmd != null ? 1 : 0)]; + Arrays.fill(args, "a"); + if (cmd != null) { + args[0] = cmd; + } else { + cmd = "default"; + } + try { + JInfo j = newJInfo(args); + fail("\"" + cmd + "\" requires at least " + reqArgs + " argument"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testDefaultPID() throws Exception { + cmdPID(null, "1234"); + } + + public void testFlagsPID() throws Exception { + cmdPID("-flags", "1234"); + } + + public void testSyspropsPID() throws Exception { + cmdPID("-sysprops", "1234"); + } + + public void testReadFlagPID() throws Exception { + cmdPID("-flag", "SomeManagementFlag", "1234"); + } + + public void testSetFlag1PID() throws Exception { + cmdPID("-flag", "+SomeManagementFlag", "1234"); + } + + public void testSetFlag2PID() throws Exception { + cmdPID("-flag", "-SomeManagementFlag", "1234"); + } + + public void testSetFlag3PID() throws Exception { + cmdPID("-flag", "SomeManagementFlag=314", "1234"); + } + + public void testDefaultCore() throws Exception { + cmdCore(null, "myapp.exe", "my.core"); + } + + public void testFlagsCore() throws Exception { + cmdCore("-flags", "myapp.exe", "my.core"); + } + + public void testSyspropsCore() throws Exception { + cmdCore("-sysprops", "myapp.exe", "my.core"); + } + + public void testReadFlagCore() throws Exception { + try { + cmdCore("-flag", "SomeManagementFlag", "myapp.exe", "my.core"); + fail("Flags can not be read from core files"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag1Core() throws Exception { + try { + cmdCore("-flag", "+SomeManagementFlag", "myapp.exe", "my.core"); + fail("Flags can not be set in core files"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag2Core() throws Exception { + try { + cmdCore("-flag", "-SomeManagementFlag", "myapp.exe", "my.core"); + fail("Flags can not be set in core files"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag3Core() throws Exception { + try { + cmdCore("-flag", "SomeManagementFlag=314", "myapp.exe", "my.core"); + fail("Flags can not be set in core files"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testDefaultRemote() throws Exception { + cmdRemote(null, "serverid@host"); + } + + public void testFlagsRemote() throws Exception { + cmdRemote("-flags", "serverid@host"); + } + + public void testSyspropsRemote() throws Exception { + cmdRemote("-sysprops", "serverid@host"); + } + + public void testReadFlagRemote() throws Exception { + try { + cmdCore("-flag", "SomeManagementFlag", "serverid@host"); + fail("Flags can not be read from SA server"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag1Remote() throws Exception { + try { + cmdCore("-flag", "+SomeManagementFlag","serverid@host"); + fail("Flags can not be set on SA server"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag2Remote() throws Exception { + try { + cmdCore("-flag", "-SomeManagementFlag", "serverid@host"); + fail("Flags can not be read set on SA server"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testSetFlag3Remote() throws Exception { + try { + cmdCore("-flag", "SomeManagementFlag=314", "serverid@host"); + fail("Flags can not be read set on SA server"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + public void testDefaultExtraArgs() throws Exception { + cmdExtraArgs(null, 2); + } + + public void testFlagsExtraArgs() throws Exception { + cmdExtraArgs("-flags", 2); + } + + public void testSyspropsExtraArgs() throws Exception { + cmdExtraArgs("-sysprops", 2); + } + + public void testFlagExtraArgs() throws Exception { + cmdExtraArgs("-flag", 2); + } + + public void testHelp1ExtraArgs() throws Exception { + cmdExtraArgs("-h", 0); + } + + public void testHelp2ExtraArgs() throws Exception { + cmdExtraArgs("-help", 0); + } + + public void testDefaultMissingArgs() throws Exception { + cmdMissingArgs(null, 1); + } + + public void testFlagsMissingArgs() throws Exception { + cmdMissingArgs("-flags", 1); + } + + public void testSyspropsMissingArgs() throws Exception { + cmdMissingArgs("-sysprops", 1); + } + + public void testFlagMissingArgs() throws Exception { + cmdMissingArgs("-flag", 2); + } + + public void testUnknownCommand() throws Exception { + try { + JInfo j = newJInfo(new String[]{"-unknown_command"}); + fail("JInfo accepts unknown commands"); + } catch (Exception e) { + if (!isValidationException(e)) { + throw e; + } + // ignore + } + } + + private static boolean isValidationException(Throwable e) { + return e.getClass().getName().equals(VALIDATION_EXCEPTION_CLSNAME); + } +} diff -r 16ec7c58cdea -r cb2cf6e2958a make/Javadoc.gmk --- a/make/Javadoc.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/make/Javadoc.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -72,6 +72,7 @@ TREEAPI_FIRST_COPYRIGHT_YEAR = 2005 JNLP_FIRST_COPYRIGHT_YEAR = 1998 PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007 +JDKNET_FIRST_COPYRIGHT_YEAR = 2014 # Oracle name FULL_COMPANY_NAME = Oracle and/or its affiliates @@ -1160,6 +1161,57 @@ ############################################################# # +# jdk.net docs +# + +ALL_OTHER_TARGETS += jdknetdocs + +JDKNET_DOCDIR := $(JRE_API_DOCSDIR)/net/socketoptions/spec +JDKNET2COREAPI := ../../../$(JDKJRE2COREAPI) +JDKNET_DOCTITLE := jdk.net API +JDKNET_WINDOWTITLE := jdk.net API +JDKNET_HEADER := jdk.net API +JDKNET_BOTTOM := $(call CommonBottom,$(JDKNET_FIRST_COPYRIGHT_YEAR)) +JDKNET_PKGS := jdk.net + +JDKNET_INDEX_HTML = $(JDKNET_DOCDIR)/index.html +JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options +JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages + +jdknetdocs: $(JDKNET_INDEX_HTML) + +# Set relative location to core api document root +$(JDKNET_INDEX_HTML): GET2DOCSDIR=$(JDKNET2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(JDKNET_INDEX_HTML): $(JDKNET_OPTIONS_FILE) $(JDKNET_PACKAGES_FILE) coredocs + $(prep-javadoc) + $(call JavadocSummary,$(JDKNET_OPTIONS_FILE),$(JDKNET_PACKAGES_FILE)) + $(JAVADOC_CMD) -d $(@D) \ + @$(JDKNET_OPTIONS_FILE) @$(JDKNET_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JDKNET_OPTIONS_FILE): + $(prep-target) + @($(call OptionOnly,$(COMMON_JAVADOCFLAGS)) ; \ + $(call OptionOnly,-Xdoclint:none) ; \ + $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \ + $(call OptionPair,-encoding,ascii) ; \ + $(call OptionOnly,-nodeprecatedlist) ; \ + $(call OptionPair,-doctitle,$(JDKNET_DOCTITLE)) ; \ + $(call OptionPair,-windowtitle,$(JDKNET_WINDOWTITLE) $(DRAFT_WINTITLE)); \ + $(call OptionPair,-header,$(JDKNET_HEADER)$(DRAFT_HEADER)); \ + $(call OptionPair,-bottom,$(JDKNET_BOTTOM)$(DRAFT_BOTTOM)); \ + $(call OptionTrip,-linkoffline,$(JDKNET2COREAPI),$(COREAPI_DOCSDIR)/); \ + ) >> $@ + +# Create a file with the package names in it +$(JDKNET_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDKNET_PKGS)) + $(prep-target) + $(call PackageFilter,$(JDKNET_PKGS)) + +############################################################# +# # Get a cache of all the directories $(DIRECTORY_CACHE): $(ALL_EXISTING_SOURCE_DIRS) diff -r 16ec7c58cdea -r cb2cf6e2958a make/common/NON_CORE_PKGS.gmk --- a/make/common/NON_CORE_PKGS.gmk Thu Apr 17 15:23:23 2014 -0700 +++ b/make/common/NON_CORE_PKGS.gmk Wed Jul 05 19:37:43 2017 +0200 @@ -94,7 +94,8 @@ com.apple.eio endif -JDK_PKGS = jdk +JDK_PKGS = jdk \ + jdk.net # non-core packages in rt.jar NON_CORE_PKGS = $(DOMAPI_PKGS) \ diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/.hgtags --- a/nashorn/.hgtags Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/.hgtags Wed Jul 05 19:37:43 2017 +0200 @@ -242,3 +242,4 @@ 1f75bcbe74e315470dc0b75b7d5bcd209e287c39 jdk9-b06 9a34d2a0a5bdaf0bf0d81d6fe6324aa0cfb35bfe jdk9-b07 4764920fd81d631915b13ba03b5d962ab14a50c4 jdk9-b08 +27f6ea87dcbd52c4b59e34a9f18d5b3321d53fa7 jdk9-b09 diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java --- a/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Wed Jul 05 19:37:43 2017 +0200 @@ -211,7 +211,8 @@ if(!CheckRestrictedPackage.isRestrictedClass(clazz)) { searchSuperTypes = false; for(Method method: clazz.getMethods()) { - if(instance != Modifier.isStatic(method.getModifiers())) { + final boolean isStatic = Modifier.isStatic(method.getModifiers()); + if(instance != isStatic) { final MethodSignature sig = new MethodSignature(method); if(!methods.containsKey(sig)) { final Class declaringClass = method.getDeclaringClass(); @@ -228,7 +229,10 @@ //generate the said synthetic delegators. searchSuperTypes = true; } else { - methods.put(sig, method); + // don't allow inherited static + if (!isStatic || clazz == declaringClass) { + methods.put(sig, method); + } } } } @@ -245,7 +249,8 @@ searchSuperTypes = true; } - if(searchSuperTypes) { + // don't need to search super types for static methods + if(instance && searchSuperTypes) { // If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is // public, but some of its methods claim that their declaring class is non-public. We'll try superclasses // and implemented interfaces then looking for public ones. diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java --- a/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java Wed Jul 05 19:37:43 2017 +0200 @@ -136,7 +136,13 @@ final Field[] fields = clazz.getFields(); final Collection cfields = new ArrayList<>(fields.length); for(Field field: fields) { - if(instance != Modifier.isStatic(field.getModifiers()) && isAccessible(field)) { + final boolean isStatic = Modifier.isStatic(field.getModifiers()); + if(isStatic && clazz != field.getDeclaringClass()) { + // ignore inherited static fields + continue; + } + + if(instance != isStatic && isAccessible(field)) { cfields.add(field); } } diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Jul 05 19:37:43 2017 +0200 @@ -89,6 +89,15 @@ } @Override + protected void setImpl(final int index, final long value) { + if (JSType.isRepresentableAsInt(value)) { + setImpl(index, (int)value); + } else { + buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0; + } + } + + @Override protected void setImpl(final int key, final double value) { setImpl(key, (int)Math.rint(value)); } diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/src/jdk/nashorn/internal/runtime/JSType.java --- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java Wed Jul 05 19:37:43 2017 +0200 @@ -438,7 +438,9 @@ // encode integer part from least significant digit, then reverse do { - sb.append(chars.charAt((int) (intPart % radix))); + final double remainder = intPart % radix; + sb.append(chars.charAt((int) remainder)); + intPart -= remainder; intPart /= radix; } while (intPart >= 1.0); diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Wed Jul 05 19:37:43 2017 +0200 @@ -39,16 +39,38 @@ * Check java reflection permission for java reflective and java.lang.invoke access from scripts */ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{ + private static final Class STATEMENT_CLASS = getBeanClass("Statement"); + private static final Class XMLENCODER_CLASS = getBeanClass("XMLEncoder"); + private static final Class XMLDECODER_CLASS = getBeanClass("XMLDecoder"); + + private static Class getBeanClass(final String name) { + try { + return Class.forName("java.beans." + name); + } catch (final ClassNotFoundException cnfe) { + // Possible to miss this class in other profiles. + return null; + } + } + @Override public boolean canLinkType(final Class type) { return isReflectionClass(type); } private static boolean isReflectionClass(final Class type) { + // Class or ClassLoader subclasses if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) { return true; } + // check for bean reflection + if ((STATEMENT_CLASS != null && STATEMENT_CLASS.isAssignableFrom(type)) || + (XMLENCODER_CLASS != null && XMLENCODER_CLASS.isAssignableFrom(type)) || + (XMLDECODER_CLASS != null && XMLDECODER_CLASS.isAssignableFrom(type))) { + return true; + } + + // package name check final String name = type.getName(); return name.startsWith("java.lang.reflect.") || name.startsWith("java.lang.invoke."); } diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/test/script/basic/JDK-8030199.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8030199.js Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/** + * JDK-8030199: Nashorn: Uint8ClampedArray - Incorrect ToUint8Clamp implementation + * + * @test + * @run + */ + +function testTypedArray(ArrayType) { + print(ArrayType.BYTES_PER_ELEMENT); + var a = new ArrayType(7); + a[0] = 4294967296; + a[1] = -4294967295; + a[2] = 4294967298; + a[3] = -4294967298; + a[4] = Infinity; + a[5] = -Infinity; + a[6] = NaN; + print(Array.prototype.join.call(a)); +} + +testTypedArray(Uint8ClampedArray); +testTypedArray(Uint8Array); +testTypedArray(Int8Array); +testTypedArray(Uint16Array); +testTypedArray(Int16Array); +testTypedArray(Uint32Array); +testTypedArray(Int32Array); diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/test/script/basic/JDK-8030199.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8030199.js.EXPECTED Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,14 @@ +1 +255,0,255,0,255,0,0 +1 +0,1,2,254,0,0,0 +1 +0,1,2,-2,0,0,0 +2 +0,1,2,65534,0,0,0 +2 +0,1,2,-2,0,0,0 +4 +0,1,2,4294967294,0,0,0 +4 +0,1,2,-2,0,0,0 diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/test/script/basic/JDK-8030200.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8030200.js Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * JDK-8030200: Wrong result for Number.prototype.toString() for certain radix/inputs + * + * @test + * @run + */ + +var n = 0x8000000000000800; +print(n); +var s = n.toString(5); +var m = parseInt(s, 5); +print(m === n); +print(n); diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/test/script/basic/JDK-8030200.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8030200.js.EXPECTED Wed Jul 05 19:37:43 2017 +0200 @@ -0,0 +1,3 @@ +9223372036854778000 +true +9223372036854778000 diff -r 16ec7c58cdea -r cb2cf6e2958a nashorn/test/script/basic/NASHORN-173.js.EXPECTED --- a/nashorn/test/script/basic/NASHORN-173.js.EXPECTED Thu Apr 17 15:23:23 2014 -0700 +++ b/nashorn/test/script/basic/NASHORN-173.js.EXPECTED Wed Jul 05 19:37:43 2017 +0200 @@ -132,7 +132,7 @@ 2.3423446609034533e+21 2.3423446609034533e+21 11111101111101010001111111010101101000101011011001001000000000000000000 -2224143002343343220233144213324 +2224143002343343220233044213324 375752177255053311000000 73b92b9962990aa44400 7efa8fead15b240000