8081678: Add Stream returning methods to classes where there currently exist only Enumeration returning methods
authorpsandoz
Tue, 09 Jun 2015 07:10:02 +0100
changeset 31469 92cc72d2a11a
parent 31468 6cd3ae8de51c
child 31470 93708c7917fc
8081678: Add Stream returning methods to classes where there currently exist only Enumeration returning methods Reviewed-by: lancea, alanb, chegar, dfuchs, mullan, smarks
jdk/src/java.base/share/classes/java/net/NetworkInterface.java
jdk/src/java.base/share/classes/java/security/PermissionCollection.java
jdk/src/java.base/share/classes/java/util/Collections.java
jdk/src/java.base/share/classes/java/util/jar/JarFile.java
jdk/src/java.base/share/classes/java/util/zip/ZipFile.java
jdk/src/java.sql/share/classes/java/sql/DriverManager.java
jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java
jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java
jdk/test/java/sql/testng/test/sql/DriverManagerTests.java
--- a/jdk/src/java.base/share/classes/java/net/NetworkInterface.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/NetworkInterface.java	Tue Jun 09 07:10:02 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -25,10 +25,14 @@
 
 package java.net;
 
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
-import sun.security.action.*;
 import java.security.AccessController;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 /**
  * This class represents a Network Interface made up of a name,
@@ -95,8 +99,8 @@
     }
 
     /**
-     * Convenience method to return an Enumeration with all or a
-     * subset of the InetAddresses bound to this network interface.
+     * Get an Enumeration with all or a subset of the InetAddresses bound to
+     * this network interface.
      * <p>
      * If there is a security manager, its {@code checkConnect}
      * method is called for each InetAddress. Only InetAddresses where
@@ -104,53 +108,56 @@
      * will be returned in the Enumeration. However, if the caller has the
      * {@link NetPermission}("getNetworkInformation") permission, then all
      * InetAddresses are returned.
+     *
      * @return an Enumeration object with all or a subset of the InetAddresses
      * bound to this network interface
+     * @see #inetAddresses()
      */
     public Enumeration<InetAddress> getInetAddresses() {
-
-        class checkedAddresses implements Enumeration<InetAddress> {
-
-            private int i=0, count=0;
-            private InetAddress local_addrs[];
-
-            checkedAddresses() {
-                local_addrs = new InetAddress[addrs.length];
-                boolean trusted = true;
+        return enumerationFromArray(getCheckedInetAddresses());
+    }
 
-                SecurityManager sec = System.getSecurityManager();
-                if (sec != null) {
-                    try {
-                        sec.checkPermission(new NetPermission("getNetworkInformation"));
-                    } catch (SecurityException e) {
-                        trusted = false;
-                    }
-                }
-                for (int j=0; j<addrs.length; j++) {
-                    try {
-                        if (sec != null && !trusted) {
-                            sec.checkConnect(addrs[j].getHostAddress(), -1);
-                        }
-                        local_addrs[count++] = addrs[j];
-                    } catch (SecurityException e) { }
-                }
+    /**
+     * Get a Stream of all or a subset of the InetAddresses bound to this
+     * network interface.
+     * <p>
+     * If there is a security manager, its {@code checkConnect}
+     * method is called for each InetAddress. Only InetAddresses where
+     * the {@code checkConnect} doesn't throw a SecurityException will be
+     * returned in the Stream. However, if the caller has the
+     * {@link NetPermission}("getNetworkInformation") permission, then all
+     * InetAddresses are returned.
+     *
+     * @return a Stream object with all or a subset of the InetAddresses
+     * bound to this network interface
+     * @since 1.9
+     */
+    public Stream<InetAddress> inetAddresses() {
+        return streamFromArray(getCheckedInetAddresses());
+    }
 
-            }
+    private InetAddress[] getCheckedInetAddresses() {
+        InetAddress[] local_addrs = new InetAddress[addrs.length];
+        boolean trusted = true;
 
-            public InetAddress nextElement() {
-                if (i < count) {
-                    return local_addrs[i++];
-                } else {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            public boolean hasMoreElements() {
-                return (i < count);
+        SecurityManager sec = System.getSecurityManager();
+        if (sec != null) {
+            try {
+                sec.checkPermission(new NetPermission("getNetworkInformation"));
+            } catch (SecurityException e) {
+                trusted = false;
             }
         }
-        return new checkedAddresses();
-
+        int i = 0;
+        for (int j = 0; j < addrs.length; j++) {
+            try {
+                if (!trusted) {
+                    sec.checkConnect(addrs[j].getHostAddress(), -1);
+                }
+                local_addrs[i++] = addrs[j];
+            } catch (SecurityException e) { }
+        }
+        return Arrays.copyOf(local_addrs, i);
     }
 
     /**
@@ -188,30 +195,23 @@
      *
      * @return an Enumeration object with all of the subinterfaces
      * of this network interface
+     * @see #subInterfaces()
      * @since 1.6
      */
     public Enumeration<NetworkInterface> getSubInterfaces() {
-        class subIFs implements Enumeration<NetworkInterface> {
-
-            private int i=0;
-
-            subIFs() {
-            }
+        return enumerationFromArray(childs);
+    }
 
-            public NetworkInterface nextElement() {
-                if (i < childs.length) {
-                    return childs[i++];
-                } else {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            public boolean hasMoreElements() {
-                return (i < childs.length);
-            }
-        }
-        return new subIFs();
-
+    /**
+     * Get a Stream of all subinterfaces (also known as virtual
+     * interfaces) attached to this network interface.
+     *
+     * @return a Stream object with all of the subinterfaces
+     * of this network interface
+     * @since 1.9
+     */
+    public Stream<NetworkInterface> subInterfaces() {
+        return streamFromArray(childs);
     }
 
     /**
@@ -326,43 +326,80 @@
     }
 
     /**
-     * Returns all the interfaces on this machine. The {@code Enumeration}
-     * contains at least one element, possibly representing a loopback
-     * interface that only supports communication between entities on
+     * Returns an {@code Enumeration} of all the interfaces on this machine. The
+     * {@code Enumeration} contains at least one element, possibly representing
+     * a loopback interface that only supports communication between entities on
      * this machine.
      *
-     * NOTE: can use getNetworkInterfaces()+getInetAddresses()
-     *       to obtain all IP addresses for this node
+     * @apiNote this method can be used in combination with
+     * {@link #getInetAddresses()} to obtain all IP addresses for this node
      *
      * @return an Enumeration of NetworkInterfaces found on this machine
      * @exception  SocketException  if an I/O error occurs.
+     * @see #networkInterfaces()
      */
-
     public static Enumeration<NetworkInterface> getNetworkInterfaces()
         throws SocketException {
-        final NetworkInterface[] netifs = getAll();
+        NetworkInterface[] netifs = getAll();
+        assert netifs != null && netifs.length > 0;
 
-        // specified to return null if no network interfaces
-        if (netifs == null)
-            return null;
+        return enumerationFromArray(netifs);
+    }
 
+    /**
+     * Returns a {@code Stream} of all the interfaces on this machine.  The
+     * {@code Stream} contains at least one interface, possibly representing a
+     * loopback interface that only supports communication between entities on
+     * this machine.
+     *
+     * @apiNote this method can be used in combination with
+     * {@link #inetAddresses()}} to obtain a stream of all IP addresses for
+     * this node, for example:
+     * <pre> {@code
+     * Stream<InetAddress> addrs = NetworkInterface.networkInterfaces()
+     *     .flatMap(NetworkInterface::inetAddresses);
+     * }</pre>
+     *
+     * @return a Stream of NetworkInterfaces found on this machine
+     * @exception  SocketException  if an I/O error occurs.
+     * @since 1.9
+     */
+    public static Stream<NetworkInterface> networkInterfaces()
+        throws SocketException {
+        NetworkInterface[] netifs = getAll();
+        assert netifs != null && netifs.length > 0;
+
+        return streamFromArray(netifs);
+    }
+
+    private static <T> Enumeration<T> enumerationFromArray(T[] a) {
         return new Enumeration<>() {
-            private int i = 0;
-            public NetworkInterface nextElement() {
-                if (netifs != null && i < netifs.length) {
-                    NetworkInterface netif = netifs[i++];
-                    return netif;
+            int i = 0;
+
+            @Override
+            public T nextElement() {
+                if (i < a.length) {
+                    return a[i++];
                 } else {
                     throw new NoSuchElementException();
                 }
             }
 
+            @Override
             public boolean hasMoreElements() {
-                return (netifs != null && i < netifs.length);
+                return i < a.length;
             }
         };
     }
 
+    private static <T> Stream<T> streamFromArray(T[] a) {
+        return StreamSupport.stream(
+                Spliterators.spliterator(
+                        a,
+                        Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL),
+                false);
+    }
+
     private native static NetworkInterface[] getAll()
         throws SocketException;
 
--- a/jdk/src/java.base/share/classes/java/security/PermissionCollection.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/security/PermissionCollection.java	Tue Jun 09 07:10:02 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -26,6 +26,8 @@
 package java.security;
 
 import java.util.*;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 /**
  * Abstract class representing a collection of Permission objects.
@@ -126,10 +128,35 @@
      * Returns an enumeration of all the Permission objects in the collection.
      *
      * @return an enumeration of all the Permissions.
+     * @see #elementsAsStream()
      */
     public abstract Enumeration<Permission> elements();
 
     /**
+     * Returns a stream of all the Permission objects in the collection.
+     *
+     * <p> The collection should not be modified (see {@link #add}) during the
+     * execution of the terminal stream operation. Otherwise, the result of the
+     * terminal stream operation is undefined.
+     *
+     * @implSpec
+     * The default implementation creates a stream whose source is derived from
+     * the enumeration returned from a call to {@link #elements()}.
+     *
+     * @return a stream of all the Permissions.
+     * @since 1.9
+     */
+    public Stream<Permission> elementsAsStream() {
+        int characteristics = isReadOnly()
+                ? Spliterator.NONNULL | Spliterator.IMMUTABLE
+                : Spliterator.NONNULL;
+        return StreamSupport.stream(
+                Spliterators.spliteratorUnknownSize(
+                        elements().asIterator(), characteristics),
+                false);
+    }
+
+    /**
      * Marks this PermissionCollection object as "readonly". After
      * a PermissionCollection object
      * is marked as readonly, no new Permission objects can be added to it
--- a/jdk/src/java.base/share/classes/java/util/Collections.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java	Tue Jun 09 07:10:02 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -4268,6 +4268,7 @@
 
         public boolean hasMoreElements() { return false; }
         public E nextElement() { throw new NoSuchElementException(); }
+        public Iterator<E> asIterator() { return emptyIterator(); }
     }
 
     /**
@@ -5199,6 +5200,11 @@
      * interoperability with legacy APIs that require an enumeration
      * as input.
      *
+     * <p>The iterator returned from a call to {@link Enumeration#asIterator()}
+     * does not support removal of elements from the specified collection.  This
+     * is necessary to avoid unintentionally increasing the capabilities of the
+     * returned enumeration.
+     *
      * @param  <T> the class of the objects in the collection
      * @param c the collection for which an enumeration is to be returned.
      * @return an enumeration over the specified collection.
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java	Tue Jun 09 07:10:02 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -265,6 +265,10 @@
         public JarEntry nextElement() {
             return next();
         }
+
+        public Iterator<JarEntry> asIterator() {
+            return this;
+        }
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Tue Jun 09 07:10:02 2015 +0100
@@ -526,6 +526,10 @@
                 return ze;
             }
         }
+
+        public Iterator<ZipEntry> asIterator() {
+            return this;
+        }
     }
 
     /**
--- a/jdk/src/java.sql/share/classes/java/sql/DriverManager.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/DriverManager.java	Tue Jun 09 07:10:02 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,11 +25,17 @@
 
 package java.sql;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.List;
 import java.util.ServiceLoader;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Stream;
+
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 
@@ -429,29 +435,44 @@
      * <CODE>d.getClass().getName()</CODE>
      *
      * @return the list of JDBC Drivers loaded by the caller's class loader
+     * @see #drivers()
      */
     @CallerSensitive
-    public static java.util.Enumeration<Driver> getDrivers() {
-        java.util.Vector<Driver> result = new java.util.Vector<>();
-
+    public static Enumeration<Driver> getDrivers() {
         ensureDriversInitialized();
 
-        Class<?> callerClass = Reflection.getCallerClass();
+        return Collections.enumeration(getDrivers(Reflection.getCallerClass()));
+    }
 
+    /**
+     * Retrieves a Stream with all of the currently loaded JDBC drivers
+     * to which the current caller has access.
+     *
+     * @return the stream of JDBC Drivers loaded by the caller's class loader
+     * @since 1.9
+     */
+    @CallerSensitive
+    public static Stream<Driver> drivers() {
+        ensureDriversInitialized();
+
+        return getDrivers(Reflection.getCallerClass()).stream();
+    }
+
+    private static List<Driver> getDrivers(Class<?> callerClass) {
+        List<Driver> result = new ArrayList<>();
         // Walk through the loaded registeredDrivers.
         for (DriverInfo aDriver : registeredDrivers) {
             // If the caller does not have permission to load the driver then
             // skip it.
             if (isDriverAllowed(aDriver.driver, callerClass)) {
-                result.addElement(aDriver.driver);
+                result.add(aDriver.driver);
             } else {
                 println("    skipping: " + aDriver.getClass().getName());
             }
         }
-        return (result.elements());
+        return result;
     }
 
-
     /**
      * Sets the maximum time in seconds that a driver will wait
      * while attempting to connect to a database once the driver has
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java	Tue Jun 09 07:10:02 2015 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8081678
+ * @summary Tests for stream returning methods
+ * @library ../../util/stream/bootlib
+ * @build java.util.stream.OpTestCase
+ * @run testng/othervm NetworkInterfaceStreamTest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest
+ */
+
+import org.testng.annotations.Test;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Supplier;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.TestData;
+
+public class NetworkInterfaceStreamTest extends OpTestCase {
+
+    @Test
+    public void testNetworkInterfaces() throws SocketException {
+        Supplier<Stream<NetworkInterface>> ss = () -> {
+            try {
+                return NetworkInterface.networkInterfaces();
+            }
+            catch (SocketException e) {
+                throw new RuntimeException(e);
+            }
+        };
+
+        Collection<NetworkInterface> expected = Collections.list(NetworkInterface.getNetworkInterfaces());
+        withData(TestData.Factory.ofSupplier("Top-level network interfaces", ss))
+                .stream(s -> s)
+                .expectedResult(expected)
+                .exercise();
+    }
+
+
+    private Collection<NetworkInterface> getAllNetworkInterfaces() throws SocketException {
+        Collection<NetworkInterface> anis = new ArrayList<>();
+        for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
+            getAllSubNetworkInterfaces(ni, anis);
+        }
+        return anis;
+    }
+
+    private void getAllSubNetworkInterfaces(NetworkInterface ni, Collection<NetworkInterface> result) {
+        result.add(ni);
+
+        for (NetworkInterface sni : Collections.list(ni.getSubInterfaces())) {
+            getAllSubNetworkInterfaces(sni, result);
+        }
+    }
+
+    private Stream<NetworkInterface> allNetworkInterfaces() throws SocketException {
+        return NetworkInterface.networkInterfaces().flatMap(this::allSubNetworkInterfaces);
+    }
+
+    private Stream<NetworkInterface> allSubNetworkInterfaces(NetworkInterface ni) {
+        return Stream.concat(
+                Stream.of(ni),
+                ni.subInterfaces().flatMap(this::allSubNetworkInterfaces));
+    }
+
+    @Test
+    public void testSubNetworkInterfaces() throws SocketException {
+        Supplier<Stream<NetworkInterface>> ss = () -> {
+            try {
+                return allNetworkInterfaces();
+            }
+            catch (SocketException e) {
+                throw new RuntimeException(e);
+            }
+        };
+
+        Collection<NetworkInterface> expected = getAllNetworkInterfaces();
+        withData(TestData.Factory.ofSupplier("All network interfaces", ss))
+                .stream(s -> s)
+                .expectedResult(expected)
+                .exercise();
+    }
+
+
+    @Test
+    public void testInetAddresses() throws SocketException {
+        Supplier<Stream<InetAddress>> ss = () -> {
+            try {
+                return NetworkInterface.networkInterfaces().flatMap(NetworkInterface::inetAddresses);
+            }
+            catch (SocketException e) {
+                throw new RuntimeException(e);
+            }
+        };
+
+        Collection<NetworkInterface> nis = Collections.list(NetworkInterface.getNetworkInterfaces());
+        Collection<InetAddress> expected = new ArrayList<>();
+        for (NetworkInterface ni : nis) {
+            expected.addAll(Collections.list(ni.getInetAddresses()));
+        }
+        withData(TestData.Factory.ofSupplier("All inet addresses", ss))
+                .stream(s -> s)
+                .expectedResult(expected)
+                .exercise();
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java	Tue Jun 09 07:10:02 2015 +0100
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8081678
+ * @summary Tests for stream returning methods
+ * @library ../../util/stream/bootlib
+ * @build java.util.stream.OpTestCase
+ * @run testng/othervm PermissionCollectionStreamTest
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.FilePermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Supplier;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.TestData;
+
+public class PermissionCollectionStreamTest extends OpTestCase {
+
+    @DataProvider
+    public static Object[][] permissions() {
+        return new Object[][]{
+                {
+                        "FilePermission",
+                        new Permission[]{
+                                new FilePermission("/home/foobar", "read"),
+                                new FilePermission("/home/foo", "write"),
+                                new FilePermission("/home/foobar", "read,write"),
+                        }
+                },
+        };
+    }
+
+
+    private PermissionCollection create(Permission[] pa) {
+        PermissionCollection pc = pa[0].newPermissionCollection();
+        for (Permission p : pa) {
+            pc.add(p);
+        }
+        return pc;
+    }
+
+    @Test(dataProvider = "permissions")
+    public void testElementsAsStream(String description, Permission[] pa) {
+        PermissionCollection pc = create(pa);
+
+        Supplier<Stream<Permission>> ss = pc::elementsAsStream;
+
+        Collection<Permission> expected = Collections.list(pc.elements());
+        withData(TestData.Factory.ofSupplier(description, ss))
+                .stream(s -> s)
+                .expectedResult(expected)
+                .exercise();
+    }
+}
--- a/jdk/test/java/sql/testng/test/sql/DriverManagerTests.java	Tue Jun 30 17:48:06 2015 -0700
+++ b/jdk/test/java/sql/testng/test/sql/DriverManagerTests.java	Tue Jun 09 07:10:02 2015 +0100
@@ -34,7 +34,11 @@
 import java.sql.Driver;
 import java.sql.DriverManager;
 import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Properties;
+import java.util.stream.Collectors;
+
 import static org.testng.Assert.*;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
@@ -351,4 +355,24 @@
             assertTrue(result.equals(reader.readLine()));
         }
     }
+
+    /**
+     * Register some driver implementations and validate that the driver
+     * elements covered by the Enumeration obtained from
+     * {@link DriverManager#getDrivers()} are the same as driver elements
+     * covered by the stream obtained from {@link DriverManager#drivers()}}
+     */
+    @Test
+    public void tests19() throws Exception {
+        int n = 8;
+        for (int i = 0; i < n; i++) {
+            DriverManager.registerDriver(new StubDriver());
+        }
+
+        Collection<Driver> expectedDrivers = Collections.list(DriverManager.getDrivers());
+        assertEquals(expectedDrivers.size(), n);
+        Collection<Driver> drivers = DriverManager.drivers().collect(Collectors.toList());
+
+        assertEquals(drivers, expectedDrivers);
+    }
 }