From 8e8098cb87a5c9c83d0d1a54d1373b112c4aa460 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 9 Jan 2017 14:14:20 -0800 Subject: [PATCH 01/11] 8172347: Refactoring src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java to improve testability of rmiregistry Reviewed-by: rriggs, msheppar --- .../sun/rmi/registry/RegistryImpl.java | 106 +++++++++++------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java index 49da2249827..03119cc9552 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2017, 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 @@ -362,59 +362,81 @@ public class RegistryImpl extends java.rmi.server.RemoteServer } /** - * Main program to start a registry.
- * The port number can be specified on the command line. + * Return a new RegistryImpl on the requested port and export it to serve + * registry requests. A classloader is initialized from the system property + * "env.class.path" and a security manager is set unless one is already set. + *

+ * The returned Registry is fully functional within the current process and + * is usable for internal and testing purposes. + * + * @param regPort port on which the rmiregistry accepts requests; + * if 0, an implementation specific port is assigned + * @return a RegistryImpl instance + * @exception RemoteException If remote operation failed. + * @since 9 */ - public static void main(String args[]) - { + public static RegistryImpl createRegistry(int regPort) throws RemoteException { // Create and install the security manager if one is not installed // already. if (System.getSecurityManager() == null) { System.setSecurityManager(new SecurityManager()); } + /* + * Fix bugid 4147561: When JDK tools are executed, the value of + * the CLASSPATH environment variable for the shell in which they + * were invoked is no longer incorporated into the application + * class path; CLASSPATH's only effect is to be the value of the + * system property "env.class.path". To preserve the previous + * (JDK1.1 and JDK1.2beta3) behavior of this tool, however, its + * CLASSPATH should still be considered when resolving classes + * being unmarshalled. To effect this old behavior, a class + * loader that loads from the file path specified in the + * "env.class.path" property is created and set to be the context + * class loader before the remote object is exported. + */ + String envcp = System.getProperty("env.class.path"); + if (envcp == null) { + envcp = "."; // preserve old default behavior + } + URL[] urls = pathToURLs(envcp); + ClassLoader cl = new URLClassLoader(urls); + + /* + * Fix bugid 4242317: Classes defined by this class loader should + * be annotated with the value of the "java.rmi.server.codebase" + * property, not the "file:" URLs for the CLASSPATH elements. + */ + sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl); + + Thread.currentThread().setContextClassLoader(cl); + + RegistryImpl registryImpl = null; try { - /* - * Fix bugid 4147561: When JDK tools are executed, the value of - * the CLASSPATH environment variable for the shell in which they - * were invoked is no longer incorporated into the application - * class path; CLASSPATH's only effect is to be the value of the - * system property "env.class.path". To preserve the previous - * (JDK1.1 and JDK1.2beta3) behavior of this tool, however, its - * CLASSPATH should still be considered when resolving classes - * being unmarshalled. To effect this old behavior, a class - * loader that loads from the file path specified in the - * "env.class.path" property is created and set to be the context - * class loader before the remote object is exported. - */ - String envcp = System.getProperty("env.class.path"); - if (envcp == null) { - envcp = "."; // preserve old default behavior - } - URL[] urls = pathToURLs(envcp); - ClassLoader cl = new URLClassLoader(urls); + registryImpl = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public RegistryImpl run() throws RemoteException { + return new RegistryImpl(regPort); + } + }, getAccessControlContext(regPort)); + } catch (PrivilegedActionException ex) { + throw (RemoteException) ex.getException(); + } - /* - * Fix bugid 4242317: Classes defined by this class loader should - * be annotated with the value of the "java.rmi.server.codebase" - * property, not the "file:" URLs for the CLASSPATH elements. - */ - sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl); - - Thread.currentThread().setContextClassLoader(cl); + return registryImpl; + } + /** + * Main program to start a registry.
+ * The port number can be specified on the command line. + */ + public static void main(String args[]) + { + try { final int regPort = (args.length >= 1) ? Integer.parseInt(args[0]) : Registry.REGISTRY_PORT; - try { - registry = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public RegistryImpl run() throws RemoteException { - return new RegistryImpl(regPort); - } - }, getAccessControlContext(regPort)); - } catch (PrivilegedActionException ex) { - throw (RemoteException) ex.getException(); - } + + registry = createRegistry(regPort); // prevent registry from exiting while (true) { From 0d958d9da8337433ac8a277f91420d792e4799be Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 9 Jan 2017 21:40:10 -0800 Subject: [PATCH 02/11] 8172475: Remove usage from Class and ClassLoader Reviewed-by: bpb, mchung --- .../share/classes/java/lang/Class.java | 10 +- .../share/classes/java/lang/ClassLoader.java | 200 +++++++++--------- 2 files changed, 105 insertions(+), 105 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 1afa833c7a9..589ba51089c 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2017, 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 @@ -2477,7 +2477,7 @@ public final class Class implements java.io.Serializable, *

* @@ -2570,7 +2570,7 @@ public final class Class implements java.io.Serializable, * * diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 3778fc8d122..fb771c29a10 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -70,34 +70,34 @@ import sun.security.util.SecurityConstants; /** * A class loader is an object that is responsible for loading classes. The - * class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to * locate or generate data that constitutes a definition for the class. A * typical strategy is to transform the name into a file name and then read a * "class file" of that name from a file system. * - *

Every {@link Class Class} object contains a {@link - * Class#getClassLoader() reference} to the ClassLoader that defined + *

Every {@link java.lang.Class Class} object contains a {@link + * Class#getClassLoader() reference} to the {@code ClassLoader} that defined * it. * - *

Class objects for array classes are not created by class + *

{@code Class} objects for array classes are not created by class * loaders, but are created automatically as required by the Java runtime. * The class loader for an array class, as returned by {@link * Class#getClassLoader()} is the same as the class loader for its element * type; if the element type is a primitive type, then the array class has no * class loader. * - *

Applications implement subclasses of ClassLoader in order to + *

Applications implement subclasses of {@code ClassLoader} in order to * extend the manner in which the Java virtual machine dynamically loads * classes. * *

Class loaders may typically be used by security managers to indicate * security domains. * - *

The ClassLoader class uses a delegation model to search for - * classes and resources. Each instance of ClassLoader has an + *

The {@code ClassLoader} class uses a delegation model to search for + * classes and resources. Each instance of {@code ClassLoader} has an * associated parent class loader. When requested to find a class or - * resource, a ClassLoader instance will delegate the search for the + * resource, a {@code ClassLoader} instance will delegate the search for the * class or resource to its parent class loader before attempting to find the * class or resource itself. * @@ -105,15 +105,15 @@ import sun.security.util.SecurityConstants; * {@linkplain #isRegisteredAsParallelCapable() parallel capable} class * loaders and are required to register themselves at their class initialization * time by invoking the {@link - * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} - * method. Note that the ClassLoader class is registered as parallel + * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} + * method. Note that the {@code ClassLoader} class is registered as parallel * capable by default. However, its subclasses still need to register themselves * if they are parallel capable. * In environments in which the delegation model is not strictly * hierarchical, class loaders need to be parallel capable, otherwise class * loading can lead to deadlocks because the loader lock is held for the * duration of the class loading process (see {@link #loadClass - * loadClass} methods). + * loadClass} methods). * *

Run-time Built-in Class Loaders

* @@ -143,13 +143,13 @@ import sun.security.util.SecurityConstants; * However, some classes may not originate from a file; they may originate * from other sources, such as the network, or they could be constructed by an * application. The method {@link #defineClass(String, byte[], int, int) - * defineClass} converts an array of bytes into an instance of class - * Class. Instances of this newly defined class can be created using - * {@link Class#newInstance Class.newInstance}. + * defineClass} converts an array of bytes into an instance of class + * {@code Class}. Instances of this newly defined class can be created using + * {@link Class#newInstance Class.newInstance}. * *

The methods and constructors of objects created by a class loader may * reference other classes. To determine the class(es) referred to, the Java - * virtual machine invokes the {@link #loadClass loadClass} method of + * virtual machine invokes the {@link #loadClass loadClass} method of * the class loader that originally created the class. * *

For example, an application could create a network class loader to @@ -162,9 +162,9 @@ import sun.security.util.SecurityConstants; * * *

The network class loader subclass must define the methods {@link - * #findClass findClass} and loadClassData to load a class + * #findClass findClass} and {@code loadClassData} to load a class * from the network. Once it has downloaded the bytes that make up the class, - * it should use the method {@link #defineClass defineClass} to + * it should use the method {@link #defineClass defineClass} to * create a class instance. A sample implementation is: * *

@@ -392,7 +392,7 @@ public abstract class ClassLoader {
      *
      * 

If there is a security manager, its {@link * SecurityManager#checkCreateClassLoader() - * checkCreateClassLoader} method is invoked. This may result in + * checkCreateClassLoader} method is invoked. This may result in * a security exception.

* * @param parent @@ -400,7 +400,7 @@ public abstract class ClassLoader { * * @throws SecurityException * If a security manager exists and its - * checkCreateClassLoader method doesn't allow creation + * {@code checkCreateClassLoader} method doesn't allow creation * of a new class loader. * * @since 1.2 @@ -410,18 +410,18 @@ public abstract class ClassLoader { } /** - * Creates a new class loader using the ClassLoader returned by + * Creates a new class loader using the {@code ClassLoader} returned by * the method {@link #getSystemClassLoader() - * getSystemClassLoader()} as the parent class loader. + * getSystemClassLoader()} as the parent class loader. * *

If there is a security manager, its {@link * SecurityManager#checkCreateClassLoader() - * checkCreateClassLoader} method is invoked. This may result in + * checkCreateClassLoader} method is invoked. This may result in * a security exception.

* * @throws SecurityException * If a security manager exists and its - * checkCreateClassLoader method doesn't allow creation + * {@code checkCreateClassLoader} method doesn't allow creation * of a new class loader. */ protected ClassLoader() { @@ -458,13 +458,13 @@ public abstract class ClassLoader { * This method searches for classes in the same manner as the {@link * #loadClass(String, boolean)} method. It is invoked by the Java virtual * machine to resolve class references. Invoking this method is equivalent - * to invoking {@link #loadClass(String, boolean) loadClass(name, - * false)}. + * to invoking {@link #loadClass(String, boolean) loadClass(name, + * false)}. * * @param name * The binary name of the class * - * @return The resulting Class object + * @return The resulting {@code Class} object * * @throws ClassNotFoundException * If the class was not found @@ -483,8 +483,8 @@ public abstract class ClassLoader { *
  • Invoke {@link #findLoadedClass(String)} to check if the class * has already been loaded.

  • * - *
  • Invoke the {@link #loadClass(String) loadClass} method - * on the parent class loader. If the parent is null the class + *

  • Invoke the {@link #loadClass(String) loadClass} method + * on the parent class loader. If the parent is {@code null} the class * loader built-in to the virtual machine is used, instead.

  • * *
  • Invoke the {@link #findClass(String)} method to find the @@ -493,23 +493,23 @@ public abstract class ClassLoader { * * *

    If the class was found using the above steps, and the - * resolve flag is true, this method will then invoke the {@link - * #resolveClass(Class)} method on the resulting Class object. + * {@code resolve} flag is true, this method will then invoke the {@link + * #resolveClass(Class)} method on the resulting {@code Class} object. * - *

    Subclasses of ClassLoader are encouraged to override {@link + *

    Subclasses of {@code ClassLoader} are encouraged to override {@link * #findClass(String)}, rather than this method.

    * *

    Unless overridden, this method synchronizes on the result of - * {@link #getClassLoadingLock getClassLoadingLock} method + * {@link #getClassLoadingLock getClassLoadingLock} method * during the entire class loading process. * * @param name * The binary name of the class * * @param resolve - * If true then resolve the class + * If {@code true} then resolve the class * - * @return The resulting Class object + * @return The resulting {@code Class} object * * @throws ClassNotFoundException * If the class could not be found @@ -606,7 +606,7 @@ public abstract class ClassLoader { * @return the lock for class loading operations * * @throws NullPointerException - * If registered as parallel capable and className is null + * If registered as parallel capable and {@code className} is null * * @see #loadClass(String, boolean) * @@ -667,14 +667,14 @@ public abstract class ClassLoader { * Finds the class with the specified binary name. * This method should be overridden by class loader implementations that * follow the delegation model for loading classes, and will be invoked by - * the {@link #loadClass loadClass} method after checking the + * the {@link #loadClass loadClass} method after checking the * parent class loader for the requested class. The default implementation - * throws a ClassNotFoundException. + * throws a {@code ClassNotFoundException}. * * @param name * The binary name of the class * - * @return The resulting Class object + * @return The resulting {@code Class} object * * @throws ClassNotFoundException * If the class could not be found @@ -722,32 +722,32 @@ public abstract class ClassLoader { /** - * Converts an array of bytes into an instance of class Class. - * Before the Class can be used it must be resolved. This method + * Converts an array of bytes into an instance of class {@code Class}. + * Before the {@code Class} can be used it must be resolved. This method * is deprecated in favor of the version that takes a binary name as its first argument, and is more secure. * * @param b * The bytes that make up the class data. The bytes in positions - * off through off+len-1 should have the format + * {@code off} through {@code off+len-1} should have the format * of a valid class file as defined by * The Java™ Virtual Machine Specification. * * @param off - * The start offset in b of the class data + * The start offset in {@code b} of the class data * * @param len * The length of the class data * - * @return The Class object that was created from the specified + * @return The {@code Class} object that was created from the specified * class data * * @throws ClassFormatError * If the data did not contain a valid class * * @throws IndexOutOfBoundsException - * If either off or len is negative, or if - * off+len is greater than b.length. + * If either {@code off} or {@code len} is negative, or if + * {@code off+len} is greater than {@code b.length}. * * @throws SecurityException * If an attempt is made to add this class to a package that @@ -994,11 +994,11 @@ public abstract class ClassLoader { * #defineClass(String, byte[], int, int, ProtectionDomain)}. * *

    An invocation of this method of the form - * cl.defineClass(name, - * bBuffer, pd) yields exactly the same + * cl{@code .defineClass(}name{@code ,} + * bBuffer{@code ,} pd{@code )} yields exactly the same * result as the statements * - *

    + *

    * ...
    * byte[] temp = new byte[bBuffer.{@link * java.nio.ByteBuffer#remaining remaining}()];
    @@ -1007,16 +1007,16 @@ public abstract class ClassLoader { * return {@link #defineClass(String, byte[], int, int, ProtectionDomain) * cl.defineClass}(name, temp, 0, * temp.length, pd);
    - *

    + *

    * * @param name * The expected binary name. of the class, or - * null if not known + * {@code null} if not known * * @param b * The bytes that make up the class data. The bytes from positions - * b.position() through b.position() + b.limit() -1 - * should have the format of a valid class file as defined by + * {@code b.position()} through {@code b.position() + b.limit() -1 + * } should have the format of a valid class file as defined by * The Java™ Virtual Machine Specification. * * @param protectionDomain @@ -1158,7 +1158,7 @@ public abstract class ClassLoader { /** * Links the specified class. This (misleadingly named) method may be - * used by a class loader to link a class. If the class c has + * used by a class loader to link a class. If the class {@code c} has * already been linked, then this method simply returns. Otherwise, the * class is linked as described in the "Execution" chapter of * The Java™ Language Specification. @@ -1167,7 +1167,7 @@ public abstract class ClassLoader { * The class to link * * @throws NullPointerException - * If c is null. + * If {@code c} is {@code null}. * * @see #defineClass(String, byte[], int, int) */ @@ -1182,16 +1182,16 @@ public abstract class ClassLoader { * loading it if necessary. * *

    This method loads the class through the system class loader (see - * {@link #getSystemClassLoader()}). The Class object returned - * might have more than one ClassLoader associated with it. - * Subclasses of ClassLoader need not usually invoke this method, + * {@link #getSystemClassLoader()}). The {@code Class} object returned + * might have more than one {@code ClassLoader} associated with it. + * Subclasses of {@code ClassLoader} need not usually invoke this method, * because most class loaders need to override just {@link * #findClass(String)}.

    * * @param name * The binary name of the class * - * @return The Class object for the specified name + * @return The {@code Class} object for the specified {@code name} * * @throws ClassNotFoundException * If the class could not be found @@ -1222,12 +1222,12 @@ public abstract class ClassLoader { * Returns the class with the given binary name if this * loader has been recorded by the Java virtual machine as an initiating * loader of a class with that binary name. Otherwise - * null is returned. + * {@code null} is returned. * * @param name * The binary name of the class * - * @return The Class object, or null if the class has + * @return The {@code Class} object, or {@code null} if the class has * not been loaded * * @since 1.1 @@ -1245,7 +1245,7 @@ public abstract class ClassLoader { * class. * * @param c - * The Class object + * The {@code Class} object * * @param signers * The signers for the class @@ -1306,11 +1306,11 @@ public abstract class ClassLoader { * (images, audio, text, etc) that can be accessed by class code in a way * that is independent of the location of the code. * - *

    The name of a resource is a '/'-separated path name that + *

    The name of a resource is a '{@code /}'-separated path name that * identifies the resource. * *

    This method will first search the parent class loader for the - * resource; if the parent is null the path of the class loader + * resource; if the parent is {@code null} the path of the class loader * built-in to the virtual machine is searched. That failing, this method * will invoke {@link #findResource(String)} to find the resource.

    * @@ -1362,7 +1362,7 @@ public abstract class ClassLoader { * (images, audio, text, etc) that can be accessed by class code in a way * that is independent of the location of the code. * - *

    The name of a resource is a /-separated path name that + *

    The name of a resource is a {@code /}-separated path name that * identifies the resource. * *

    The delegation order for searching is described in the documentation @@ -1389,7 +1389,7 @@ public abstract class ClassLoader { * @param name * The resource name * - * @return An enumeration of {@link java.net.URL URL} objects for + * @return An enumeration of {@link java.net.URL URL} objects for * the resource. If no resources could be found, the enumeration * will be empty. Resources for which a {@code URL} cannot be * constructed, are in package that is not opened unconditionally, @@ -1505,7 +1505,7 @@ public abstract class ClassLoader { } /** - * Returns an enumeration of {@link java.net.URL URL} objects + * Returns an enumeration of {@link java.net.URL URL} objects * representing all the resources with the given name. Class loader * implementations should override this method to specify where to load * resources from. @@ -1520,7 +1520,7 @@ public abstract class ClassLoader { * @param name * The resource name * - * @return An enumeration of {@link java.net.URL URL} objects for + * @return An enumeration of {@link java.net.URL URL} objects for * the resource. If no resources could be found, the enumeration * will be empty. Resources for which a {@code URL} cannot be * constructed, are in a package that is not opened unconditionally, @@ -1594,7 +1594,7 @@ public abstract class ClassLoader { * @param name * The resource name * - * @return A {@link java.net.URL URL} to the resource; {@code + * @return A {@link java.net.URL URL} to the resource; {@code * null} if the resource could not be found, a URL could not be * constructed to locate the resource, the resource is in a package * that is not opened unconditionally or access to the resource is @@ -1609,8 +1609,8 @@ public abstract class ClassLoader { /** * Finds all resources of the specified name from the search path used to * load classes. The resources thus found are returned as an - * {@link java.util.Enumeration Enumeration} of {@link - * java.net.URL URL} objects. + * {@link java.util.Enumeration Enumeration} of {@link + * java.net.URL URL} objects. * *

    The search order is described in the documentation for {@link * #getSystemResource(String)}.

    @@ -1625,7 +1625,7 @@ public abstract class ClassLoader { * @param name * The resource name * - * @return An enumeration of {@link java.net.URL URL} objects for + * @return An enumeration of {@link java.net.URL URL} objects for * the resource. If no resources could be found, the enumeration * will be empty. Resources for which a {@code URL} cannot be * constructed, are in a package that is not opened unconditionally, @@ -1714,11 +1714,11 @@ public abstract class ClassLoader { /** * Returns the parent class loader for delegation. Some implementations may - * use null to represent the bootstrap class loader. This method - * will return null in such implementations if this class loader's + * use {@code null} to represent the bootstrap class loader. This method + * will return {@code null} in such implementations if this class loader's * parent is the bootstrap class loader. * - * @return The parent ClassLoader + * @return The parent {@code ClassLoader} * * @throws SecurityException * If a security manager is present, and the caller's class loader @@ -1785,7 +1785,7 @@ public abstract class ClassLoader { /** * Returns the system class loader for delegation. This is the default - * delegation parent for new ClassLoader instances, and is + * delegation parent for new {@code ClassLoader} instances, and is * typically the class loader used to start the application. * *

    This method is first invoked early in the runtime's startup @@ -1797,12 +1797,12 @@ public abstract class ClassLoader { *

    The default system class loader is an implementation-dependent * instance of this class. * - *

    If the system property "java.system.class.loader" is defined + *

    If the system property "{@code java.system.class.loader}" is defined * when this method is first invoked then the value of that property is * taken to be the name of a class that will be returned as the system * class loader. The class is loaded using the default system class loader * and must define a public constructor that takes a single parameter of - * type ClassLoader which is used as the delegation parent. An + * type {@code ClassLoader} which is used as the delegation parent. An * instance is then created using this constructor with the default system * class loader as the parameter. The resulting class loader is defined * to be the system class loader. During construction, the class loader @@ -1825,7 +1825,7 @@ public abstract class ClassLoader { * the application module path then the class path defaults to * the current working directory. * - * @return The system ClassLoader for delegation + * @return The system {@code ClassLoader} for delegation * * @throws SecurityException * If a security manager is present, and the caller's class loader @@ -1835,11 +1835,11 @@ public abstract class ClassLoader { * * @throws IllegalStateException * If invoked recursively during the construction of the class - * loader specified by the "java.system.class.loader" + * loader specified by the "{@code java.system.class.loader}" * property. * * @throws Error - * If the system property "java.system.class.loader" + * If the system property "{@code java.system.class.loader}" * is defined but the named class could not be loaded, the * provider class does not define the required constructor, or an * exception is thrown by that constructor when it is invoked. The @@ -2249,9 +2249,9 @@ public abstract class ClassLoader { /** * Returns the absolute path name of a native library. The VM invokes this * method to locate the native libraries that belong to classes loaded with - * this class loader. If this method returns null, the VM + * this class loader. If this method returns {@code null}, the VM * searches the library along the path specified as the - * "java.library.path" property. + * "{@code java.library.path}" property. * * @param libname * The library name @@ -2270,12 +2270,12 @@ public abstract class ClassLoader { /** * The inner class NativeLibrary denotes a loaded native library instance. * Every classloader contains a vector of loaded native libraries in the - * private field nativeLibraries. The native libraries loaded - * into the system are entered into the systemNativeLibraries + * private field {@code nativeLibraries}. The native libraries loaded + * into the system are entered into the {@code systemNativeLibraries} * vector. * *

    Every native library requires a particular version of JNI. This is - * denoted by the private jniVersion field. This field is set by + * denoted by the private {@code jniVersion} field. This field is set by * the VM when it loads the library, and used by the VM to pass the correct * version of JNI to the native methods.

    * @@ -2592,8 +2592,8 @@ public abstract class ClassLoader { * #setClassAssertionStatus(String, boolean)}. * * @param enabled - * true if classes loaded by this class loader will - * henceforth have assertions enabled by default, false + * {@code true} if classes loaded by this class loader will + * henceforth have assertions enabled by default, {@code false} * if they will have assertions disabled by default. * * @since 1.4 @@ -2614,16 +2614,16 @@ public abstract class ClassLoader { * any of its "subpackages". * *

    A subpackage of a package named p is any package whose name begins - * with "p.". For example, javax.swing.text is a - * subpackage of javax.swing, and both java.util and - * java.lang.reflect are subpackages of java. + * with "{@code p.}". For example, {@code javax.swing.text} is a + * subpackage of {@code javax.swing}, and both {@code java.util} and + * {@code java.lang.reflect} are subpackages of {@code java}. * *

    In the event that multiple package defaults apply to a given class, * the package default pertaining to the most specific package takes - * precedence over the others. For example, if javax.lang and - * javax.lang.reflect both have package defaults associated with + * precedence over the others. For example, if {@code javax.lang} and + * {@code javax.lang.reflect} both have package defaults associated with * them, the latter package default applies to classes in - * javax.lang.reflect. + * {@code javax.lang.reflect}. * *

    Package defaults take precedence over the class loader's default * assertion status, and may be overridden on a per-class basis by invoking @@ -2631,15 +2631,15 @@ public abstract class ClassLoader { * * @param packageName * The name of the package whose package default assertion status - * is to be set. A null value indicates the unnamed + * is to be set. A {@code null} value indicates the unnamed * package that is "current" * (see section 7.4.2 of * The Java™ Language Specification.) * * @param enabled - * true if classes loaded by this classloader and + * {@code true} if classes loaded by this classloader and * belonging to the named package or any of its subpackages will - * have assertions enabled by default, false if they will + * have assertions enabled by default, {@code false} if they will * have assertions disabled by default. * * @since 1.4 @@ -2670,8 +2670,8 @@ public abstract class ClassLoader { * assertion status is to be set. * * @param enabled - * true if the named class is to have assertions - * enabled when (and if) it is initialized, false if the + * {@code true} if the named class is to have assertions + * enabled when (and if) it is initialized, {@code false} if the * class is to have assertions disabled. * * @since 1.4 @@ -2687,7 +2687,7 @@ public abstract class ClassLoader { /** * Sets the default assertion status for this class loader to - * false and discards any package defaults or class assertion + * {@code false} and discards any package defaults or class assertion * status settings associated with the class loader. This method is * provided so that class loaders can be made to ignore any command line or * persistent assertion status settings and "start with a clean slate." From 4cd655c1f6962138798d911f7097708cb19beb5c Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Tue, 10 Jan 2017 22:17:02 +0300 Subject: [PATCH 03/11] 8159058: SAXParseException when sending soap message Reviewed-by: lancea --- .../ws/8159058/SaajEmptyNamespaceTest.java | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 jdk/test/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java diff --git a/jdk/test/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java b/jdk/test/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java new file mode 100644 index 00000000000..eb9fb3bffe5 --- /dev/null +++ b/jdk/test/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2017, 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 8159058 + * @summary Test that empty default namespace declaration clears the + * default namespace value + * @modules java.xml.ws/com.sun.xml.internal.ws.api + * java.xml.ws/com.sun.xml.internal.ws.api.message.saaj + * java.xml.ws/com.sun.xml.internal.ws.message.stream + * @run testng/othervm SaajEmptyNamespaceTest + */ + +import com.sun.xml.internal.ws.api.SOAPVersion; +import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory; +import com.sun.xml.internal.ws.message.stream.StreamMessage; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import javax.xml.namespace.QName; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.w3c.dom.Node; + +public class SaajEmptyNamespaceTest { + + /* + * Test that SOAP message with default namespace declaration that contains empty + * string is properly processed by SAAJ reader. + */ + @Test + public void testResetDefaultNamespaceSAAJ() throws Exception { + // Create SOAP message from XML string and process it with SAAJ reader + XMLStreamReader envelope = XMLInputFactory.newFactory().createXMLStreamReader( + new StringReader(INPUT_SOAP_MESSAGE)); + StreamMessage streamMessage = new StreamMessage(SOAPVersion.SOAP_11, + envelope, null); + SAAJFactory saajFact = new SAAJFactory(); + SOAPMessage soapMessage = saajFact.readAsSOAPMessage(SOAPVersion.SOAP_11, streamMessage); + + // Check if constructed object model meets local names and namespace expectations + SOAPElement request = (SOAPElement) soapMessage.getSOAPBody().getFirstChild(); + // Check top body element name + Assert.assertEquals(request.getLocalName(), "SampleServiceRequest"); + // Check top body element namespace + Assert.assertEquals(request.getNamespaceURI(), TEST_NS); + SOAPElement params = (SOAPElement) request.getFirstChild(); + // Check first child name + Assert.assertEquals(params.getLocalName(), "RequestParams"); + // Check if first child namespace is null + Assert.assertNull(params.getNamespaceURI()); + + // Check inner elements of the first child + SOAPElement param1 = (SOAPElement) params.getFirstChild(); + Assert.assertEquals(param1.getLocalName(), "Param1"); + Assert.assertNull(param1.getNamespaceURI()); + SOAPElement param2 = (SOAPElement) params.getChildNodes().item(1); + Assert.assertEquals(param2.getLocalName(), "Param2"); + Assert.assertNull(param2.getNamespaceURI()); + // Check full content of SOAP body + Assert.assertEquals(nodeToText(request), EXPECTED_RESULT); + } + + /* + * Test that adding element with explicitly null namespace URI shall put the + * element into global namespace. Namespace declarations are not added explicitly. + */ + @Test + public void testAddElementToNullNsNoDeclarations() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); + } + + /* + * Test that adding element with explicitly empty namespace URI shall put + * the element into global namespace. Namespace declarations are not added + * explicitly. + */ + @Test + public void testAddElementToGlobalNsNoDeclarations() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", ""); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); + } + + /* + * Test that adding element with explicitly empty namespace URI set via QName + * shall put the element into global namespace. + */ + @Test + public void testAddElementToNullNsQName() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + parentExplicitNS.addNamespaceDeclaration("", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName(null, "global-child")); + childGlobalNS.addNamespaceDeclaration("", ""); + SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); + Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); + } + + /* + * Test that adding element with explicitly empty namespace URI shall put + * the element into global namespace. + */ + @Test + public void testAddElementToGlobalNs() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + parentExplicitNS.addNamespaceDeclaration("", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", ""); + childGlobalNS.addNamespaceDeclaration("", ""); + SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); + Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); + } + + /* + * Test that adding element with explicitly null namespace URI shall put + * the element into global namespace. + */ + @Test + public void testAddElementToNullNs() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + parentExplicitNS.addNamespaceDeclaration("", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null); + childGlobalNS.addNamespaceDeclaration("", null); + SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); + Assert.assertEquals(TEST_NS, childDefaultNS.getNamespaceURI()); + } + + /* + * Test that adding element with explicitly empty namespace URI via QName + * shall put the element in global namespace. + */ + @Test + public void testAddElementToGlobalNsQName() throws Exception { + // Create empty SOAP message + SOAPMessage msg = createSoapMessage(); + SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); + + // Add elements + SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); + parentExplicitNS.addNamespaceDeclaration("", TEST_NS); + SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName("", "global-child")); + childGlobalNS.addNamespaceDeclaration("", ""); + SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); + SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); + + // Check namespace URIs + Assert.assertNull(childGlobalNS.getNamespaceURI()); + Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); + Assert.assertEquals(childDefaultNS.getNamespaceURI(),TEST_NS); + } + + // Convert DOM node to text representation + private String nodeToText(Node node) throws TransformerException { + Transformer trans = TransformerFactory.newInstance().newTransformer(); + trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + trans.transform(new DOMSource(node), result); + String bodyContent = writer.toString(); + System.out.println("SOAP body content read by SAAJ:"+bodyContent); + return bodyContent; + } + + // Create SOAP message with empty body + private static SOAPMessage createSoapMessage() throws SOAPException, UnsupportedEncodingException { + String xml = "" + +""; + MessageFactory mFactory = MessageFactory.newInstance(); + SOAPMessage msg = mFactory.createMessage(); + msg.getSOAPPart().setContent(new StreamSource(new ByteArrayInputStream(xml.getBytes("utf-8")))); + return msg; + } + + // Namespace value used in tests + private static String TEST_NS = "http://example.org/test"; + + // Content of SOAP message passed to SAAJ factory + private static String INPUT_SOAP_MESSAGE = "" + + "" + + "" + + "" + + "" + + "hogehoge" + + "fugafuga" + + "" + + "" + + "" + + ""; + + // Expected body content after SAAJ processing + private static String EXPECTED_RESULT = "" + + "" + + "hogehoge" + + "fugafuga" + + "" + + ""; +} From 60a77d0b8480cb47c4b2407c967fecc4b7c95194 Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Wed, 11 Jan 2017 13:10:03 +0300 Subject: [PATCH 04/11] 8171958: Several tests from java/time/test/java/time/format requiring jdk.localedata for execution Reviewed-by: naoto --- jdk/test/java/time/TEST.properties | 1 - .../format/TestDateTimeFormatterBuilder.java | 62 ----- ...estDateTimeFormatterBuilderWithLocale.java | 195 +++++++++++++++ .../time/format/TestDateTimeTextProvider.java | 45 +--- .../TestDateTimeTextProviderWithLocale.java | 146 +++++++++++ .../TestNarrowMonthNamesAndDayNames.java | 5 +- .../java/time/format/TestNonIsoFormatter.java | 7 + .../test/java/time/format/TestTextParser.java | 116 +-------- .../time/format/TestTextParserWithLocale.java | 226 ++++++++++++++++++ .../java/time/format/TestTextPrinter.java | 54 +---- .../format/TestTextPrinterWithLocale.java | 163 +++++++++++++ 11 files changed, 743 insertions(+), 277 deletions(-) create mode 100644 jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java create mode 100644 jdk/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java create mode 100644 jdk/test/java/time/test/java/time/format/TestTextParserWithLocale.java create mode 100644 jdk/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java diff --git a/jdk/test/java/time/TEST.properties b/jdk/test/java/time/TEST.properties index 49d8c3ce5d4..f522b84681a 100644 --- a/jdk/test/java/time/TEST.properties +++ b/jdk/test/java/time/TEST.properties @@ -1,7 +1,6 @@ # Threeten test uses TestNG TestNG.dirs = . othervm.dirs = tck/java/time/chrono test/java/time/chrono test/java/time/format -modules = jdk.localedata lib.dirs = ../../lib/testlibrary lib.build = jdk.testlibrary.RandomFactory modules = java.base/java.time:open java.base/java.time.chrono:open java.base/java.time.zone:open diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java index 88b491e8b74..5b83d444faa 100644 --- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java @@ -879,25 +879,6 @@ public class TestDateTimeFormatterBuilder { } } - //----------------------------------------------------------------------- - @DataProvider(name="patternPrint") - Object[][] data_patternPrint() { - return new Object[][] { - {"Q", date(2012, 2, 10), "1"}, - {"QQ", date(2012, 2, 10), "01"}, - {"QQQ", date(2012, 2, 10), "Q1"}, - {"QQQQ", date(2012, 2, 10), "1st quarter"}, - {"QQQQQ", date(2012, 2, 10), "1"}, - }; - } - - @Test(dataProvider="patternPrint") - public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { - DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); - String test = f.format(temporal); - assertEquals(test, expected); - } - //----------------------------------------------------------------------- @DataProvider(name="localePatterns") Object[][] localizedDateTimePatterns() { @@ -914,48 +895,6 @@ public class TestDateTimeFormatterBuilder { {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"}, {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"}, {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"}, - - // French Locale and ISO Chronology - {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"}, - {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"}, - {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"}, - {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"}, - {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"}, - {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"}, - {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"}, - {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"}, - {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"}, - {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"}, - {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"}, - {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"}, - - // Japanese Locale and JapaneseChronology - {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"}, - {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"}, - {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"}, - {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"}, - {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, - {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, - {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, - {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"}, - {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"}, - {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"}, - {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"}, - {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"}, - - // Chinese Local and Chronology - {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"}, - {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"}, - {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"}, - {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"}, - {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, - {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, - {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, - {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"}, - {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"}, - {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"}, - {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"}, - {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"}, }; } @@ -1004,5 +943,4 @@ public class TestDateTimeFormatterBuilder { private static Temporal date(int y, int m, int d) { return LocalDate.of(y, m, d); } - } diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java new file mode 100644 index 00000000000..afb879de8ec --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2012, 2016, 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos + * + * 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 JSR-310 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. + */ + +/* + * @test + * @modules jdk.localedata + */ +package test.java.time.format; + +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.FormatStyle; +import java.time.LocalDate; +import java.time.temporal.Temporal; + +import java.util.Locale; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test DateTimeFormatterBuilder. + */ +@Test +public class TestDateTimeFormatterBuilderWithLocale { + + private DateTimeFormatterBuilder builder; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + } + + //----------------------------------------------------------------------- + @DataProvider(name="patternPrint") + Object[][] data_patternPrint() { + return new Object[][] { + {"Q", date(2012, 2, 10), "1"}, + {"QQ", date(2012, 2, 10), "01"}, + {"QQQ", date(2012, 2, 10), "Q1"}, + {"QQQQ", date(2012, 2, 10), "1st quarter"}, + {"QQQQQ", date(2012, 2, 10), "1"}, + }; + } + + @Test(dataProvider="patternPrint") + public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { + DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); + String test = f.format(temporal); + assertEquals(test, expected); + } + + //----------------------------------------------------------------------- + @DataProvider(name="localePatterns") + Object[][] localizedDateTimePatterns() { + return new Object[][] { + // French Locale and ISO Chronology + {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"}, + {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"}, + {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"}, + {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"}, + {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"}, + {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"}, + {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"}, + {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"}, + {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"}, + {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"}, + {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"}, + {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"}, + + // Japanese Locale and JapaneseChronology + {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"}, + {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"}, + {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"}, + {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"}, + {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, + {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, + {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, + {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"}, + {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"}, + {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"}, + {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"}, + {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"}, + + // Chinese Local and Chronology + {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"}, + {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"}, + {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"}, + {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"}, + {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, + {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, + {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, + {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"}, + {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"}, + {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"}, + {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"}, + {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"}, + }; + } + + @Test(dataProvider="localePatterns") + public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle, + Chronology chrono, Locale locale, String expected) { + String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale); + assertEquals(actual, expected, "Pattern " + convertNonAscii(actual)); + } + + /** + * Returns a string that includes non-ascii characters after expanding + * the non-ascii characters to their Java language \\uxxxx form. + * @param input an input string + * @return the encoded string. + */ + private String convertNonAscii(String input) { + StringBuilder sb = new StringBuilder(input.length() * 6); + for (int i = 0; i < input.length(); i++) { + char ch = input.charAt(i); + if (ch < 255) { + sb.append(ch); + } else { + sb.append("\\u"); + sb.append(Integer.toHexString(ch)); + } + } + return sb.toString(); + } + + private static Temporal date(int y, int m, int d) { + return LocalDate.of(y, m, d); + } +} diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java index b100ddb1f7a..da4a276c8bf 100644 --- a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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,6 @@ import org.testng.annotations.Test; public class TestDateTimeTextProvider extends AbstractTestPrinterParser { Locale enUS = new Locale("en", "US"); - Locale ptBR = new Locale("pt", "BR"); //----------------------------------------------------------------------- @DataProvider(name = "Text") @@ -94,14 +93,6 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {DAY_OF_WEEK, 6, TextStyle.SHORT, enUS, "Sat"}, {DAY_OF_WEEK, 7, TextStyle.SHORT, enUS, "Sun"}, - {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"}, - {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"}, - {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"}, - {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"}, - {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"}, - {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"}, - {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"}, - {DAY_OF_WEEK, 1, TextStyle.FULL, enUS, "Monday"}, {DAY_OF_WEEK, 2, TextStyle.FULL, enUS, "Tuesday"}, {DAY_OF_WEEK, 3, TextStyle.FULL, enUS, "Wednesday"}, @@ -110,14 +101,6 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {DAY_OF_WEEK, 6, TextStyle.FULL, enUS, "Saturday"}, {DAY_OF_WEEK, 7, TextStyle.FULL, enUS, "Sunday"}, - {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"}, - {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"}, - {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"}, - {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"}, - {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"}, - {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"}, - {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"}, - {MONTH_OF_YEAR, 1, TextStyle.SHORT, enUS, "Jan"}, {MONTH_OF_YEAR, 2, TextStyle.SHORT, enUS, "Feb"}, {MONTH_OF_YEAR, 3, TextStyle.SHORT, enUS, "Mar"}, @@ -131,19 +114,6 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {MONTH_OF_YEAR, 11, TextStyle.SHORT, enUS, "Nov"}, {MONTH_OF_YEAR, 12, TextStyle.SHORT, enUS, "Dec"}, - {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"}, - {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"}, - {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"}, - {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"}, - {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"}, - {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"}, - {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"}, - {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"}, - {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"}, - {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"}, - {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"}, - {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"}, - {MONTH_OF_YEAR, 1, TextStyle.FULL, enUS, "January"}, {MONTH_OF_YEAR, 2, TextStyle.FULL, enUS, "February"}, {MONTH_OF_YEAR, 3, TextStyle.FULL, enUS, "March"}, @@ -157,19 +127,6 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { {MONTH_OF_YEAR, 11, TextStyle.FULL, enUS, "November"}, {MONTH_OF_YEAR, 12, TextStyle.FULL, enUS, "December"}, - {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"}, - {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"}, - {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"}, - {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"}, - {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"}, - {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"}, - {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"}, - {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"}, - {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"}, - {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"}, - {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"}, - {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"}, - {AMPM_OF_DAY, 0, TextStyle.SHORT, enUS, "AM"}, {AMPM_OF_DAY, 1, TextStyle.SHORT, enUS, "PM"}, diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java new file mode 100644 index 00000000000..2a426a89abd --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2012, 2016, 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos + * + * 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 JSR-310 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. + */ + +/* + * @test + * @modules jdk.localedata + */ + +package test.java.time.format; + +import static java.time.temporal.ChronoField.AMPM_OF_DAY; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static org.testng.Assert.assertEquals; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.time.temporal.TemporalField; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test SimpleDateTimeTextProviderWithLocale. + */ +@Test +public class TestDateTimeTextProviderWithLocale extends AbstractTestPrinterParser { + + Locale enUS = new Locale("en", "US"); + Locale ptBR = new Locale("pt", "BR"); + + //----------------------------------------------------------------------- + @DataProvider(name = "Text") + Object[][] data_text() { + return new Object[][] { + {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"}, + {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"}, + {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"}, + {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"}, + {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"}, + {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"}, + {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"}, + + {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"}, + {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"}, + {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"}, + {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"}, + {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"}, + {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"}, + {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"}, + + {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"}, + {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"}, + {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"}, + {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"}, + {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"}, + {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"}, + {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"}, + {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"}, + {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"}, + {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"}, + {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"}, + {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"}, + + {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"}, + {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"}, + {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"}, + {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"}, + {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"}, + {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"}, + {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"}, + {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"}, + {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"}, + {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"}, + {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"}, + {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"}, + + }; + } + + @Test(dataProvider = "Text") + public void test_getText(TemporalField field, Number value, TextStyle style, Locale locale, String expected) { + DateTimeFormatter fmt = getFormatter(field, style).withLocale(locale); + assertEquals(fmt.format(ZonedDateTime.now().with(field, value.longValue())), expected); + } + +} diff --git a/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java index 925e7ec5ef8..07eb6f63722 100644 --- a/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java +++ b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java @@ -20,13 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package test.java.time.format; - /* * @test + * @modules jdk.localedata * @bug 8146750 * @summary Test Narrow and NarrowStandalone month names are retrieved correctly. */ +package test.java.time.format; + import static org.testng.Assert.assertEquals; import java.time.DayOfWeek; diff --git a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java index 6ba45267414..885331a7776 100644 --- a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java +++ b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java @@ -20,6 +20,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/* + * + * @test + * @modules jdk.localedata + */ + package test.java.time.format; import static org.testng.Assert.assertEquals; diff --git a/jdk/test/java/time/test/java/time/format/TestTextParser.java b/jdk/test/java/time/test/java/time/format/TestTextParser.java index 5974d21911e..b6126a6b407 100644 --- a/jdk/test/java/time/test/java/time/format/TestTextParser.java +++ b/jdk/test/java/time/test/java/time/format/TestTextParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -68,16 +68,9 @@ import static org.testng.Assert.assertTrue; import java.text.ParsePosition; import java.time.DayOfWeek; -import java.time.chrono.ChronoLocalDate; -import java.time.chrono.JapaneseChronology; -import java.time.chrono.HijrahDate; -import java.time.chrono.JapaneseDate; -import java.time.chrono.MinguoDate; -import java.time.chrono.ThaiBuddhistDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; -import java.time.format.SignStyle; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQueries; @@ -92,8 +85,6 @@ import org.testng.annotations.Test; */ @Test public class TestTextParser extends AbstractTestPrinterParser { - static final Locale RUSSIAN = new Locale("ru"); - static final Locale FINNISH = new Locale("fi"); //----------------------------------------------------------------------- @DataProvider(name="error") @@ -213,20 +204,6 @@ public class TestTextParser extends AbstractTestPrinterParser { }; } - // Test data is dependent on localized resources. - @DataProvider(name="parseStandaloneText") - Object[][] providerStandaloneText() { - // Locale, TemporalField, TextStyle, expected value, input text - return new Object[][] { - {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, - {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"}, - {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 1, "\u044f\u043d\u0432."}, - {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a."}, - {FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, 2, "tiistai"}, - {FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, 2, "ti"}, - }; - } - @DataProvider(name="parseDayOfWeekText") Object[][] providerDayOfWeekData() { return new Object[][] { @@ -234,26 +211,9 @@ public class TestTextParser extends AbstractTestPrinterParser { {Locale.US, "e", "1", DayOfWeek.SUNDAY}, {Locale.US, "ee", "01", DayOfWeek.SUNDAY}, {Locale.US, "c", "1", DayOfWeek.SUNDAY}, - - {Locale.UK, "e", "1", DayOfWeek.MONDAY}, - {Locale.UK, "ee", "01", DayOfWeek.MONDAY}, - {Locale.UK, "c", "1", DayOfWeek.MONDAY}, }; } - // Test data is dependent on localized resources. - @DataProvider(name="parseLenientText") - Object[][] providerLenientText() { - // Locale, TemporalField, expected value, input text - return new Object[][] { - {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format - {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, // full standalone - {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short format - {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short standalone - }; - } - - @Test(dataProvider="parseText") public void test_parseText(TemporalField field, TextStyle style, int value, String input) throws Exception { @@ -269,14 +229,6 @@ public class TestTextParser extends AbstractTestPrinterParser { assertEquals(pos.getIndex(), input.length()); } - @Test(dataProvider="parseStandaloneText") - public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) { - DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale); - ParsePosition pos = new ParsePosition(0); - assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue); - assertEquals(pos.getIndex(), input.length()); - } - @Test(dataProvider="parseDayOfWeekText") public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) { DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale); @@ -373,25 +325,6 @@ public class TestTextParser extends AbstractTestPrinterParser { assertEquals(pos.getErrorIndex(), 0); } - //----------------------------------------------------------------------- - public void test_parse_french_short_strict_full_noMatch() throws Exception { - setStrict(true); - ParsePosition pos = new ParsePosition(0); - getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) - .parseUnresolved("janvier", pos); - assertEquals(pos.getErrorIndex(), 0); - } - - public void test_parse_french_short_strict_short_match() throws Exception { - setStrict(true); - ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) - .parseUnresolved("janv.", pos) - .getLong(MONTH_OF_YEAR), - 1L); - assertEquals(pos.getIndex(), 5); - } - //----------------------------------------------------------------------- public void test_parse_full_lenient_full_match() throws Exception { setStrict(false); @@ -436,51 +369,4 @@ public class TestTextParser extends AbstractTestPrinterParser { assertEquals(pos.getIndex(), 1); } - @Test(dataProvider="parseLenientText") - public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) { - setStrict(false); - ParsePosition pos = new ParsePosition(0); - DateTimeFormatter formatter = getFormatter(field).withLocale(locale); - assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue); - assertEquals(pos.getIndex(), input.length()); - } - - //----------------------------------------------------------------------- - @DataProvider(name="parseChronoLocalDate") - Object[][] provider_chronoLocalDate() { - return new Object[][] { - { HijrahDate.now() }, - { JapaneseDate.now() }, - { MinguoDate.now() }, - { ThaiBuddhistDate.now() }}; - } - - private static final DateTimeFormatter fmt_chrono = - new DateTimeFormatterBuilder() - .optionalStart() - .appendChronologyId() - .appendLiteral(' ') - .optionalEnd() - .optionalStart() - .appendText(ChronoField.ERA, TextStyle.SHORT) - .appendLiteral(' ') - .optionalEnd() - .appendValue(ChronoField.YEAR_OF_ERA, 1, 9, SignStyle.NORMAL) - .appendLiteral('-') - .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER) - .appendLiteral('-') - .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER) - .toFormatter(); - - @Test(dataProvider="parseChronoLocalDate") - public void test_chronoLocalDate(ChronoLocalDate date) throws Exception { - System.out.printf(" %s, [fmt=%s]%n", date, fmt_chrono.format(date)); - assertEquals(date, fmt_chrono.parse(fmt_chrono.format(date), ChronoLocalDate::from)); - - DateTimeFormatter fmt = DateTimeFormatter.ofPattern("[GGG ]yyy-MM-dd") - .withChronology(date.getChronology()); - System.out.printf(" %s, [fmt=%s]%n", date.toString(), fmt.format(date)); - assertEquals(date, fmt.parse(fmt.format(date), ChronoLocalDate::from)); - } - } diff --git a/jdk/test/java/time/test/java/time/format/TestTextParserWithLocale.java b/jdk/test/java/time/test/java/time/format/TestTextParserWithLocale.java new file mode 100644 index 00000000000..ab5bdf28df3 --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestTextParserWithLocale.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2012, 2016, 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * 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 JSR-310 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. + */ + +/* + * @test + * @modules jdk.localedata + */ + +package test.java.time.format; + +import java.text.ParsePosition; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.HijrahDate; +import java.time.chrono.JapaneseDate; +import java.time.chrono.MinguoDate; +import java.time.chrono.ThaiBuddhistDate; +import java.time.DayOfWeek; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.TextStyle; +import java.time.format.SignStyle; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalField; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + + +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static org.testng.Assert.assertEquals; + +/** + * Test TextPrinterParser. + */ +@Test +public class TestTextParserWithLocale extends AbstractTestPrinterParser { + static final Locale RUSSIAN = new Locale("ru"); + static final Locale FINNISH = new Locale("fi"); + + @DataProvider(name="parseDayOfWeekText") + Object[][] providerDayOfWeekData() { + return new Object[][] { + // Locale, pattern, input text, expected DayOfWeek + {Locale.US, "e", "1", DayOfWeek.SUNDAY}, + {Locale.US, "ee", "01", DayOfWeek.SUNDAY}, + {Locale.US, "c", "1", DayOfWeek.SUNDAY}, + + {Locale.UK, "e", "1", DayOfWeek.MONDAY}, + {Locale.UK, "ee", "01", DayOfWeek.MONDAY}, + {Locale.UK, "c", "1", DayOfWeek.MONDAY}, + }; + } + + @Test(dataProvider="parseDayOfWeekText") + public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) { + DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale); + ParsePosition pos = new ParsePosition(0); + assertEquals(DayOfWeek.from(formatter.parse(input, pos)), expected); + assertEquals(pos.getIndex(), input.length()); + } + + //-------------------------------------------------------------------- + // Test data is dependent on localized resources. + @DataProvider(name="parseStandaloneText") + Object[][] providerStandaloneText() { + // Locale, TemporalField, TextStyle, expected value, input text + return new Object[][] { + {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, + {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, 12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"}, + {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 1, "\u044f\u043d\u0432."}, + {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a."}, + {FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, 2, "tiistai"}, + {FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, 2, "ti"}, + }; + } + + // Test data is dependent on localized resources. + @DataProvider(name="parseLenientText") + Object[][] providerLenientText() { + // Locale, TemporalField, expected value, input text + return new Object[][] { + {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format + {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, // full standalone + {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short format + {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short standalone + }; + } + + @Test(dataProvider="parseStandaloneText") + public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) { + DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale); + ParsePosition pos = new ParsePosition(0); + assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue); + assertEquals(pos.getIndex(), input.length()); + } + + //----------------------------------------------------------------------- + public void test_parse_french_short_strict_full_noMatch() throws Exception { + setStrict(true); + ParsePosition pos = new ParsePosition(0); + getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) + .parseUnresolved("janvier", pos); + assertEquals(pos.getErrorIndex(), 0); + } + + public void test_parse_french_short_strict_short_match() throws Exception { + setStrict(true); + ParsePosition pos = new ParsePosition(0); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) + .parseUnresolved("janv.", pos) + .getLong(MONTH_OF_YEAR), + 1L); + assertEquals(pos.getIndex(), 5); + } + + //----------------------------------------------------------------------- + + @Test(dataProvider="parseLenientText") + public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) { + setStrict(false); + ParsePosition pos = new ParsePosition(0); + DateTimeFormatter formatter = getFormatter(field).withLocale(locale); + assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue); + assertEquals(pos.getIndex(), input.length()); + } + + + //----------------------------------------------------------------------- + @DataProvider(name="parseChronoLocalDate") + Object[][] provider_chronoLocalDate() { + return new Object[][] { + { HijrahDate.now() }, + { JapaneseDate.now() }, + { MinguoDate.now() }, + { ThaiBuddhistDate.now() }}; + } + + private static final DateTimeFormatter fmt_chrono = + new DateTimeFormatterBuilder() + .optionalStart() + .appendChronologyId() + .appendLiteral(' ') + .optionalEnd() + .optionalStart() + .appendText(ChronoField.ERA, TextStyle.SHORT) + .appendLiteral(' ') + .optionalEnd() + .appendValue(ChronoField.YEAR_OF_ERA, 1, 9, SignStyle.NORMAL) + .appendLiteral('-') + .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER) + .appendLiteral('-') + .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER) + .toFormatter(); + + @Test(dataProvider="parseChronoLocalDate") + public void test_chronoLocalDate(ChronoLocalDate date) throws Exception { + System.out.printf(" %s, [fmt=%s]%n", date, fmt_chrono.format(date)); + assertEquals(date, fmt_chrono.parse(fmt_chrono.format(date), ChronoLocalDate::from)); + + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("[GGG ]yyy-MM-dd") + .withChronology(date.getChronology()); + System.out.printf(" %s, [fmt=%s]%n", date.toString(), fmt.format(date)); + assertEquals(date, fmt.parse(fmt.format(date), ChronoLocalDate::from)); + } +} diff --git a/jdk/test/java/time/test/java/time/format/TestTextPrinter.java b/jdk/test/java/time/test/java/time/format/TestTextPrinter.java index d10af2207fb..379d6a23bb0 100644 --- a/jdk/test/java/time/test/java/time/format/TestTextPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestTextPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -84,8 +84,6 @@ import test.java.time.temporal.MockFieldValue; */ @Test public class TestTextPrinter extends AbstractTestPrinterParser { - static final Locale RUSSIAN = new Locale("ru"); - static final Locale FINNISH = new Locale("fi"); //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) @@ -213,32 +211,6 @@ public class TestTextPrinter extends AbstractTestPrinterParser { {Locale.US, "e", "1", DayOfWeek.SUNDAY}, {Locale.US, "ee", "01", DayOfWeek.SUNDAY}, {Locale.US, "c", "1", DayOfWeek.SUNDAY}, - - {Locale.UK, "e", "1", DayOfWeek.MONDAY}, - {Locale.UK, "ee", "01", DayOfWeek.MONDAY}, - {Locale.UK, "c", "1", DayOfWeek.MONDAY}, - }; - } - - @DataProvider(name="print_JapaneseChronology") - Object[][] provider_japaneseEra() { - return new Object[][] { - {ERA, TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names. - {ERA, TextStyle.SHORT, 2, "Heisei"}, - {ERA, TextStyle.NARROW, 2, "H"}, - }; - }; - - // Test data is dependent on localized resources. - @DataProvider(name="print_standalone") - Object[][] provider_StandaloneNames() { - return new Object[][] { - // standalone names for 2013-01-01 (Tue) - // Locale, TemporalField, TextStyle, expected text - {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, "\u044f\u043d\u0432\u0430\u0440\u044c"}, - {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."}, - {FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, "tiistai"}, - {FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, "ti"}, }; } @@ -255,30 +227,6 @@ public class TestTextPrinter extends AbstractTestPrinterParser { assertEquals(text, expected); } - @Test(dataProvider="print_JapaneseChronology") - public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception { - LocalDate ld = LocalDate.of(2013, 1, 31); - getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf); - assertEquals(buf.toString(), expected); - } - - @Test(dataProvider="print_standalone") - public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) { - getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf); - assertEquals(buf.toString(), expected); - } - - //----------------------------------------------------------------------- - public void test_print_french_long() throws Exception { - getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); - assertEquals(buf.toString(), "janvier"); - } - - public void test_print_french_short() throws Exception { - getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); - assertEquals(buf.toString(), "janv."); - } - //----------------------------------------------------------------------- public void test_toString1() throws Exception { assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).toString(), "Text(MonthOfYear)"); diff --git a/jdk/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java b/jdk/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java new file mode 100644 index 00000000000..9c4d7d9e402 --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012, 2016, 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * 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 JSR-310 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. + */ + +/* + * @test + * @modules jdk.localedata + */ + +package test.java.time.format; + +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.ERA; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.IsoFields.QUARTER_OF_YEAR; +import static org.testng.Assert.assertEquals; + +import java.time.DateTimeException; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.chrono.JapaneseChronology; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.time.temporal.TemporalField; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import test.java.time.temporal.MockFieldValue; + +/** + * Test TextPrinterParserWithLocale. + */ +@Test +public class TestTextPrinterWithLocale extends AbstractTestPrinterParser { + static final Locale RUSSIAN = new Locale("ru"); + static final Locale FINNISH = new Locale("fi"); + + //----------------------------------------------------------------------- + @DataProvider(name="print_DayOfWeekData") + Object[][] providerDayOfWeekData() { + return new Object[][] { + // Locale, pattern, expected text, input DayOfWeek + {Locale.US, "e", "1", DayOfWeek.SUNDAY}, + {Locale.US, "ee", "01", DayOfWeek.SUNDAY}, + {Locale.US, "c", "1", DayOfWeek.SUNDAY}, + + {Locale.UK, "e", "1", DayOfWeek.MONDAY}, + {Locale.UK, "ee", "01", DayOfWeek.MONDAY}, + {Locale.UK, "c", "1", DayOfWeek.MONDAY}, + }; + } + + // Test data is dependent on localized resources. + @DataProvider(name="print_standalone") + Object[][] provider_StandaloneNames() { + return new Object[][] { + // standalone names for 2013-01-01 (Tue) + // Locale, TemporalField, TextStyle, expected text + {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE, "\u044f\u043d\u0432\u0430\u0440\u044c"}, + {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."}, + {FINNISH, DAY_OF_WEEK, TextStyle.FULL_STANDALONE, "tiistai"}, + {FINNISH, DAY_OF_WEEK, TextStyle.SHORT_STANDALONE, "ti"}, + }; + } + + @Test(dataProvider="print_DayOfWeekData") + public void test_formatDayOfWeek(Locale locale, String pattern, String expected, DayOfWeek dayOfWeek) { + DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale); + String text = formatter.format(dayOfWeek); + assertEquals(text, expected); + } + + @Test(dataProvider="print_standalone") + public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) { + getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf); + assertEquals(buf.toString(), expected); + } + + //----------------------------------------------------------------------- + public void test_print_french_long() throws Exception { + getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); + assertEquals(buf.toString(), "janvier"); + } + + public void test_print_french_short() throws Exception { + getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); + assertEquals(buf.toString(), "janv."); + } + + @DataProvider(name="print_JapaneseChronology") + Object[][] provider_japaneseEra() { + return new Object[][] { + {ERA, TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names. + {ERA, TextStyle.SHORT, 2, "Heisei"}, + {ERA, TextStyle.NARROW, 2, "H"}, + }; + }; + + @Test(dataProvider="print_JapaneseChronology") + public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception { + LocalDate ld = LocalDate.of(2013, 1, 31); + getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf); + assertEquals(buf.toString(), expected); + } +} From 4a253dcdec262122872f6ec9f4707ce070371d7f Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Wed, 11 Jan 2017 08:53:59 -0800 Subject: [PATCH 05/11] 8075884: check runtime usage tests with multi-release jar files Reviewed-by: psandoz --- .../tools/jar/multiRelease/RuntimeTest.java | 236 ++++++++++++++++++ .../data/runtimetest/MVJarJJSTestScript.js | 30 +++ .../runtimetest/base/testpackage/Helper.java | 33 +++ .../runtimetest/base/testpackage/Main.java | 62 +++++ .../data/runtimetest/base/versionResource | 1 + .../data/runtimetest/manifest.txt | 1 + .../data/runtimetest/test/UseByImport.java | 41 +++ .../runtimetest/test/UseByReflection.java | 64 +++++ .../runtimetest/v10/testpackage/Helper.java | 33 +++ .../runtimetest/v10/testpackage/Main.java | 62 +++++ .../data/runtimetest/v10/versionResource | 1 + .../runtimetest/v9/testpackage/Helper.java | 33 +++ .../data/runtimetest/v9/testpackage/Main.java | 62 +++++ .../data/runtimetest/v9/versionResource | 1 + 14 files changed, 660 insertions(+) create mode 100644 jdk/test/tools/jar/multiRelease/RuntimeTest.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/MVJarJJSTestScript.js create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Helper.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Main.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/base/versionResource create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/manifest.txt create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByImport.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByReflection.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Helper.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Main.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v10/versionResource create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Helper.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Main.java create mode 100644 jdk/test/tools/jar/multiRelease/data/runtimetest/v9/versionResource diff --git a/jdk/test/tools/jar/multiRelease/RuntimeTest.java b/jdk/test/tools/jar/multiRelease/RuntimeTest.java new file mode 100644 index 00000000000..930c07c9a60 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/RuntimeTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2016, 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 Test Multi-Release jar usage in runtime + * @library /test/lib + * @library /lib/testlibrary + * @modules jdk.compiler + * @build jdk.test.lib.JDKToolFinder jdk.test.lib.JDKToolLauncher + * jdk.test.lib.process.OutputAnalyzer + * jdk.test.lib.process.ProcessTools + * CompilerUtils RuntimeTest + * @run testng RuntimeTest + */ + +import static org.testng.Assert.*; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class RuntimeTest { + public static final int SUCCESS = 0; + private final String src = System.getProperty("test.src", "."); + private final String usr = System.getProperty("user.dir", "."); + + @DataProvider(name = "jarFiles") + Object[][] jarFiles() { + return new Object[][] { { "MV_BOTH.jar", 9, 9, 9 }, + { "MV_ONLY_9.jar", 9, 9, 9 }, + { "NON_MV.jar", 8, 8, 8 } }; + } + + @BeforeClass + protected void setUpTest() throws Throwable { + compile(); + Path classes = Paths.get("classes"); + jar("cfm", "MV_BOTH.jar", "manifest.txt", + "-C", classes.resolve("base").toString(), ".", + "--release", "9", "-C", classes.resolve("v9").toString(), ".", + "--release", "10", "-C", classes.resolve("v10").toString(), ".") + .shouldHaveExitValue(0); + + jar("cfm", "MV_ONLY_9.jar", "manifest.txt", + "-C", classes.resolve("base").toString(), ".", + "--release", "9", "-C", classes.resolve("v9").toString(), ".") + .shouldHaveExitValue(0); + jar("cfm", "NON_MV.jar", "manifest.txt", + "-C", classes.resolve("base").toString(), ".") + .shouldHaveExitValue(0); + } + + @Test(dataProvider = "jarFiles") + public void testClasspath(String jar, int mainVer, int helperVer, + int resVer) throws Throwable { + String[] command = { "-cp", jar, "testpackage.Main" }; + System.out.println("Command arguments:" + Arrays.asList(command)); + System.out.println(); + java(command).shouldHaveExitValue(SUCCESS) + .shouldContain("Main version: " + mainVer) + .shouldContain("Helpers version: " + helperVer) + .shouldContain("Resource version: " + resVer); + } + + @Test(dataProvider = "jarFiles") + void testMVJarAsLib(String jar, int mainVer, int helperVer, int resVer) + throws Throwable { + String[] apps = { "UseByImport", "UseByReflection" }; + for (String app : apps) { + String[] command = {"-cp", + jar + File.pathSeparatorChar + "classes/test/", app }; + System.out.println("Command arguments:" + Arrays.asList(command)); + System.out.println(); + java(command).shouldHaveExitValue(SUCCESS) + .shouldContain("Main version: " + mainVer) + .shouldContain("Helpers version: " + helperVer) + .shouldContain("Resource version: " + resVer); + } + } + + @Test(dataProvider = "jarFiles") + void testJavaJar(String jar, int mainVer, int helperVer, int resVer) + throws Throwable { + String[] command = { "-jar", jar }; + System.out.println("Command arguments:" + Arrays.asList(command)); + System.out.println(); + java(command).shouldHaveExitValue(SUCCESS) + .shouldContain("Main version: " + mainVer) + .shouldContain("Helpers version: " + helperVer) + .shouldContain("Resource version: " + resVer); + } + + @Test(dataProvider = "jarFiles") + void testURLClassLoader(String jarName, int mainVer, int helperVer, + int resVer) throws ClassNotFoundException, NoSuchMethodException, + IllegalAccessException, IllegalArgumentException, + InvocationTargetException, IOException { + Path pathToJAR = Paths.get(jarName).toAbsolutePath(); + URL jarURL1 = new URL("jar:file:" + pathToJAR + "!/"); + URL jarURL2 = new URL("file:///" + pathToJAR); + testURLClassLoaderURL(jarURL1, mainVer, helperVer, resVer); + testURLClassLoaderURL(jarURL2, mainVer, helperVer, resVer); + } + + private static void testURLClassLoaderURL(URL jarURL, + int mainVersionExpected, int helperVersionExpected, + int resourceVersionExpected) throws ClassNotFoundException, + NoSuchMethodException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, IOException { + System.out.println( + "Testing URLClassLoader MV JAR support for URL: " + jarURL); + URL[] urls = { jarURL }; + int mainVersionActual; + int helperVersionActual; + int resourceVersionActual; + try (URLClassLoader cl = URLClassLoader.newInstance(urls)) { + Class c = cl.loadClass("testpackage.Main"); + Method getMainVersion = c.getMethod("getMainVersion"); + mainVersionActual = (int) getMainVersion.invoke(null); + Method getHelperVersion = c.getMethod("getHelperVersion"); + helperVersionActual = (int) getHelperVersion.invoke(null); + try (InputStream ris = cl.getResourceAsStream("versionResource"); + BufferedReader br = new BufferedReader( + new InputStreamReader(ris))) { + resourceVersionActual = Integer.parseInt(br.readLine()); + } + } + + assertEquals(mainVersionActual, mainVersionExpected, + "Test failed: Expected Main class version: " + + mainVersionExpected + " Actual version: " + + mainVersionActual); + assertEquals(helperVersionActual, helperVersionExpected, + "Test failed: Expected Helper class version: " + + helperVersionExpected + " Actual version: " + + helperVersionActual); + assertEquals(resourceVersionActual, resourceVersionExpected, + "Test failed: Expected resource version: " + + resourceVersionExpected + " Actual version: " + + resourceVersionActual); + } + + @Test(dataProvider = "jarFiles") + void testJjs(String jar, int mainVer, int helperVer, int resVer) + throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jjs"); + launcher.addToolArg("-cp").addToolArg(jar) + .addToolArg(src + "/data/runtimetest/MVJarJJSTestScript.js"); + ProcessTools.executeCommand(launcher.getCommand()) + .shouldHaveExitValue(SUCCESS) + .shouldContain("Main version: " + mainVer) + .shouldContain("Helpers version: " + helperVer) + .shouldContain("Resource version: " + resVer); + } + + private static OutputAnalyzer jar(String... args) throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar"); + Stream.of(args).forEach(launcher::addToolArg); + return ProcessTools.executeCommand(launcher.getCommand()); + } + + private void compile() throws Throwable { + String[] vers = { "base", "v9", "v10" }; + for (String ver : vers) { + Path classes = Paths.get(usr, "classes", ver); + Files.createDirectories(classes); + Path source = Paths.get(src, "data", "runtimetest", ver); + assertTrue(CompilerUtils.compile(source, classes)); + Files.copy(source.resolve("versionResource"), + classes.resolve("versionResource"), + StandardCopyOption.REPLACE_EXISTING); + } + + Path classes = Paths.get(usr, "classes", "test"); + Files.createDirectory(classes); + Path source = Paths.get(src, "data", "runtimetest", "test"); + assertTrue( + CompilerUtils.compile(source, classes, "-cp", "classes/base/")); + Files.copy(Paths.get(src, "data", "runtimetest", "manifest.txt"), + Paths.get(usr, "manifest.txt"), + StandardCopyOption.REPLACE_EXISTING); + } + + OutputAnalyzer java(String... args) throws Throwable { + String java = JDKToolFinder.getJDKTool("java"); + + List commands = new ArrayList<>(); + commands.add(java); + Stream.of(args).forEach(x -> commands.add(x)); + return ProcessTools.executeCommand(new ProcessBuilder(commands)); + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/MVJarJJSTestScript.js b/jdk/test/tools/jar/multiRelease/data/runtimetest/MVJarJJSTestScript.js new file mode 100644 index 00000000000..5416851537a --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/MVJarJJSTestScript.js @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, 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. + */ + +var Main = Java.type("testpackage.Main"); +var mainVersion = Main.getMainVersion(); +var helperVersion = Main.getHelperVersion(); +var resourceVersion = Main.getResourceVersion(); +print("Main version: " + mainVersion); +print("Helpers version: " + helperVersion); +print("Resource version: " + resourceVersion); diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Helper.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Helper.java new file mode 100644 index 00000000000..6028cf8090d --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Helper.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +public class Helper { + + private static final int HELPER_VERSION = 8; + + public static int getHelperVersion() { + return HELPER_VERSION; + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Main.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Main.java new file mode 100644 index 00000000000..892bbe7329c --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Main.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class Main { + + private static final int MAIN_VERSION = 8; + + public static void main(String[] args) { + System.out.println("Main version: " + getMainVersion()); + System.out.println("Helpers version: " + getHelperVersion()); + System.out.println("Resource version: " + getResourceVersion()); + } + + public static int getMainVersion() { + return MAIN_VERSION; + } + + public static int getHelperVersion() { + return testpackage.Helper.getHelperVersion(); + } + + public static int getResourceVersion() { + ClassLoader cl = Main.class.getClassLoader(); + InputStream ris = cl.getResourceAsStream("versionResource"); + if (ris == null) { + throw new Error("Test issue: resource versionResource" + + " cannot be loaded!"); + } + try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) { + return Integer.parseInt(br.readLine()); + } catch (IOException ioe) { + throw new Error("Unexpected issue", ioe); + } + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/base/versionResource b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/versionResource new file mode 100644 index 00000000000..301160a9306 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/versionResource @@ -0,0 +1 @@ +8 \ No newline at end of file diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/manifest.txt b/jdk/test/tools/jar/multiRelease/data/runtimetest/manifest.txt new file mode 100644 index 00000000000..86aa94faa56 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/manifest.txt @@ -0,0 +1 @@ +Main-Class: testpackage.Main diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByImport.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByImport.java new file mode 100644 index 00000000000..2689a43353c --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByImport.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, 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 testpackage.Main; + +/** + * This class is used in MVJarAsLibraryTest.java test. + * It is a part of the test. + */ +public class UseByImport { + + /** + * Method for the test execution. + * @param args - no args needed + */ + public static void main(String[] args) { + System.out.println("Main version: " + Main.getMainVersion()); + System.out.println("Helpers version: " + Main.getHelperVersion()); + System.out.println("Resource version: " + Main.getResourceVersion()); + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByReflection.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByReflection.java new file mode 100644 index 00000000000..f4934a65037 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByReflection.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, 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.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class is used in RuntimeTest.java. + */ +public class UseByReflection { + + /** + * Method for the test execution. + * + * @param args - no args needed + * @throws java.lang.ClassNotFoundException + * @throws java.lang.NoSuchMethodException + * @throws java.lang.IllegalAccessException + * @throws java.lang.reflect.InvocationTargetException + * @throws java.io.IOException + */ + public static void main(String[] args) throws ClassNotFoundException, + NoSuchMethodException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, IOException { + Class mainClass = Class.forName("testpackage.Main"); + Method getMainVersion = mainClass.getMethod("getMainVersion"); + int mainVersionActual = (int) getMainVersion.invoke(null); + Method getHelperVersion = mainClass.getMethod("getHelperVersion"); + int helperVersionActual = (int) getHelperVersion.invoke(null); + ClassLoader cl = UseByReflection.class.getClassLoader(); + int resourceVersionActual; + try (InputStream ris = cl.getResourceAsStream("versionResource"); + BufferedReader br = new BufferedReader(new InputStreamReader(ris))) { + resourceVersionActual = Integer.parseInt(br.readLine()); + } + System.out.println("Main version: " + mainVersionActual); + System.out.println("Helpers version: " + helperVersionActual); + System.out.println("Resource version: " + resourceVersionActual); + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Helper.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Helper.java new file mode 100644 index 00000000000..7071b436757 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Helper.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +public class Helper { + + private static final int HELPER_VERSION = 10; + + public static int getHelperVersion() { + return HELPER_VERSION; + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Main.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Main.java new file mode 100644 index 00000000000..de6fc15cbbd --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Main.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class Main { + + private static final int MAIN_VERSION = 10; + + public static void main(String[] args) { + System.out.println("Main version: " + getMainVersion()); + System.out.println("Helpers version: " + getHelperVersion()); + System.out.println("Resource version: " + getResourceVersion()); + } + + public static int getMainVersion() { + return MAIN_VERSION; + } + + public static int getHelperVersion() { + return testpackage.Helper.getHelperVersion(); + } + + public static int getResourceVersion() { + ClassLoader cl = Main.class.getClassLoader(); + InputStream ris = cl.getResourceAsStream("versionResource"); + if (ris == null) { + throw new Error("Test issue: resource versionResource" + + " cannot be loaded!"); + } + try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) { + return Integer.parseInt(br.readLine()); + } catch (IOException ioe) { + throw new Error("Unexpected issue", ioe); + } + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/versionResource b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/versionResource new file mode 100644 index 00000000000..f599e28b8ab --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/versionResource @@ -0,0 +1 @@ +10 diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Helper.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Helper.java new file mode 100644 index 00000000000..8d4517d0ee8 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Helper.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +public class Helper { + + private static final int HELPER_VERSION = 9; + + public static int getHelperVersion() { + return HELPER_VERSION; + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Main.java b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Main.java new file mode 100644 index 00000000000..7afcc0efc0e --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Main.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 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. + */ + +package testpackage; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class Main { + + private static final int MAIN_VERSION = 9; + + public static void main(String[] args) { + System.out.println("Main version: " + getMainVersion()); + System.out.println("Helpers version: " + getHelperVersion()); + System.out.println("Resource version: " + getResourceVersion()); + } + + public static int getMainVersion() { + return MAIN_VERSION; + } + + public static int getHelperVersion() { + return testpackage.Helper.getHelperVersion(); + } + + public static int getResourceVersion() { + ClassLoader cl = Main.class.getClassLoader(); + InputStream ris = cl.getResourceAsStream("versionResource"); + if (ris == null) { + throw new Error("Test issue: resource versionResource" + + " cannot be loaded!"); + } + try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) { + return Integer.parseInt(br.readLine()); + } catch (IOException ioe) { + throw new Error("Unexpected issue", ioe); + } + } +} diff --git a/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/versionResource b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/versionResource new file mode 100644 index 00000000000..ec635144f60 --- /dev/null +++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/versionResource @@ -0,0 +1 @@ +9 From 4ec18784014f07b77305ab9f697c00258235e999 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Wed, 11 Jan 2017 19:36:11 -0800 Subject: [PATCH 06/11] 8172314: java/rmi/registry/altSecurityManager/AltSecurityManager.java fails with "port in use" Reviewed-by: rriggs --- .../AltSecurityManager.java | 45 +++++---- .../TestSecurityManager.java | 6 +- .../registry.security.policy | 8 ++ .../altSecurityManager/rmid.security.policy | 7 ++ .../java/rmi/registry/reexport/Reexport.java | 10 +- jdk/test/java/rmi/testlibrary/JavaVM.java | 18 +++- jdk/test/java/rmi/testlibrary/RMID.java | 50 +++++++--- .../rmi/testlibrary/RMIRegistryRunner.java | 79 +++++++++++++++ .../java/rmi/testlibrary/RegistryRunner.java | 20 ++-- .../{REGISTRY.java => RegistryVM.java} | 95 ++++++++++++++++--- jdk/test/java/rmi/testlibrary/TestParams.java | 8 +- .../transport/dgcDeadLock/DGCDeadLock.java | 17 ++-- .../dgcDeadLock/registry.security.policy | 27 ++++++ .../transport/tcp/DeadCachedConnection.java | 10 +- 14 files changed, 320 insertions(+), 80 deletions(-) create mode 100644 jdk/test/java/rmi/registry/altSecurityManager/registry.security.policy create mode 100644 jdk/test/java/rmi/registry/altSecurityManager/rmid.security.policy create mode 100644 jdk/test/java/rmi/testlibrary/RMIRegistryRunner.java rename jdk/test/java/rmi/testlibrary/{REGISTRY.java => RegistryVM.java} (50%) create mode 100644 jdk/test/java/rmi/transport/dgcDeadLock/registry.security.policy diff --git a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java index 2e10313f5fb..4f29e0519b4 100644 --- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java +++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -31,7 +31,9 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary JavaVM RMID TestSecurityManager + * java.base/sun.nio.ch + * @build TestLibrary RMID RMIDSelectorProvider RegistryVM RMIRegistryRunner + * TestSecurityManager * @run main/othervm AltSecurityManager */ @@ -44,7 +46,6 @@ * if registry and rmid take too long to exit. */ public class AltSecurityManager implements Runnable { - private final int regPort; // variable to hold registry and rmid children static JavaVM vm = null; @@ -57,31 +58,34 @@ public class AltSecurityManager implements Runnable { private static final long TIME_OUT = (long)(15000 * TestLibrary.getTimeoutFactor()); - public AltSecurityManager(int port) { - if (port <= 0) { - TestLibrary.bomb("Port must be greater than 0."); - } - - this.regPort = port; - } - public void run() { try { if (utilityToStart.equals(REGISTRY_IMPL)) { - vm = new JavaVM(utilityToStart, - " -Djava.security.manager=TestSecurityManager", - Integer.toString(regPort)); + vm = RegistryVM.createRegistryVMWithRunner( + "RMIRegistryRunner", + "-Djava.security.manager=TestSecurityManager"); } else if (utilityToStart.contains(ACTIVATION)) { - vm = new JavaVM(utilityToStart, - " -Djava.security.manager=TestSecurityManager", - "-port " + Integer.toString(regPort)); + vm = RMID.createRMIDOnEphemeralPortWithOptions( + "-Djava.security.manager=TestSecurityManager"); } else { TestLibrary.bomb("Utility to start must be " + REGISTRY_IMPL + " or " + ACTIVATION); } System.err.println("starting " + utilityToStart); - vm.execute(); + try { + vm.start(); + throw new RuntimeException("Expected exception did not occur!"); + } catch (Exception expected) { + int exit = vm.waitFor(); + if (exit != TestSecurityManager.EXIT_VALUE) { + throw new RuntimeException(utilityToStart + + " exit with an unexpected value " + + exit + "."); + } + System.err.format("Success: starting %s exited with status %d%n", + utilityToStart, TestSecurityManager.EXIT_VALUE); + } } catch (Exception e) { TestLibrary.bomb(e); @@ -96,8 +100,7 @@ public class AltSecurityManager implements Runnable { utilityToStart = utility; try { - int port = TestLibrary.getUnusedRandomPort(); - Thread thread = new Thread(new AltSecurityManager(port)); + Thread thread = new Thread(new AltSecurityManager()); System.err.println("expecting RuntimeException for " + "checkListen in child process"); long start = System.currentTimeMillis(); @@ -116,7 +119,7 @@ public class AltSecurityManager implements Runnable { " terminated on time"); } } finally { - vm.destroy(); + vm.cleanup(); vm = null; } } diff --git a/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java b/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java index e1a6ef85db3..ea291919ad3 100644 --- a/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java +++ b/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -24,6 +24,8 @@ /**/ public class TestSecurityManager extends SecurityManager { + public static final int EXIT_VALUE = 123; + public TestSecurityManager() { } @@ -36,7 +38,7 @@ public class TestSecurityManager extends SecurityManager { // by the main test process to detect that the proper security // manager has been installed in the relevant VMs. // - System.exit(1); + System.exit(EXIT_VALUE); } public void checkExit(int status) { diff --git a/jdk/test/java/rmi/registry/altSecurityManager/registry.security.policy b/jdk/test/java/rmi/registry/altSecurityManager/registry.security.policy new file mode 100644 index 00000000000..5c09bd0d93b --- /dev/null +++ b/jdk/test/java/rmi/registry/altSecurityManager/registry.security.policy @@ -0,0 +1,8 @@ +grant { + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; + permission java.util.PropertyPermission "env.class.path", "read"; + permission java.io.FilePermission ".", "read"; + permission java.util.PropertyPermission "user.dir", "read"; + permission java.lang.RuntimePermission "createClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; +}; diff --git a/jdk/test/java/rmi/registry/altSecurityManager/rmid.security.policy b/jdk/test/java/rmi/registry/altSecurityManager/rmid.security.policy new file mode 100644 index 00000000000..5307f72ce64 --- /dev/null +++ b/jdk/test/java/rmi/registry/altSecurityManager/rmid.security.policy @@ -0,0 +1,7 @@ +grant { + permission java.lang.RuntimePermission "selectorProvider"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read"; + permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; +}; diff --git a/jdk/test/java/rmi/registry/reexport/Reexport.java b/jdk/test/java/rmi/registry/reexport/Reexport.java index b0b29ef9bd4..47320afaf48 100644 --- a/jdk/test/java/rmi/registry/reexport/Reexport.java +++ b/jdk/test/java/rmi/registry/reexport/Reexport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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,7 +29,7 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary REGISTRY RegistryRunner + * @build TestLibrary RegistryVM RegistryRunner * @run main/othervm Reexport */ @@ -114,7 +114,7 @@ public class Reexport { public static void makeRegistry() { try { - subreg = REGISTRY.createREGISTRY(); + subreg = RegistryVM.createRegistryVM(); subreg.start(); port = subreg.getPort(); System.out.println("Starting registry on port " + port); @@ -125,12 +125,12 @@ public class Reexport { } } - private static REGISTRY subreg = null; + private static RegistryVM subreg = null; private static int port = -1; public static void killRegistry() { if (subreg != null) { - subreg.shutdown(); + subreg.cleanup(); subreg = null; } } diff --git a/jdk/test/java/rmi/testlibrary/JavaVM.java b/jdk/test/java/rmi/testlibrary/JavaVM.java index 087e700391e..5c841f5426b 100644 --- a/jdk/test/java/rmi/testlibrary/JavaVM.java +++ b/jdk/test/java/rmi/testlibrary/JavaVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -229,6 +229,22 @@ public class JavaVM { vm = null; } + /** + * Return exit value for vm process. + * @return exit value for vm process + * @throws IllegalThreadStateException if the vm process has not yet terminated + */ + public int exitValue() { + return vm.exitValue(); + } + + /** + * Destroy the vm process, and do necessary cleanup. + */ + public void cleanup() { + destroy(); + } + /** * Destroys the VM, waits for it to terminate, and returns * its exit status. diff --git a/jdk/test/java/rmi/testlibrary/RMID.java b/jdk/test/java/rmi/testlibrary/RMID.java index 07628fb2358..a2135b3a9b0 100644 --- a/jdk/test/java/rmi/testlibrary/RMID.java +++ b/jdk/test/java/rmi/testlibrary/RMID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -140,18 +140,6 @@ public class RMID extends JavaVM { } private static String makeArgs(boolean includePortArg, int port) { - String propagateManager = null; - - // rmid will run with a security manager set, but no policy - // file - it should not need one. - if (System.getSecurityManager() == null) { - propagateManager = MANAGER_OPTION + - TestParams.defaultSecurityManager; - } else { - propagateManager = MANAGER_OPTION + - System.getSecurityManager().getClass().getName(); - } - // getAbsolutePath requires permission to read user.dir String args = " -log " + (new File(LOGDIR, log)).getAbsolutePath(); @@ -209,8 +197,31 @@ public class RMID extends JavaVM { public static RMID createRMID(OutputStream out, OutputStream err, boolean debugExec, boolean includePortArg, int port) + { + return createRMIDWithOptions(out, err, debugExec, includePortArg, port, ""); + } + + /** + * Create a RMID on a specified port capturing stdout and stderr + * with additional command line options and whether to print out + * debugging information that is used for spawning activation groups. + * + * @param out the OutputStream where the normal output of the + * rmid subprocess goes + * @param err the OutputStream where the error output of the + * rmid subprocess goes + * @param debugExec whether to print out debugging information + * @param includePortArg whether to include port argument + * @param port the port on which rmid accepts requests + * @param additionalOptions additional command line options + * @return a RMID instance + */ + public static RMID createRMIDWithOptions(OutputStream out, OutputStream err, + boolean debugExec, boolean includePortArg, + int port, String additionalOptions) { String options = makeOptions(port, debugExec, false); + options += " " + additionalOptions; String args = makeArgs(includePortArg, port); RMID rmid = new RMID("sun.rmi.server.Activation", options, args, out, err, port); @@ -223,6 +234,19 @@ public class RMID extends JavaVM { return createRMID(System.out, System.err, true, false, 0); } + /** + * Create a RMID on an ephemeral port capturing stdout and stderr + * with additional command line options. + * + * @param additionalOptions additional command line options + * @return a RMID instance + */ + public static RMID createRMIDOnEphemeralPortWithOptions( + String additionalOptions) { + return createRMIDWithOptions(System.out, System.err, + true, false, 0, additionalOptions); + } + public static RMID createRMIDOnEphemeralPort(OutputStream out, OutputStream err, boolean debugExec) diff --git a/jdk/test/java/rmi/testlibrary/RMIRegistryRunner.java b/jdk/test/java/rmi/testlibrary/RMIRegistryRunner.java new file mode 100644 index 00000000000..3be51e95e14 --- /dev/null +++ b/jdk/test/java/rmi/testlibrary/RMIRegistryRunner.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, 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.rmi.*; +import java.rmi.registry.*; +import java.rmi.server.*; + +/** + * Class to run a rmiregistry whose VM can be told to exit remotely; + * Difference between this class and RegistryRunner is that this class + * simulate rmiregistry closer than RegistryRunner. + */ +public class RMIRegistryRunner extends RegistryRunner +{ + public RMIRegistryRunner() throws RemoteException { + } + + /** + * port 0 means to use ephemeral port to start registry. + * + * @param args command line arguments passed in from main + * @return the port number on which registry accepts requests + */ + protected static int init(String[] args) { + try { + if (args.length == 0) { + System.err.println("Usage: "); + System.exit(0); + } + int port = -1; + port = Integer.parseInt(args[0]); + + // call RegistryImpl.createRegistry to simulate rmiregistry. + registry = sun.rmi.registry.RegistryImpl.createRegistry(port); + if (port == 0) { + port = TestLibrary.getRegistryPort(registry); + } + + // create a remote object to tell this VM to exit + exiter = new RMIRegistryRunner(); + Naming.rebind("rmi://localhost:" + port + + "/RemoteExiter", exiter); + + return port; + } catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + System.exit(1); + } + return -1; + } + + public static void main(String[] args) { + int port = init(args); + notify(port); + } +} diff --git a/jdk/test/java/rmi/testlibrary/RegistryRunner.java b/jdk/test/java/rmi/testlibrary/RegistryRunner.java index e8c9ab45873..a604a8d0027 100644 --- a/jdk/test/java/rmi/testlibrary/RegistryRunner.java +++ b/jdk/test/java/rmi/testlibrary/RegistryRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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,7 +29,7 @@ import java.rmi.server.*; /** * Class to run a registry whose VM can be told to exit remotely; using - * the rmiregistry in this fashion makes tests more robust under + * a registry (in a sub-process) in this fashion makes tests more robust under * windows where Process.destroy() seems not to be 100% reliable. */ public class RegistryRunner extends UnicastRemoteObject @@ -38,8 +38,8 @@ public class RegistryRunner extends UnicastRemoteObject private static final String PORT_LABEL_START = "RegistryRunner.port.start:"; private static final String PORT_LABEL_END = ":RegistryRunner.port.end"; - private static Registry registry = null; - private static RemoteExiter exiter = null; + protected static Registry registry = null; + protected static RemoteExiter exiter = null; public RegistryRunner() throws RemoteException { } @@ -72,6 +72,7 @@ public class RegistryRunner extends UnicastRemoteObject } catch (RemoteException re) { } e = null; + } catch (java.net.MalformedURLException mfue) { // will not happen } catch (NotBoundException nbe) { @@ -97,6 +98,9 @@ public class RegistryRunner extends UnicastRemoteObject /** * port 0 means to use ephemeral port to start registry. + * + * @param args command line arguments passed in from main + * @return the port number on which registry accepts requests */ protected static int init(String[] args) { try { @@ -128,13 +132,15 @@ public class RegistryRunner extends UnicastRemoteObject } /** - * REGISTRY.start() will filter the output of registry subprocess, - * when valid port is detected, REGISTRY.start() returns. + * RegistryVM.start() will filter the output of registry subprocess, + * when valid port is detected, RegistryVM.start() returns. * So, for subclass, it's important to call this method after registry * is initialized and necessary remote objects have been bound. + * + * @param port the port on which registry accepts requests */ protected static void notify(int port) { - // this output is important for REGISTRY to get the port + // this output is important for RegistryVM to get the port // where rmiregistry is serving System.out.println(PORT_LABEL_START + port + PORT_LABEL_END); System.out.flush(); diff --git a/jdk/test/java/rmi/testlibrary/REGISTRY.java b/jdk/test/java/rmi/testlibrary/RegistryVM.java similarity index 50% rename from jdk/test/java/rmi/testlibrary/REGISTRY.java rename to jdk/test/java/rmi/testlibrary/RegistryVM.java index 6cd866a70da..69b9d8f4f1d 100644 --- a/jdk/test/java/rmi/testlibrary/REGISTRY.java +++ b/jdk/test/java/rmi/testlibrary/RegistryVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -25,13 +25,15 @@ import java.io.OutputStream; import java.io.IOException; /** - * Class to run and control rmiregistry in a sub-process. + * Class to run and control registry/rmiregistry in a sub-process. + * The behaviour changes when use different runner, currently + * there are 2 built-in runners, RegistryRunner and RMIRegistryRunner. * * We can't kill a registry if we have too-close control * over it. We must make it in a subprocess, and then kill the * subprocess when it has served our needs. */ -public class REGISTRY extends JavaVM { +public class RegistryVM extends JavaVM { private static final double START_TIMEOUT = 20_000 * TestLibrary.getTimeoutFactor(); @@ -39,7 +41,7 @@ public class REGISTRY extends JavaVM { private int port = -1; - private REGISTRY(String runner, OutputStream out, OutputStream err, + private RegistryVM(String runner, OutputStream out, OutputStream err, String options, int port) { super(runner, options, Integer.toString(port), out, err); try { @@ -54,33 +56,86 @@ public class REGISTRY extends JavaVM { this.port = port; } - public static REGISTRY createREGISTRY() { - return createREGISTRYWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0); + /** + * Create a RegistryVM instance on an ephemeral port. + * + * @return a RegistryVM instance + */ + public static RegistryVM createRegistryVM() { + return createRegistryVMWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0); } - public static REGISTRY createREGISTRY(OutputStream out, OutputStream err, - String options, int port) { - return createREGISTRYWithRunner(DEFAULT_RUNNER, out, err, options, port); + /** + * Create a RegistryVM instance on an ephemeral port with additional + * command line options. + * + * @param options command line options + * @return a RegistryVM instance + */ + public static RegistryVM createRegistryVM(String options) { + return createRegistryVMWithRunner( + DEFAULT_RUNNER, System.out, System.err, options, 0); } - public static REGISTRY createREGISTRYWithRunner(String runner, String options) { - return createREGISTRYWithRunner(runner, System.out, System.err, options, 0); + /** + * Create a RegistryVM instance on a specified port capturing stdout and + * stderr with additional command line options. + * + * @param out the OutputStream where the normal output of the + * registry subprocess goes + * @param err the OutputStream where the error output of the + * registry subprocess goes + * @param options the command line options + * @param port the port on which Registry accepts requests + * @return a RegistryVM instance + */ + public static RegistryVM createRegistryVM(OutputStream out, OutputStream err, + String options, int port) { + return createRegistryVMWithRunner(DEFAULT_RUNNER, out, err, options, port); } - public static REGISTRY createREGISTRYWithRunner(String runner, OutputStream out, + /** + * Create a RegistryVM instance on an ephemeral port with additional + * command line options and a specified runner. + * + * @param runner the runner class name + * @param options command line options + * @return a RegistryVM instance + */ + public static RegistryVM createRegistryVMWithRunner(String runner, String options) { + return createRegistryVMWithRunner(runner, System.out, System.err, options, 0); + } + + /** + * Create a RegistryVM instance on a specified port capturing stdout and + * stderr with additional command line options and a specified runner. + * + * @param runner the runner class name + * @param out the OutputStream where the normal output of the + * registry subprocess goes + * @param err the OutputStream where the error output of the + * registry subprocess goes + * @param options the command line options + * @param port the port on which Registry accepts requests + * @return a RegistryVM instance + */ + public static RegistryVM createRegistryVMWithRunner(String runner, OutputStream out, OutputStream err, String options, int port) { options += " --add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED" + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED" + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED" + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"; - REGISTRY reg = new REGISTRY(runner, out, err, options, port); - return reg; + RegistryVM reg = new RegistryVM(runner, out, err, options, port); + reg.setPolicyFile(TestParams.defaultRegistryPolicy); + return reg; } /** * Starts the registry in a sub-process and waits up to * the given timeout period to confirm that it's running, * and get the port where it's running. + * + * @throws IOException if fails to start subprocess */ public void start() throws IOException { super.start(); @@ -96,6 +151,12 @@ public class REGISTRY extends JavaVM { if (port != -1) { break; } + try { + int exit = vm.exitValue(); + TestLibrary.bomb("[RegistryVM] registry sub-process exited with status " + + exit + "."); + } catch (IllegalThreadStateException ignore) { } + if (System.currentTimeMillis() > deadline) { TestLibrary.bomb("Failed to start registry, giving up after " + (System.currentTimeMillis() - startTime) + "ms.", null); @@ -106,12 +167,16 @@ public class REGISTRY extends JavaVM { /** * Shuts down the registry. */ - public void shutdown() { + @Override + public void cleanup() { RegistryRunner.requestExit(port); + super.destroy(); } /** * Gets the port where the registry is serving. + * + * @return the port where the registry is serving */ public int getPort() { return port; diff --git a/jdk/test/java/rmi/testlibrary/TestParams.java b/jdk/test/java/rmi/testlibrary/TestParams.java index 5f60efbd639..4b1f4d6e6e7 100644 --- a/jdk/test/java/rmi/testlibrary/TestParams.java +++ b/jdk/test/java/rmi/testlibrary/TestParams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -42,6 +42,9 @@ public class TestParams { /** name of default security policy for RMID */ public static final String defaultRmidPolicy; + /** name of default security policy for RegistryVM */ + public static final String defaultRegistryPolicy; + /** name of default security policy for activation groups */ public static final String defaultGroupPolicy; @@ -69,6 +72,9 @@ public class TestParams { defaultRmidPolicy = testSrc + File.separatorChar + "rmid.security.policy"; + defaultRegistryPolicy = + testSrc + File.separatorChar + "registry.security.policy"; + defaultGroupPolicy = testSrc + File.separatorChar + "group.security.policy"; diff --git a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java index 9d700c4786b..295646cab5d 100644 --- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java +++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -33,7 +33,7 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary Test TestImpl REGISTRY RegistryRunner + * @build TestLibrary Test TestImpl RegistryVM RegistryRunner * @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock */ @@ -68,21 +68,18 @@ public class DGCDeadLock implements Runnable { static public void main(String[] args) { - REGISTRY testImplVM = null; + RegistryVM testImplVM = null; System.err.println("\nregression test for 4118056\n"); TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager"); try { - String options = " -Djava.security.policy=" + - TestParams.defaultPolicy + - " --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" + + String options = " --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" + " -Djava.rmi.dgc.leaseValue=500000" + " -Dsun.rmi.dgc.checkInterval=" + - (HOLD_TARGET_TIME - 5000) + - "" ; + (HOLD_TARGET_TIME - 5000); - testImplVM = REGISTRY.createREGISTRYWithRunner("TestImpl", options); + testImplVM = RegistryVM.createRegistryVMWithRunner("TestImpl", options); testImplVM.start(); registryPort = testImplVM.getPort(); @@ -107,7 +104,7 @@ public class DGCDeadLock implements Runnable { TestLibrary.bomb("test failed in main()", e); } finally { if (testImplVM != null) { - testImplVM.shutdown(); + testImplVM.cleanup(); testImplVM = null; } } diff --git a/jdk/test/java/rmi/transport/dgcDeadLock/registry.security.policy b/jdk/test/java/rmi/transport/dgcDeadLock/registry.security.policy new file mode 100644 index 00000000000..926d8787fd9 --- /dev/null +++ b/jdk/test/java/rmi/transport/dgcDeadLock/registry.security.policy @@ -0,0 +1,27 @@ +/* + * security policy used by the registry sub-process + */ + +grant { + // used by TestLibrary to determine extra commandline properties + permission java.io.FilePermission "..${/}..${/}test.props", "read"; + + // property specifically accessed by this test. + permission java.util.PropertyPermission "sun.rmi.transport.cleanInterval", "write"; + permission java.util.PropertyPermission "package.restrict.access.sun", "read"; + permission java.util.PropertyPermission "package.restrict.access.sun.rmi", "read"; + + // test needs to use java to exec an EchoImpl object + permission java.io.FilePermission "${java.home}${/}bin${/}java", "execute"; + + // used by TestLibrary to determine test environment + permission java.util.PropertyPermission "test.*", "read"; + permission java.util.PropertyPermission "user.dir", "read"; + permission java.util.PropertyPermission "java.home", "read"; + + permission java.util.PropertyPermission "java.security.policy", "read"; + permission java.util.PropertyPermission "java.security.manager", "read"; + + // test needs to export rmid and communicate with objects on arbitrary ports + permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; +}; diff --git a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java index cbc34f7687e..b63869ef2e3 100644 --- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java +++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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,7 +29,7 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary REGISTRY RegistryRunner + * @build TestLibrary RegistryVM RegistryRunner * @run main/othervm DeadCachedConnection */ @@ -100,7 +100,7 @@ public class DeadCachedConnection { public static int makeRegistry(int port) { try { - subreg = REGISTRY.createREGISTRY(System.out, System.err, "", port); + subreg = RegistryVM.createRegistryVM(System.out, System.err, "", port); subreg.start(); int regPort = subreg.getPort(); System.out.println("Starting registry on port " + regPort); @@ -113,11 +113,11 @@ public class DeadCachedConnection { return -1; } - private static REGISTRY subreg = null; + private static RegistryVM subreg = null; public static void killRegistry() throws InterruptedException { if (subreg != null) { - subreg.shutdown(); + subreg.cleanup(); subreg = null; } } From 186fec9a8a6aeb739ebecd2233c25fe119e039f6 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 12 Jan 2017 11:41:51 +0000 Subject: [PATCH 07/11] 8168149: Examine the behavior of jmod command-line options - repeating vs last one wins Reviewed-by: mchung --- .../classes/jdk/tools/jmod/JmodTask.java | 129 ++++++++++-------- jdk/test/tools/jmod/JmodTest.java | 72 +++++++++- 2 files changed, 145 insertions(+), 56 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index beb70184f18..4a8839ee16a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -1088,34 +1088,58 @@ public class JmodTask { } } - static class ClassPathConverter implements ValueConverter { - static final ValueConverter INSTANCE = new ClassPathConverter(); + /** + * An abstract converter that given a string representing a list of paths, + * separated by the File.pathSeparator, returns a List of java.nio.Path's. + * Specific subclasses should do whatever validation is required on the + * individual path elements, if any. + */ + static abstract class AbstractPathConverter implements ValueConverter> { + @Override + public List convert(String value) { + List paths = new ArrayList<>(); + String[] pathElements = value.split(File.pathSeparator); + for (String pathElement : pathElements) { + paths.add(toPath(pathElement)); + } + return paths; + } + + @SuppressWarnings("unchecked") + @Override + public Class> valueType() { + return (Class>)(Object)List.class; + } + + @Override public String valuePattern() { return "path"; } + + abstract Path toPath(String path); + } + + static class ClassPathConverter extends AbstractPathConverter { + static final ValueConverter> INSTANCE = new ClassPathConverter(); @Override - public Path convert(String value) { + public Path toPath(String value) { try { Path path = CWD.resolve(value); if (Files.notExists(path)) throw new CommandException("err.path.not.found", path); - if (! (Files.isDirectory(path) || - (Files.isRegularFile(path) && path.toString().endsWith(".jar")))) + if (!(Files.isDirectory(path) || + (Files.isRegularFile(path) && path.toString().endsWith(".jar")))) throw new CommandException("err.invalid.class.path.entry", path); return path; } catch (InvalidPathException x) { throw new CommandException("err.path.not.valid", value); } } - - @Override public Class valueType() { return Path.class; } - - @Override public String valuePattern() { return "path"; } } - static class DirPathConverter implements ValueConverter { - static final ValueConverter INSTANCE = new DirPathConverter(); + static class DirPathConverter extends AbstractPathConverter { + static final ValueConverter> INSTANCE = new DirPathConverter(); @Override - public Path convert(String value) { + public Path toPath(String value) { try { Path path = CWD.resolve(value); if (Files.notExists(path)) @@ -1127,10 +1151,6 @@ public class JmodTask { throw new CommandException("err.path.not.valid", value); } } - - @Override public Class valueType() { return Path.class; } - - @Override public String valuePattern() { return "path"; } } static class ExtractDirPathConverter implements ValueConverter { @@ -1142,12 +1162,6 @@ public class JmodTask { if (Files.exists(path)) { if (!Files.isDirectory(path)) throw new CommandException("err.cannot.create.dir", path); - } else { - try { - Files.createDirectories(path); - } catch (IOException ioe) { - throw new CommandException("err.cannot.create.dir", path); - } } return path; } catch (InvalidPathException x) { @@ -1316,22 +1330,19 @@ public class JmodTask { options = new Options(); parser.formatHelpWith(new JmodHelpFormatter(options)); - OptionSpec classPath + OptionSpec> classPath = parser.accepts("class-path", getMessage("main.opt.class-path")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(ClassPathConverter.INSTANCE); - OptionSpec cmds + OptionSpec> cmds = parser.accepts("cmds", getMessage("main.opt.cmds")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); - OptionSpec config + OptionSpec> config = parser.accepts("config", getMessage("main.opt.config")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); OptionSpec dir @@ -1359,22 +1370,19 @@ public class JmodTask { OptionSpec helpExtra = parser.accepts("help-extra", getMessage("main.opt.help-extra")); - OptionSpec headerFiles + OptionSpec> headerFiles = parser.accepts("header-files", getMessage("main.opt.header-files")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); - OptionSpec libs + OptionSpec> libs = parser.accepts("libs", getMessage("main.opt.libs")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); - OptionSpec legalNotices + OptionSpec> legalNotices = parser.accepts("legal-notices", getMessage("main.opt.legal-notices")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); @@ -1383,17 +1391,15 @@ public class JmodTask { .withRequiredArg() .describedAs(getMessage("main.opt.main-class.arg")); - OptionSpec manPages + OptionSpec> manPages = parser.accepts("man-pages", getMessage("main.opt.man-pages")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); - OptionSpec modulePath + OptionSpec> modulePath = parser.acceptsAll(Set.of("p", "module-path"), getMessage("main.opt.module-path")) .withRequiredArg() - .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); OptionSpec moduleVersion @@ -1452,48 +1458,48 @@ public class JmodTask { } if (opts.has(classPath)) - options.classpath = opts.valuesOf(classPath); + options.classpath = getLastElement(opts.valuesOf(classPath)); if (opts.has(cmds)) - options.cmds = opts.valuesOf(cmds); + options.cmds = getLastElement(opts.valuesOf(cmds)); if (opts.has(config)) - options.configs = opts.valuesOf(config); + options.configs = getLastElement(opts.valuesOf(config)); if (opts.has(dir)) - options.extractDir = opts.valueOf(dir); + options.extractDir = getLastElement(opts.valuesOf(dir)); if (opts.has(dryrun)) options.dryrun = true; if (opts.has(excludes)) - options.excludes = opts.valuesOf(excludes); + options.excludes = opts.valuesOf(excludes); // excludes is repeatable if (opts.has(libs)) - options.libs = opts.valuesOf(libs); + options.libs = getLastElement(opts.valuesOf(libs)); if (opts.has(headerFiles)) - options.headerFiles = opts.valuesOf(headerFiles); + options.headerFiles = getLastElement(opts.valuesOf(headerFiles)); if (opts.has(manPages)) - options.manPages = opts.valuesOf(manPages); + options.manPages = getLastElement(opts.valuesOf(manPages)); if (opts.has(legalNotices)) - options.legalNotices = opts.valuesOf(legalNotices); + options.legalNotices = getLastElement(opts.valuesOf(legalNotices)); if (opts.has(modulePath)) { - Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]); + Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]); options.moduleFinder = new ModulePath(Runtime.version(), true, dirs); } if (opts.has(moduleVersion)) - options.moduleVersion = opts.valueOf(moduleVersion); + options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion)); if (opts.has(mainClass)) - options.mainClass = opts.valueOf(mainClass); + options.mainClass = getLastElement(opts.valuesOf(mainClass)); if (opts.has(osName)) - options.osName = opts.valueOf(osName); + options.osName = getLastElement(opts.valuesOf(osName)); if (opts.has(osArch)) - options.osArch = opts.valueOf(osArch); + options.osArch = getLastElement(opts.valuesOf(osArch)); if (opts.has(osVersion)) - options.osVersion = opts.valueOf(osVersion); + options.osVersion = getLastElement(opts.valuesOf(osVersion)); if (opts.has(warnIfResolved)) - options.moduleResolution = opts.valueOf(warnIfResolved); + options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved)); if (opts.has(doNotResolveByDefault)) { if (options.moduleResolution == null) options.moduleResolution = ModuleResolution.empty(); options.moduleResolution = options.moduleResolution.withDoNotResolveByDefault(); } if (opts.has(hashModules)) { - options.modulesToHash = opts.valueOf(hashModules); + options.modulesToHash = getLastElement(opts.valuesOf(hashModules)); // if storing hashes then the module path is required if (options.moduleFinder == null) throw new CommandException("err.modulepath.must.be.specified") @@ -1531,6 +1537,13 @@ public class JmodTask { throw new CommandException("err.classpath.must.be.specified").showUsage(true); if (options.mainClass != null && !isValidJavaIdentifier(options.mainClass)) throw new CommandException("err.invalid.main-class", options.mainClass); + if (options.mode.equals(Mode.EXTRACT) && options.extractDir != null) { + try { + Files.createDirectories(options.extractDir); + } catch (IOException ioe) { + throw new CommandException("err.cannot.create.dir", options.extractDir); + } + } } catch (OptionException e) { throw new CommandException(e.getMessage()); } @@ -1558,6 +1571,12 @@ public class JmodTask { return true; } + static E getLastElement(List list) { + if (list.size() == 0) + throw new InternalError("Unexpected 0 list size"); + return list.get(list.size() - 1); + } + private void reportError(String message) { out.println(getMessage("error.prefix") + " " + message); } diff --git a/jdk/test/tools/jmod/JmodTest.java b/jdk/test/tools/jmod/JmodTest.java index 4a6a1c51479..8ed6343696d 100644 --- a/jdk/test/tools/jmod/JmodTest.java +++ b/jdk/test/tools/jmod/JmodTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8142968 8166568 8166286 8170618 + * @bug 8142968 8166568 8166286 8170618 8168149 * @summary Basic test for jmod * @library /lib/testlibrary * @modules jdk.compiler @@ -458,6 +458,76 @@ public class JmodTest { ); } + @Test + public void testLastOneWins() throws IOException { + Path workDir = Paths.get("lastOneWins"); + if (Files.exists(workDir)) + FileUtils.deleteFileTreeWithRetry(workDir); + Files.createDirectory(workDir); + Path jmod = MODS_DIR.resolve("lastOneWins.jmod"); + FileUtils.deleteFileIfExistsWithRetry(jmod); + Path cp = EXPLODED_DIR.resolve("foo").resolve("classes"); + Path bp = EXPLODED_DIR.resolve("foo").resolve("bin"); + Path lp = EXPLODED_DIR.resolve("foo").resolve("lib"); + Path cf = EXPLODED_DIR.resolve("foo").resolve("conf"); + + Path shouldNotBeAdded = workDir.resolve("shouldNotBeAdded"); + Files.createDirectory(shouldNotBeAdded); + Files.write(shouldNotBeAdded.resolve("aFile"), "hello".getBytes(UTF_8)); + + // Pairs of options. For options with required arguments the last one + // should win ( first should be effectively ignored, but may still be + // validated ). + jmod("create", + "--conf", shouldNotBeAdded.toString(), + "--conf", cf.toString(), + "--cmds", shouldNotBeAdded.toString(), + "--cmds", bp.toString(), + "--libs", shouldNotBeAdded.toString(), + "--libs", lp.toString(), + "--class-path", shouldNotBeAdded.toString(), + "--class-path", cp.toString(), + "--main-class", "does.NotExist", + "--main-class", "jdk.test.foo.Foo", + "--module-version", "00001", + "--module-version", "5.4.3", + "--do-not-resolve-by-default", + "--do-not-resolve-by-default", + "--warn-if-resolved=incubating", + "--warn-if-resolved=deprecated", + MODS_DIR.resolve("lastOneWins.jmod").toString()) + .assertSuccess() + .resultChecker(r -> { + ModuleDescriptor md = getModuleDescriptor(jmod); + Optional omc = md.mainClass(); + assertTrue(omc.isPresent()); + assertEquals(omc.get(), "jdk.test.foo.Foo"); + Optional ov = md.version(); + assertTrue(ov.isPresent()); + assertEquals(ov.get().toString(), "5.4.3"); + + try (Stream s1 = findFiles(lp).map(p -> LIBS_PREFIX + p); + Stream s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p); + Stream s3 = findFiles(bp).map(p -> CMDS_PREFIX + p); + Stream s4 = findFiles(cf).map(p -> CONFIGS_PREFIX + p)) { + Set expectedFilenames = Stream.concat(Stream.concat(s1,s2), + Stream.concat(s3, s4)) + .collect(toSet()); + assertJmodContent(jmod, expectedFilenames); + } + }); + + jmod("extract", + "--dir", "blah", + "--dir", "lastOneWinsExtractDir", + jmod.toString()) + .assertSuccess() + .resultChecker(r -> { + assertTrue(Files.exists(Paths.get("lastOneWinsExtractDir"))); + assertTrue(Files.notExists(Paths.get("blah"))); + }); + } + @Test public void testPackagesAttribute() throws IOException { Path jmod = MODS_DIR.resolve("foo.jmod"); From a004b7fb9e6750af8c65365b32741906e17378ac Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 12 Jan 2017 13:38:27 +0100 Subject: [PATCH 08/11] 8166365: Small immutable collections should provide optimized implementations when possible Reviewed-by: smarks, psandoz, attila --- .../share/classes/java/util/Collections.java | 20 +- .../java/util/ImmutableCollections.java | 193 +++++++++++++++--- .../classes/java/util/KeyValueHolder.java | 6 +- .../share/classes/java/util/List.java | 5 +- .../share/classes/java/util/Map.java | 5 +- .../share/classes/java/util/Set.java | 5 +- .../java/util/Collection/SetFactories.java | 15 +- jdk/test/java/util/Map/MapFactories.java | 21 +- 8 files changed, 228 insertions(+), 42 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java index 7119fff3e89..02d656cb574 100644 --- a/jdk/src/java.base/share/classes/java/util/Collections.java +++ b/jdk/src/java.base/share/classes/java/util/Collections.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -4354,6 +4354,11 @@ public class Collections { private Object readResolve() { return EMPTY_SET; } + + @Override + public int hashCode() { + return 0; + } } /** @@ -4786,6 +4791,10 @@ public class Collections { public boolean removeIf(Predicate filter) { throw new UnsupportedOperationException(); } + @Override + public int hashCode() { + return Objects.hashCode(element); + } } /** @@ -4848,6 +4857,10 @@ public class Collections { public Spliterator spliterator() { return singletonSpliterator(element); } + @Override + public int hashCode() { + return Objects.hashCode(element); + } } /** @@ -4970,6 +4983,11 @@ public class Collections { BiFunction remappingFunction) { throw new UnsupportedOperationException(); } + + @Override + public int hashCode() { + return Objects.hashCode(k) ^ Objects.hashCode(v); + } } // Miscellaneous diff --git a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java index 26a03e0dae6..2bc0cc1b5d9 100644 --- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -35,6 +35,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; +import jdk.internal.vm.annotation.Stable; /** * Container class for immutable collections. Not part of the public API. @@ -105,6 +106,11 @@ class ImmutableCollections { return null; // but the compiler doesn't know this } + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -112,9 +118,26 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_LIST); } + + @Override + public boolean contains(Object o) { + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection o) { + return o.isEmpty(); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 1; + } } static final class List1 extends AbstractImmutableList { + @Stable private final E e0; List1(E e0) { @@ -129,7 +152,6 @@ class ImmutableCollections { @Override public E get(int index) { Objects.checkIndex(index, 1); - // assert index == 0 return e0; } @@ -140,10 +162,22 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_LIST, e0); } + + @Override + public boolean contains(Object o) { + return o.equals(e0); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 31 + e0.hashCode(); + } } static final class List2 extends AbstractImmutableList { + @Stable private final E e0; + @Stable private final E e1; List2(E e0, E e1) { @@ -166,6 +200,17 @@ class ImmutableCollections { } } + @Override + public boolean contains(Object o) { + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + int hash = 31 + e0.hashCode(); + return 31 * hash + e1.hashCode(); + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -176,6 +221,7 @@ class ImmutableCollections { } static final class ListN extends AbstractImmutableList { + @Stable private final E[] elements; @SafeVarargs @@ -200,6 +246,25 @@ class ImmutableCollections { return elements[index]; } + @Override + public boolean contains(Object o) { + for (E e : elements) { + if (o.equals(e)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 1; + for (E e : elements) { + hash = 31 * hash + e.hashCode(); + } + return hash; + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -238,7 +303,13 @@ class ImmutableCollections { @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection o) { + return o.isEmpty(); // implicit nullcheck of o } @Override @@ -253,9 +324,15 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_SET); } + + @Override + public int hashCode() { + return 0; + } } static final class Set1 extends AbstractImmutableSet { + @Stable private final E e0; Set1(E e0) { @@ -269,7 +346,7 @@ class ImmutableCollections { @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + return o.equals(e0); // implicit nullcheck of o } @Override @@ -284,17 +361,21 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_SET, e0); } + + @Override + public int hashCode() { + return e0.hashCode(); + } } static final class Set2 extends AbstractImmutableSet { - private final E e0; - private final E e1; + @Stable + final E e0; + @Stable + final E e1; Set2(E e0, E e1) { - Objects.requireNonNull(e0); - Objects.requireNonNull(e1); - - if (e0.equals(e1)) { + if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0 throw new IllegalArgumentException("duplicate element: " + e0); } @@ -314,7 +395,12 @@ class ImmutableCollections { @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return e0.hashCode() + e1.hashCode(); } @Override @@ -358,8 +444,10 @@ class ImmutableCollections { * @param the element type */ static final class SetN extends AbstractImmutableSet { - private final E[] elements; - private final int size; + @Stable + final E[] elements; + @Stable + final int size; @SafeVarargs @SuppressWarnings("unchecked") @@ -368,8 +456,8 @@ class ImmutableCollections { elements = (E[])new Object[EXPAND_FACTOR * input.length]; for (int i = 0; i < input.length; i++) { - E e = Objects.requireNonNull(input[i]); - int idx = probe(e); + E e = input[i]; + int idx = probe(e); // implicit nullcheck of e if (idx >= 0) { throw new IllegalArgumentException("duplicate element: " + e); } else { @@ -385,8 +473,7 @@ class ImmutableCollections { @Override public boolean contains(Object o) { - Objects.requireNonNull(o); - return probe(o) >= 0; + return probe(o) >= 0; // implicit nullcheck of o } @Override @@ -414,8 +501,21 @@ class ImmutableCollections { }; } + @Override + public int hashCode() { + int h = 0; + for (E e : elements) { + if (e != null) { + h += e.hashCode(); + } + } + return h; + } + // returns index at which element is present; or if absent, - // (-i - 1) where i is location where element should be inserted + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pe private int probe(Object pe) { int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length); while (true) { @@ -481,12 +581,14 @@ class ImmutableCollections { @Override public boolean containsKey(Object o) { - return super.containsKey(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -496,10 +598,17 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_MAP); } + + @Override + public int hashCode() { + return 0; + } } static final class Map1 extends AbstractImmutableMap { + @Stable private final K k0; + @Stable private final V v0; Map1(K k0, V v0) { @@ -514,12 +623,12 @@ class ImmutableCollections { @Override public boolean containsKey(Object o) { - return super.containsKey(Objects.requireNonNull(o)); + return o.equals(k0); // implicit nullcheck of o } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + return o.equals(v0); // implicit nullcheck of o } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -529,6 +638,11 @@ class ImmutableCollections { private Object writeReplace() { return new CollSer(CollSer.IMM_MAP, k0, v0); } + + @Override + public int hashCode() { + return k0.hashCode() ^ v0.hashCode(); + } } /** @@ -541,12 +655,13 @@ class ImmutableCollections { * @param the value type */ static final class MapN extends AbstractImmutableMap { - private final Object[] table; // pairs of key, value - private final int size; // number of pairs + @Stable + final Object[] table; // pairs of key, value + @Stable + final int size; // number of pairs MapN(Object... input) { - Objects.requireNonNull(input); - if ((input.length & 1) != 0) { + if ((input.length & 1) != 0) { // implicit nullcheck of input throw new InternalError("length is odd"); } size = input.length >> 1; @@ -573,12 +688,30 @@ class ImmutableCollections { @Override public boolean containsKey(Object o) { - return probe(Objects.requireNonNull(o)) >= 0; + return probe(o) >= 0; // implicit nullcheck of o } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + for (int i = 1; i < table.length; i += 2) { + Object v = table[i]; + if (v != null && o.equals(v)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 0; + for (int i = 0; i < table.length; i += 2) { + Object k = table[i]; + if (k != null) { + hash += k.hashCode() ^ table[i + 1].hashCode(); + } + } + return hash; } @Override @@ -638,7 +771,9 @@ class ImmutableCollections { } // returns index at which the probe key is present; or if absent, - // (-i - 1) where i is location where element should be inserted + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pk. private int probe(Object pk) { int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1; while (true) { diff --git a/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java index 96ca0753ac6..3b7250ee6aa 100644 --- a/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java +++ b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -25,6 +25,8 @@ package java.util; +import jdk.internal.vm.annotation.Stable; + /** * An immutable container for a key and a value, suitable for use * in creating and populating {@code Map} instances. @@ -48,7 +50,9 @@ package java.util; * @since 9 */ final class KeyValueHolder implements Map.Entry { + @Stable final K key; + @Stable final V value; KeyValueHolder(K k, V v) { diff --git a/jdk/src/java.base/share/classes/java/util/List.java b/jdk/src/java.base/share/classes/java/util/List.java index 0f14c298805..dda514b313f 100644 --- a/jdk/src/java.base/share/classes/java/util/List.java +++ b/jdk/src/java.base/share/classes/java/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1027,8 +1027,7 @@ public interface List extends Collection { @SafeVarargs @SuppressWarnings("varargs") static List of(E... elements) { - Objects.requireNonNull(elements); - switch (elements.length) { + switch (elements.length) { // implicit null check of elements case 0: return ImmutableCollections.List0.instance(); case 1: diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java index b41e90dc866..153b86b8084 100644 --- a/jdk/src/java.base/share/classes/java/util/Map.java +++ b/jdk/src/java.base/share/classes/java/util/Map.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1602,8 +1602,7 @@ public interface Map { @SafeVarargs @SuppressWarnings("varargs") static Map ofEntries(Entry... entries) { - Objects.requireNonNull(entries); - if (entries.length == 0) { + if (entries.length == 0) { // implicit null check of entries return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { return new ImmutableCollections.Map1<>(entries[0].getKey(), diff --git a/jdk/src/java.base/share/classes/java/util/Set.java b/jdk/src/java.base/share/classes/java/util/Set.java index 08ef3297161..2dd9060f7df 100644 --- a/jdk/src/java.base/share/classes/java/util/Set.java +++ b/jdk/src/java.base/share/classes/java/util/Set.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -689,8 +689,7 @@ public interface Set extends Collection { @SafeVarargs @SuppressWarnings("varargs") static Set of(E... elements) { - Objects.requireNonNull(elements); - switch (elements.length) { + switch (elements.length) { // implicit null check of elements case 0: return ImmutableCollections.Set0.instance(); case 1: diff --git a/jdk/test/java/util/Collection/SetFactories.java b/jdk/test/java/util/Collection/SetFactories.java index aabeaa344a7..25a884501e0 100644 --- a/jdk/test/java/util/Collection/SetFactories.java +++ b/jdk/test/java/util/Collection/SetFactories.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -103,6 +103,8 @@ public class SetFactories { hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")), a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"), hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")), + a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"), + Set.of("j", "i", "h", "g", "f", "e", "d", "c", "b", "a")), a( Set.of(stringArray), hashSetOf(stringArray)) ).iterator(); @@ -183,6 +185,17 @@ public class SetFactories { Set set = Set.of(array); } + @Test(dataProvider="all") + public void hashCodeEqual(Set act, Set exp) { + assertEquals(act.hashCode(), exp.hashCode()); + } + + @Test(dataProvider="all") + public void containsAll(Set act, Set exp) { + assertTrue(act.containsAll(exp)); + assertTrue(exp.containsAll(act)); + } + @Test(expectedExceptions=NullPointerException.class) public void nullDisallowed1() { Set.of((String)null); // force one-arg overload diff --git a/jdk/test/java/util/Map/MapFactories.java b/jdk/test/java/util/Map/MapFactories.java index b8ff0c9f3f2..7495aa386c3 100644 --- a/jdk/test/java/util/Map/MapFactories.java +++ b/jdk/test/java/util/Map/MapFactories.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -103,6 +103,8 @@ public class MapFactories { a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)), a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)), a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), genMap(10)), + a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), + Map.of(4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j", 0, "a", 1, "b", 2, "c", 3, "d")), a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES)) ).iterator(); } @@ -135,6 +137,18 @@ public class MapFactories { assertEquals(act, exp); } + @Test(dataProvider="all") + public void containsAllKeys(Map act, Map exp) { + assertTrue(act.keySet().containsAll(exp.keySet())); + assertTrue(exp.keySet().containsAll(act.keySet())); + } + + @Test(dataProvider="all") + public void containsAllValues(Map act, Map exp) { + assertTrue(act.values().containsAll(exp.values())); + assertTrue(exp.values().containsAll(act.values())); + } + @Test(expectedExceptions=IllegalArgumentException.class) public void dupKeysDisallowed2() { Map map = Map.of(0, "a", 0, "b"); @@ -192,6 +206,11 @@ public class MapFactories { Map map = Map.ofEntries(entries); } + @Test(dataProvider="all") + public void hashCodeEquals(Map act, Map exp) { + assertEquals(act.hashCode(), exp.hashCode()); + } + @Test(expectedExceptions=NullPointerException.class) public void nullKeyDisallowed1() { Map map = Map.of(null, "a"); From d7ca564a5839ac772cb62d474cc798de8962cf00 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 12 Jan 2017 17:07:49 +0100 Subject: [PATCH 09/11] 8172720: Collections.SingletonList::hashCode not spec-compliant Reviewed-by: chegar --- jdk/src/java.base/share/classes/java/util/Collections.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java index 02d656cb574..22b4557ae2f 100644 --- a/jdk/src/java.base/share/classes/java/util/Collections.java +++ b/jdk/src/java.base/share/classes/java/util/Collections.java @@ -4859,7 +4859,7 @@ public class Collections { } @Override public int hashCode() { - return Objects.hashCode(element); + return 31 + Objects.hashCode(element); } } From c89c526762d5e76d655efe36d9dfe3e5b97986aa Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 12 Jan 2017 18:02:48 +0000 Subject: [PATCH 10/11] 8163449: Allow per protocol setting for URLConnection defaultUseCaches Reviewed-by: chegar, dfuchs --- .../share/classes/java/net/URLConnection.java | 65 ++++++++++++++++-- .../URLConnection/SetDefaultUseCaches.java | 67 +++++++++++++++++++ 2 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 jdk/test/java/net/URLConnection/SetDefaultUseCaches.java diff --git a/jdk/src/java.base/share/classes/java/net/URLConnection.java b/jdk/src/java.base/share/classes/java/net/URLConnection.java index 7a125faf145..e2ed0cfcbdd 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -30,8 +30,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.PrivilegedAction; import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; import java.util.Date; import java.util.Iterator; +import java.util.Locale; import java.util.Objects; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; @@ -231,7 +233,7 @@ public abstract class URLConnection { */ protected boolean allowUserInteraction = defaultAllowUserInteraction; - private static boolean defaultUseCaches = true; + private static volatile boolean defaultUseCaches = true; /** * If {@code true}, the protocol is allowed to use caching @@ -243,12 +245,18 @@ public abstract class URLConnection { *

    * Its default value is the value given in the last invocation of the * {@code setDefaultUseCaches} method. + *

    + * The default setting may be overridden per protocol with + * {@link #setDefaultUseCaches(String,boolean)}. * * @see java.net.URLConnection#setUseCaches(boolean) * @see java.net.URLConnection#getUseCaches() * @see java.net.URLConnection#setDefaultUseCaches(boolean) */ - protected boolean useCaches = defaultUseCaches; + protected boolean useCaches; + + private static final ConcurrentHashMap defaultCaching = + new ConcurrentHashMap<>(); /** * Some protocols support skipping the fetching of the object unless @@ -460,6 +468,11 @@ public abstract class URLConnection { */ protected URLConnection(URL url) { this.url = url; + if (url == null) { + this.useCaches = defaultUseCaches; + } else { + this.useCaches = getDefaultUseCaches(url.getProtocol()); + } } /** @@ -981,7 +994,8 @@ public abstract class URLConnection { * is true, the connection is allowed to use whatever caches it can. * If false, caches are to be ignored. * The default value comes from DefaultUseCaches, which defaults to - * true. + * true. A default value can also be set per-protocol using + * {@link #setDefaultUseCaches(String,boolean)}. * * @param usecaches a {@code boolean} indicating whether * or not to allow caching @@ -1032,9 +1046,10 @@ public abstract class URLConnection { * Returns the default value of a {@code URLConnection}'s * {@code useCaches} flag. *

    - * Ths default is "sticky", being a part of the static state of all + * This default is "sticky", being a part of the static state of all * URLConnections. This flag applies to the next, and all following - * URLConnections that are created. + * URLConnections that are created. This default value can be over-ridden + * per protocol using {@link #setDefaultUseCaches(String,boolean)} * * @return the default value of a {@code URLConnection}'s * {@code useCaches} flag. @@ -1046,7 +1061,8 @@ public abstract class URLConnection { /** * Sets the default value of the {@code useCaches} field to the - * specified value. + * specified value. This default value can be over-ridden + * per protocol using {@link #setDefaultUseCaches(String,boolean)} * * @param defaultusecaches the new value. * @see #getDefaultUseCaches() @@ -1055,6 +1071,43 @@ public abstract class URLConnection { defaultUseCaches = defaultusecaches; } + /** + * Sets the default value of the {@code useCaches} field for the named + * protocol to the given value. This value overrides any default setting + * set by {@link #setDefaultUseCaches(boolean)} for the given protocol. + * Successive calls to this method change the setting and affect the + * default value for all future connections of that protocol. The protocol + * name is case insensitive. + * + * @param protocol the protocol to set the default for + * @param defaultVal whether caching is enabled by default for the given protocol + * @since 9 + */ + public static void setDefaultUseCaches(String protocol, boolean defaultVal) { + protocol = protocol.toLowerCase(Locale.US); + defaultCaching.put(protocol, defaultVal); + } + + /** + * Returns the default value of the {@code useCaches} flag for the given protocol. If + * {@link #setDefaultUseCaches(String,boolean)} was called for the given protocol, + * then that value is returned. Otherwise, if {@link #setDefaultUseCaches(boolean)} + * was called, then that value is returned. If neither method was called, + * the return value is {@code true}. The protocol name is case insensitive. + * + * @param protocol the protocol whose defaultUseCaches setting is required + * @return the default value of the {@code useCaches} flag for the given protocol. + * @since 9 + */ + public static boolean getDefaultUseCaches(String protocol) { + Boolean protoDefault = defaultCaching.get(protocol.toLowerCase(Locale.US)); + if (protoDefault != null) { + return protoDefault.booleanValue(); + } else { + return defaultUseCaches; + } + } + /** * Sets the general request property. If a property with the key already * exists, overwrite its value with the new value. diff --git a/jdk/test/java/net/URLConnection/SetDefaultUseCaches.java b/jdk/test/java/net/URLConnection/SetDefaultUseCaches.java new file mode 100644 index 00000000000..2c12889d23d --- /dev/null +++ b/jdk/test/java/net/URLConnection/SetDefaultUseCaches.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, 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 8163449 + * @summary Allow per protocol setting for URLConnection defaultUseCaches + * @run main/othervm SetDefaultUseCaches + */ + +import java.net.*; +import java.io.*; + +public class SetDefaultUseCaches { + static void testAssert(boolean value, boolean comparator) { + if (value != comparator) { + System.err.println("Expected " + comparator + " Got " + value); + throw new RuntimeException("Test failed:"); + } else + System.err.println("OK"); + } + + public static void main(String s[]) throws Exception { + URL url = new URL("http://www.foo.com/"); + URL url1 = new URL("file:///a/b.txt"); + + // check default default is true + URLConnection urlc = url.openConnection(); + testAssert(urlc.getDefaultUseCaches(), true); + + // set default for http to false and check + URLConnection.setDefaultUseCaches("HTTP", false); + + urlc = url.openConnection(); + testAssert(urlc.getDefaultUseCaches(), true); + testAssert(urlc.getUseCaches(), false); + testAssert(URLConnection.getDefaultUseCaches("http"), false); + + URLConnection urlc1 = url1.openConnection(); + testAssert(urlc1.getDefaultUseCaches(), true); + + // set default default to false and check other values the same + urlc.setDefaultUseCaches(false); + urlc1.setDefaultUseCaches("fiLe", true); + testAssert(urlc1.getDefaultUseCaches(), false); + testAssert(URLConnection.getDefaultUseCaches("fiLE"), true); + } +} From 6ec0f2129e036d866a7c54d3eb0a7870225b7a87 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Thu, 12 Jan 2017 10:10:32 -0800 Subject: [PATCH 11/11] 8030950: TEST_BUG: java/rmi/registry/classPathCodebase/ClassPathCodebase.java failing intermittently Reviewed-by: rriggs --- .../classPathCodebase/ClassPathCodebase.java | 41 +++++++------------ .../registry.security.policy | 18 ++++++++ .../classPathCodebase/security.policy | 8 +++- 3 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 jdk/test/java/rmi/registry/classPathCodebase/registry.security.policy diff --git a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java index d83340bb8b0..f0acc02bcc6 100644 --- a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java +++ b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -34,7 +34,7 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary Dummy + * @build TestLibrary Dummy RegistryVM RMIRegistryRunner * @run main/othervm/policy=security.policy * -Djava.rmi.server.useCodebaseOnly=false ClassPathCodebase */ @@ -48,8 +48,9 @@ import java.util.Arrays; public class ClassPathCodebase { - /** wait 10 seconds for the registry process to be ready to call */ - private final static long REGISTRY_WAIT = 15000; + /** wait dozens of seconds for the registry process to be ready to call */ + private static final long REGISTRY_WAIT = + (long)(10000 * TestLibrary.getTimeoutFactor()); private final static String dummyClassName = "Dummy"; @@ -64,7 +65,7 @@ public class ClassPathCodebase { TestLibrary.suggestSecurityManager("java.lang.SecurityManager"); - Process rmiregistry = null; + RegistryVM rmiregistry = null; try { /* @@ -82,27 +83,13 @@ public class ClassPathCodebase { * Spawn an rmiregistry in the "import" codebase directory. */ File rmiregistryDir = - new File(System.getProperty("user.dir", "."), importCodebase); - - String rmiregistryCommand = - System.getProperty("java.home") + File.separator + - "bin" + File.separator + "rmiregistry"; - - int port = TestLibrary.getUnusedRandomPort(); - String cmdarray[] = new String[] { - rmiregistryCommand, - "-J-Denv.class.path=.", - "-J-Djava.rmi.server.codebase=" + exportCodebaseURL, - Integer.toString(port) }; - - System.err.println("\nCommand used to spawn rmiregistry process:"); - System.err.println("\t" + Arrays.asList(cmdarray).toString()); - - rmiregistry = Runtime.getRuntime().exec(cmdarray, null, rmiregistryDir); - - // pipe rmiregistry output to our output, for debugging failures - StreamPipe.plugTogether(rmiregistry.getInputStream(), System.err); - StreamPipe.plugTogether(rmiregistry.getErrorStream(), System.err); + new File(System.getProperty("user.dir", "."), importCodebase); + rmiregistry = RegistryVM.createRegistryVMWithRunner("RMIRegistryRunner", + " -Denv.class.path=." + + " -Djava.rmi.server.codebase=" + exportCodebaseURL + + " -Duser.dir=" + rmiregistryDir.getAbsolutePath()); + rmiregistry.start(); + int port = rmiregistry.getPort(); /* * Wait for the registry to initialize and be ready to call. @@ -174,7 +161,7 @@ public class ClassPathCodebase { throw new RuntimeException("TEST FAILED: " + e.toString()); } finally { if (rmiregistry != null) { - rmiregistry.destroy(); + rmiregistry.cleanup(); } } } diff --git a/jdk/test/java/rmi/registry/classPathCodebase/registry.security.policy b/jdk/test/java/rmi/registry/classPathCodebase/registry.security.policy new file mode 100644 index 00000000000..291fb8e9f88 --- /dev/null +++ b/jdk/test/java/rmi/registry/classPathCodebase/registry.security.policy @@ -0,0 +1,18 @@ +/* + * security policy used by the registry process started by RegistryVM. + */ + +grant { + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; + permission java.util.PropertyPermission "env.class.path", "read"; + permission java.io.FilePermission ".", "read"; + permission java.util.PropertyPermission "user.dir", "read"; + permission java.lang.RuntimePermission "createClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.io.FilePermission ".-Djava.rmi.server.codebase=file", "read"; + permission java.io.FilePermission ".${/}-", "read"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp"; + permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept"; +}; diff --git a/jdk/test/java/rmi/registry/classPathCodebase/security.policy b/jdk/test/java/rmi/registry/classPathCodebase/security.policy index e45924702f2..743e8f1355e 100644 --- a/jdk/test/java/rmi/registry/classPathCodebase/security.policy +++ b/jdk/test/java/rmi/registry/classPathCodebase/security.policy @@ -18,6 +18,12 @@ grant { // test needs to use java to exec an rmiregistry permission java.io.FilePermission "${java.home}${/}bin${/}-", "execute"; - // test needs to communicate with this its registry + // test needs to communicate with its registry permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + + permission java.util.PropertyPermission "java.security.policy", "read"; + permission java.util.PropertyPermission "java.security.manager", "read"; + + // used by TestLibrary to determine extra commandline properties + permission java.io.FilePermission "..${/}..${/}test.props", "read"; };