changeset 15198:e5e4cb35c92d

Merge
author ddehaven
date Thu, 28 Jul 2016 09:01:30 -0700
parents 42a74b67c5bb 22e704dfa05c
children d7a97d5db744 a178e6359999
files src/java.base/linux/classes/sun/nio/fs/GioFileTypeDetector.java src/java.base/linux/classes/sun/nio/fs/MagicFileTypeDetector.java src/java.base/linux/native/libnio/fs/GioFileTypeDetector.c src/java.base/linux/native/libnio/fs/MagicFileTypeDetector.c src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java
diffstat 105 files changed, 3374 insertions(+), 2702 deletions(-) [+]
line wrap: on
line diff
--- a/make/data/tzdata/VERSION	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/VERSION	Thu Jul 28 09:01:30 2016 -0700
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2016d
+tzdata2016f
--- a/make/data/tzdata/africa	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/africa	Thu Jul 28 09:01:30 2016 -0700
@@ -366,6 +366,12 @@
 # decision to abandon DST permanently.  See Ahram Online 2015-04-24.
 # http://english.ahram.org.eg/NewsContent/1/64/128509/Egypt/Politics-/Sisi-cancels-daylight-saving-time-in-Egypt.aspx
 
+# From Steffen Thorsen (2016-04-29):
+# Egypt will have DST from July 7 until the end of October....
+# http://english.ahram.org.eg/NewsContentP/1/204655/Egypt/Daylight-savings-time-returning-to-Egypt-on--July.aspx
+# From Mina Samuel (2016-07-04):
+# Egyptian government took the decision to cancel the DST,
+
 Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
 Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
 Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
@@ -881,11 +887,11 @@
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0:00	0	-
 Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
 Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
 Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
 Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
 Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
 Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
--- a/make/data/tzdata/antarctica	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/antarctica	Thu Jul 28 09:01:30 2016 -0700
@@ -36,7 +36,7 @@
 #
 # Except for the French entries,
 # I made up all time zone abbreviations mentioned here; corrections welcome!
-# FORMAT is 'zzz' and GMTOFF is 0 for locations while uninhabited.
+# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -90,22 +90,22 @@
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Casey	0	-	zzz	1969
+Zone Antarctica/Casey	0	-	-00	1969
 			8:00	-	AWST	2009 Oct 18  2:00
 						# Australian Western Std Time
 			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
 			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
 			8:00	-	AWST
-Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
+Zone Antarctica/Davis	0	-	-00	1957 Jan 13
 			7:00	-	DAVT	1964 Nov    # Davis Time
-			0	-	zzz	1969 Feb
+			0	-	-00	1969 Feb
 			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
 			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
-Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
+Zone Antarctica/Mawson	0	-	-00	1954 Feb 13
 			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
@@ -160,7 +160,7 @@
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
+Zone Indian/Kerguelen	0	-	-00	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
@@ -171,9 +171,9 @@
 # It was destroyed by fire on 1952-01-14.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/DumontDUrville 0 -	zzz	1947
+Zone Antarctica/DumontDUrville 0 -	-00	1947
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
-			0	-	zzz	1956 Nov
+			0	-	-00	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
 
 # France & Italy - year-round base
@@ -199,7 +199,7 @@
 # was established on 1957-01-29.  Since Syowa station is still the main
 # station of Japan, it's appropriate for the principal location.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
+Zone Antarctica/Syowa	0	-	-00	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
 # NIPR Antarctic Research Activities (1999-08-17)
@@ -249,7 +249,7 @@
 # Remove the following line when uncommenting the above '#Rule' lines.
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
+Zone Antarctica/Troll	0	-	-00	2005 Feb 12
 			0:00	Troll	%s
 
 # Poland - year-round base
@@ -290,7 +290,7 @@
 # happened to be during their visit.  So we still don't really know what time
 # it is at Vostok.  But we'll guess UTC+6.
 #
-Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
+Zone Antarctica/Vostok	0	-	-00	1957 Dec 16
 			6:00	-	VOST	# Vostok time
 
 # S Africa - year-round bases
@@ -323,7 +323,7 @@
 # <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Rothera	0	-	zzz	1976 Dec  1
+Zone Antarctica/Rothera	0	-	-00	1976 Dec  1
 			-3:00	-	ROTT	# Rothera time
 
 # Uruguay - year round base
--- a/make/data/tzdata/asia	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/asia	Thu Jul 28 09:01:30 2016 -0700
@@ -169,7 +169,7 @@
 			3:00	-	BAKT	1957 Mar    # Baku Time
 			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
-			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
+			3:00 RussiaAsia	AZ%sT	1992 Sep lastSun  2:00s
 			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
--- a/make/data/tzdata/australasia	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/australasia	Thu Jul 28 09:01:30 2016 -0700
@@ -266,11 +266,11 @@
 # will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
-Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
+Zone Antarctica/Macquarie 0	-	-00	1899 Nov
 			10:00	-	AEST	1916 Oct  1  2:00
 			10:00	1:00	AEDT	1917 Feb
 			10:00	Aus	AE%sT	1919 Apr  1  0:00s
-			0	-	zzz	1948 Mar 25
+			0	-	-00	1948 Mar 25
 			10:00	Aus	AE%sT	1967
 			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
--- a/make/data/tzdata/europe	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/europe	Thu Jul 28 09:01:30 2016 -0700
@@ -778,6 +778,14 @@
 			1:00	EU	CE%sT
 
 # Belarus
+#
+# From Stepan Golosunov (2016-07-02):
+# http://www.lawbelarus.com/repub/sub30/texf9611.htm
+# (Act of the Cabinet of Ministers of the Republic of Belarus from
+# 1992-03-25 No. 157) ... says clocks were to be moved forward at 2:00
+# on last Sunday of March and backward at 3:00 on last Sunday of September
+# (the same as previous USSR and contemporary Russian regulations).
+#
 # From Yauhen Kharuzhy (2011-09-16):
 # By latest Belarus government act Europe/Minsk timezone was changed to
 # GMT+3 without DST (was GMT+2 with DST).
@@ -801,9 +809,6 @@
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
 			3:00	-	MSK	1991 Mar 31  2:00s
-			2:00	1:00	EEST	1991 Sep 29  2:00s
-			2:00	-	EET	1992 Mar 29  0:00s
-			2:00	1:00	EEST	1992 Sep 27  0:00s
 			2:00	Russia	EE%sT	2011 Mar 27  2:00s
 			3:00	-	FET	2014 Oct 26  1:00s
 			3:00	-	MSK
@@ -2746,14 +2751,22 @@
 # Asia/Novosibirsk covers:
 # 54	RU-NVS	Novosibirsk Oblast
 
+# From Stepan Golosunov (2016-05-30):
+# http://asozd2.duma.gov.ru/main.nsf/(Spravka)?OpenAgent&RN=1085784-6
+# moves Novosibirsk oblast from UTC+6 to UTC+7.
+# From Stepan Golosunov (2016-07-04):
+# The law was signed yesterday and published today on
+# http://publication.pravo.gov.ru/Document/View/0001201607040064
+
 Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
-			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
-			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
-			 7:00	-	NOVT	2014 Oct 26  2:00s
-			 6:00	-	NOVT
+			 6:00	-	+06	1930 Jun 21
+			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
+			 6:00	Russia	+06/+07	1992 Jan 19  2:00s
+			 7:00	Russia	+07/+08	1993 May 23 # say Shanks & P.
+			 6:00	Russia	+06/+07	2011 Mar 27  2:00s
+			 7:00	-	+07	2014 Oct 26  2:00s
+			 6:00	-	+06	2016 Jul 24  2:00s
+			 7:00	-	+07
 
 # From Paul Eggert (2016-03-18):
 # Asia/Tomsk covers:
@@ -2794,6 +2807,9 @@
 # approved by the Federation Council on 2016-04-20, signed by the President and
 # published as a law around 2016-04-26.
 
+# From Matt Johnson (2016-04-26):
+# http://publication.pravo.gov.ru/Document/View/0001201604260048
+
 Zone	Asia/Tomsk	 5:39:51 -	LMT	1919 Dec 22
 			 6:00	-	+06	1930 Jun 21
 			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
@@ -2833,14 +2849,12 @@
 # realigning itself with KRAT.
 
 Zone Asia/Novokuznetsk	 5:48:48 -	LMT	1924 May  1
-			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
-			 7:00	-	NOVT	2014 Oct 26  2:00s
-			 7:00	-	KRAT	# Krasnoyarsk Time
-
+			 6:00	-	+06	1930 Jun 21
+			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
+			 6:00	Russia	+06/+07	1992 Jan 19  2:00s
+			 7:00	Russia	+07/+08	2010 Mar 28  2:00s
+			 6:00	Russia	+06/+07	2011 Mar 27  2:00s
+			 7:00	-	+07
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
 # Asia/Krasnoyarsk covers...
--- a/make/data/tzdata/northamerica	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/northamerica	Thu Jul 28 09:01:30 2016 -0700
@@ -2214,39 +2214,39 @@
 Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
-Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
+Zone America/Pangnirtung 0	-	-00	1921 # trading post est.
 			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
 			-5:00	Canada	E%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
-Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
+Zone America/Iqaluit	0	-	-00	1942 Aug # Frobisher Bay est.
 			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
-Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
+Zone America/Resolute	0	-	-00	1947 Aug 31 # Resolute founded
 			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT	2006 Oct 29  2:00
 			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
-Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
+Zone America/Rankin_Inlet 0	-	-00	1957 # Rankin Inlet founded
 			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
-Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
+Zone America/Cambridge_Bay 0	-	-00	1920 # trading post est.?
 			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2000 Nov  5  0:00
 			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
-Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
+Zone America/Yellowknife 0	-	-00	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
-Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
+Zone America/Inuvik	0	-	-00	1953 # Inuvik founded
 			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
--- a/make/data/tzdata/southamerica	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/data/tzdata/southamerica	Thu Jul 28 09:01:30 2016 -0700
@@ -1332,7 +1332,7 @@
 # Palmer used to be supplied from Argentina.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Palmer	0	-	zzz	1965
+Zone Antarctica/Palmer	0	-	-00	1965
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1982 May
 			-4:00	Chile	CL%sT
@@ -1782,16 +1782,16 @@
 # https://actualidad.rt.com/actualidad/204758-venezuela-modificar-huso-horario-sequia-elnino
 #
 # From Paul Eggert (2016-04-15):
-# Clocks advance 30 minutes on 2016-05-01 at 02:30. See:
-# Barboza AD. Huso horario en Venezuela volverá a 4 horas menos con
-# respecto al "Greenwich". Panorama 2016-04-15 12:20 -0430.
-# http://www.panorama.com.ve/ciudad/Huso-horario-en-Venezuela-volvera-a-4-horas-menos-con-respecto-al-Greenwich-20160415-0032.html
-#
+# Clocks advance 30 minutes on 2016-05-01 at 02:30....
 # "'Venezuela's new time-zone: hours without light, hours without water,
-# hours of presidential broadcasts, hours of lines," quipped comedian
-# Jean Mary Curro ...". See: Cawthorne A, Kai D. Venezuela scraps
+# hours of presidential broadcasts, hours of lines,' quipped comedian
+# Jean Mary Curró ...". See: Cawthorne A, Kai D. Venezuela scraps
 # half-hour time difference set by Chavez. Reuters 2016-04-15 14:50 -0400
 # http://www.reuters.com/article/us-venezuela-timezone-idUSKCN0XC2BE
+#
+# From Matt Johnson (2016-04-20):
+# ... published in the official Gazette [2016-04-18], here:
+# http://historico.tsj.gob.ve/gaceta_ext/abril/1842016/E-1842016-4551.pdf
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
--- a/make/mapfiles/libnio/mapfile-linux	Tue Jul 26 14:45:11 2016 -0700
+++ b/make/mapfiles/libnio/mapfile-linux	Thu Jul 28 09:01:30 2016 -0700
@@ -136,10 +136,6 @@
 		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
 		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
 		Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
-		Java_sun_nio_fs_GioFileTypeDetector_initializeGio;
-		Java_sun_nio_fs_GioFileTypeDetector_probeGio;
-		Java_sun_nio_fs_MagicFileTypeDetector_initialize0;
-		Java_sun_nio_fs_MagicFileTypeDetector_probe0;
 		Java_sun_nio_fs_LinuxWatchService_eventSize;
 		Java_sun_nio_fs_LinuxWatchService_eventOffsets;
 		Java_sun_nio_fs_LinuxWatchService_inotifyInit;
--- a/src/java.base/linux/classes/sun/nio/fs/GioFileTypeDetector.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2008, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.nio.fs;
-
-import java.nio.file.Path;
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * File type detector that uses the GNOME I/O library to guess the
- * MIME type of a file.
- */
-
-public class GioFileTypeDetector
-    extends AbstractFileTypeDetector
-{
-    // true if GIO is available
-    private final boolean gioAvailable;
-
-    public GioFileTypeDetector() {
-        gioAvailable = initializeGio();
-    }
-
-    @Override
-    public String implProbeContentType(Path obj) throws IOException {
-        if (!gioAvailable)
-            return null;
-        if (!(obj instanceof UnixPath))
-            return null;
-
-        UnixPath path = (UnixPath)obj;
-        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
-        try {
-            // GIO may access file so need permission check
-            path.checkRead();
-            byte[] type = probeGio(buffer.address());
-            return (type == null) ? null : Util.toString(type);
-        } finally {
-            buffer.release();
-        }
-
-    }
-
-    // GIO
-    private static native boolean initializeGio();
-    //
-    // The probeGIO() method is synchronized to avert potential problems
-    // such as crashes due to a suspected lack of thread safety in GIO.
-    //
-    private static synchronized native byte[] probeGio(long pathAddress);
-
-    static {
-        AccessController.doPrivileged(new PrivilegedAction<>() {
-            public Void run() {
-                System.loadLibrary("nio");
-                return null;
-        }});
-    }
-}
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Thu Jul 28 09:01:30 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -106,9 +106,7 @@
         Path userMimeTypes = Paths.get(userHome, ".mime.types");
         Path etcMimeTypes = Paths.get("/etc/mime.types");
 
-        return chain(new GioFileTypeDetector(),
-                     new MimeTypesFileTypeDetector(userMimeTypes),
-                     new MimeTypesFileTypeDetector(etcMimeTypes),
-                     new MagicFileTypeDetector());
+        return chain(new MimeTypesFileTypeDetector(userMimeTypes),
+                     new MimeTypesFileTypeDetector(etcMimeTypes));
     }
 }
--- a/src/java.base/linux/classes/sun/nio/fs/MagicFileTypeDetector.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.nio.fs;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * File type detector that uses the libmagic to guess the MIME type of a file.
- */
-
-class MagicFileTypeDetector extends AbstractFileTypeDetector {
-
-    private static final String UNKNOWN_MIME_TYPE = "application/octet-stream";
-
-    // true if libmagic is available and successfully loaded
-    private final boolean libmagicAvailable;
-
-    public MagicFileTypeDetector() {
-        libmagicAvailable = initialize0();
-    }
-
-    @Override
-    protected String implProbeContentType(Path obj) throws IOException {
-        if (!libmagicAvailable || !(obj instanceof UnixPath))
-            return null;
-
-        UnixPath path = (UnixPath) obj;
-        path.checkRead();
-
-        NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
-        try {
-            byte[] type = probe0(buffer.address());
-            String mimeType = (type == null) ? null : new String(type);
-            return UNKNOWN_MIME_TYPE.equals(mimeType) ? null : mimeType;
-        } finally {
-            buffer.release();
-        }
-    }
-
-    private static native boolean initialize0();
-
-    private static native byte[] probe0(long pathAddress);
-
-    static {
-        AccessController.doPrivileged(new PrivilegedAction<>() {
-            @Override
-            public Void run() {
-                System.loadLibrary("nio");
-                return null;
-            }
-        });
-    }
-}
--- a/src/java.base/linux/native/libnio/fs/GioFileTypeDetector.c	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2008, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include <stdlib.h>
-#include <dlfcn.h>
-
-#ifdef __solaris__
-#include <strings.h>
-#endif
-
-#if defined(__linux__)
-#include <string.h>
-#endif
-
-/*
- * For reference see for example the GFileInfo section at
- * https://developer.gnome.org/gio/unstable/.
- */
-
-/* Definitions for GIO */
-
-#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type"
-
-typedef void* gpointer;
-typedef struct _GFile GFile;
-typedef struct _GFileInfo GFileInfo;
-typedef struct _GCancellable GCancellable;
-typedef struct _GError GError;
-
-typedef enum {
-  G_FILE_QUERY_INFO_NONE = 0
-} GFileQueryInfoFlags;
-
-typedef void (*g_type_init_func)(void);
-typedef void (*g_object_unref_func)(gpointer object);
-typedef GFile* (*g_file_new_for_path_func)(const char* path);
-typedef GFileInfo* (*g_file_query_info_func)(GFile *file,
-    const char *attributes, GFileQueryInfoFlags flags,
-    GCancellable *cancellable, GError **error);
-typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info);
-
-static g_type_init_func g_type_init;
-static g_object_unref_func g_object_unref;
-static g_file_new_for_path_func g_file_new_for_path;
-static g_file_query_info_func g_file_query_info;
-static g_file_info_get_content_type_func g_file_info_get_content_type;
-
-
-#include "sun_nio_fs_GioFileTypeDetector.h"
-
-
-JNIEXPORT jboolean JNICALL
-Java_sun_nio_fs_GioFileTypeDetector_initializeGio
-    (JNIEnv* env, jclass this)
-{
-    void* gio_handle;
-
-    gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
-    if (gio_handle == NULL) {
-        gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
-        if (gio_handle == NULL) {
-            return JNI_FALSE;
-        }
-    }
-
-    g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init");
-
-    g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref");
-
-    g_file_new_for_path =
-        (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path");
-
-    g_file_query_info =
-        (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info");
-
-    g_file_info_get_content_type = (g_file_info_get_content_type_func)
-        dlsym(gio_handle, "g_file_info_get_content_type");
-
-    if (g_object_unref == NULL ||
-        g_file_new_for_path == NULL ||
-        g_file_query_info == NULL ||
-        g_file_info_get_content_type == NULL)
-    {
-        dlclose(gio_handle);
-        return JNI_FALSE;
-    }
-
-    if (g_type_init != NULL) {
-        (*g_type_init)();
-    }
-
-    return JNI_TRUE;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_sun_nio_fs_GioFileTypeDetector_probeGio
-    (JNIEnv* env, jclass this, jlong pathAddress)
-{
-    char* path = (char*)jlong_to_ptr(pathAddress);
-    GFile* gfile;
-    GFileInfo* gfileinfo;
-    jbyteArray result = NULL;
-
-    gfile = (*g_file_new_for_path)(path);
-    gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
-        G_FILE_QUERY_INFO_NONE, NULL, NULL);
-    if (gfileinfo != NULL) {
-        const char* mime = (*g_file_info_get_content_type)(gfileinfo);
-        if (mime != NULL) {
-            jsize len = strlen(mime);
-            result = (*env)->NewByteArray(env, len);
-            if (result != NULL) {
-                (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
-            }
-        }
-        (*g_object_unref)(gfileinfo);
-    }
-    (*g_object_unref)(gfile);
-
-    return result;
-}
--- a/src/java.base/linux/native/libnio/fs/MagicFileTypeDetector.c	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include <dlfcn.h>
-#include <string.h>
-
-#define MAGIC_MIME_TYPE 0x000010 /* Return the MIME type */
-
-typedef struct magic_set magic_t;
-
-typedef magic_t* (*magic_open_func)(int flags);
-typedef int (*magic_load_func)(magic_t* cookie, const char* filename);
-typedef const char* (*magic_file_func)(magic_t* cookie, const char* filename);
-typedef void (*magic_close_func)(magic_t* cookie);
-
-static void* magic_handle;
-static magic_open_func magic_open;
-static magic_load_func magic_load;
-static magic_file_func magic_file;
-static magic_close_func magic_close;
-
-#include "sun_nio_fs_MagicFileTypeDetector.h"
-
-JNIEXPORT jboolean JNICALL
-Java_sun_nio_fs_MagicFileTypeDetector_initialize0
-    (JNIEnv* env, jclass this)
-{
-    magic_handle = dlopen("libmagic.so", RTLD_LAZY);
-    if (magic_handle == NULL) {
-        magic_handle = dlopen("libmagic.so.1", RTLD_LAZY);
-        if (magic_handle == NULL) {
-            return JNI_FALSE;
-        }
-    }
-
-    magic_open = (magic_open_func)dlsym(magic_handle, "magic_open");
-
-    magic_load = (magic_load_func)dlsym(magic_handle, "magic_load");
-
-    magic_file = (magic_file_func)dlsym(magic_handle, "magic_file");
-
-    magic_close = (magic_close_func)dlsym(magic_handle, "magic_close");
-
-    if (magic_open == NULL ||
-        magic_load == NULL ||
-        magic_file == NULL ||
-        magic_close == NULL)
-    {
-        dlclose(magic_handle);
-        return JNI_FALSE;
-    }
-
-    return JNI_TRUE;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_sun_nio_fs_MagicFileTypeDetector_probe0
-    (JNIEnv* env, jclass this, jlong pathAddress)
-{
-    char* path = (char*)jlong_to_ptr(pathAddress);
-    magic_t* cookie;
-    jbyteArray result = NULL;
-
-    cookie = (*magic_open)(MAGIC_MIME_TYPE);
-
-    if (cookie != NULL) {
-        if ((*magic_load)(cookie, NULL) != -1) {
-            const char* type = (*magic_file)(cookie, path);
-            if (type != NULL) {
-                jsize len = strlen(type);
-                result = (*env)->NewByteArray(env, len);
-                if (result != NULL) {
-                    (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)type);
-                }
-            }
-        }
-        (*magic_close)(cookie);
-    }
-
-    return result;
-}
--- a/src/java.base/share/classes/java/lang/System.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/java/lang/System.java	Thu Jul 28 09:01:30 2016 -0700
@@ -236,10 +236,12 @@
      * @since   1.6
      */
      public static Console console() {
-         Console c = cons;
-         if (c == null) {
+         Console c;
+         if ((c = cons) == null) {
              synchronized (System.class) {
-                 cons = c = SharedSecrets.getJavaIOAccess().console();
+                 if ((c = cons) == null) {
+                     cons = c = SharedSecrets.getJavaIOAccess().console();
+                 }
              }
          }
          return c;
--- a/src/java.base/share/classes/java/time/LocalDate.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/java/time/LocalDate.java	Thu Jul 28 09:01:30 2016 -0700
@@ -338,6 +338,7 @@
      * @throws DateTimeException if the epoch day exceeds the supported date range
      */
     public static LocalDate ofEpochDay(long epochDay) {
+        EPOCH_DAY.checkValidValue(epochDay);
         long zeroDay = epochDay + DAYS_0000_TO_1970;
         // find the march-based year
         zeroDay -= 60;  // adjust to 0000-03-01 so leap day is at end of four year cycle
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -928,7 +928,24 @@
      * second if non-zero, no colon
      * <li>{@code +HH:mm:ss} - hour, with minute if non-zero or with minute and
      * second if non-zero, with colon
+     * <li>{@code +H} - hour only, ignoring minute and second
+     * <li>{@code +Hmm} - hour, with minute if non-zero, ignoring second, no colon
+     * <li>{@code +H:mm} - hour, with minute if non-zero, ignoring second, with colon
+     * <li>{@code +HMM} - hour and minute, ignoring second, no colon
+     * <li>{@code +H:MM} - hour and minute, ignoring second, with colon
+     * <li>{@code +HMMss} - hour and minute, with second if non-zero, no colon
+     * <li>{@code +H:MM:ss} - hour and minute, with second if non-zero, with colon
+     * <li>{@code +HMMSS} - hour, minute and second, no colon
+     * <li>{@code +H:MM:SS} - hour, minute and second, with colon
+     * <li>{@code +Hmmss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, no colon
+     * <li>{@code +H:mm:ss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, with colon
      * </ul>
+     * Patterns containing "HH" will format and parse a two digit hour,
+     * zero-padded if necessary. Patterns containing "H" will format with no
+     * zero-padding, and parse either one or two digits.
+     * In lenient mode, the parser will be greedy and parse the maximum digits possible.
      * The "no offset" text controls what text is printed when the total amount of
      * the offset fields to be output is zero.
      * Example values would be 'Z', '+00:00', 'UTC' or 'GMT'.
@@ -3475,13 +3492,15 @@
      */
     static final class OffsetIdPrinterParser implements DateTimePrinterParser {
         static final String[] PATTERNS = new String[] {
-            "+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
+                "+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
+                "+H",  "+Hmm",  "+H:mm",  "+HMM",  "+H:MM",  "+HMMss",  "+H:MM:ss",  "+HMMSS",  "+H:MM:SS",  "+Hmmss",  "+H:mm:ss",
         };  // order used in pattern builder
         static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z");
         static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0");
 
         private final String noOffsetText;
         private final int type;
+        private final int style;
 
         /**
          * Constructor.
@@ -3493,6 +3512,7 @@
             Objects.requireNonNull(pattern, "pattern");
             Objects.requireNonNull(noOffsetText, "noOffsetText");
             this.type = checkPattern(pattern);
+            this.style = type % 11;
             this.noOffsetText = noOffsetText;
         }
 
@@ -3505,6 +3525,14 @@
             throw new IllegalArgumentException("Invalid zone offset pattern: " + pattern);
         }
 
+        private boolean isPaddedHour() {
+            return type < 11;
+        }
+
+        private boolean isColon() {
+            return style > 0 && (style % 2) == 0;
+        }
+
         @Override
         public boolean format(DateTimePrintContext context, StringBuilder buf) {
             Long offsetSecs = context.getValue(OFFSET_SECONDS);
@@ -3520,15 +3548,17 @@
                 int absSeconds = Math.abs(totalSecs % 60);
                 int bufPos = buf.length();
                 int output = absHours;
-                buf.append(totalSecs < 0 ? "-" : "+")
-                    .append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0'));
-                if ((type >= 3 && type < 9) || (type >= 9 && absSeconds > 0) || (type >= 1 && absMinutes > 0)) {
-                    buf.append((type % 2) == 0 ? ":" : "")
-                        .append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0'));
+                buf.append(totalSecs < 0 ? "-" : "+");
+                if (isPaddedHour() || absHours >= 10) {
+                    formatZeroPad(false, absHours, buf);
+                } else {
+                    buf.append((char) (absHours + '0'));
+                }
+                if ((style >= 3 && style <= 8) || (style >= 9 && absSeconds > 0) || (style >= 1 && absMinutes > 0)) {
+                    formatZeroPad(isColon(), absMinutes, buf);
                     output += absMinutes;
-                    if (type == 7  || type == 8 || (type >= 5 && absSeconds > 0)) {
-                        buf.append((type % 2) == 0 ? ":" : "")
-                            .append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0'));
+                    if (style == 7 || style == 8 || (style >= 5 && absSeconds > 0)) {
+                        formatZeroPad(isColon(), absSeconds, buf);
                         output += absSeconds;
                     }
                 }
@@ -3540,19 +3570,16 @@
             return true;
         }
 
+        private void formatZeroPad(boolean colon, int value, StringBuilder buf) {
+            buf.append(colon ? ":" : "")
+                    .append((char) (value / 10 + '0'))
+                    .append((char) (value % 10 + '0'));
+        }
+
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int length = text.length();
             int noOffsetLen = noOffsetText.length();
-            int parseType = type;
-            if (context.isStrict() == false) {
-                if ((parseType > 0 && (parseType % 2) == 0) ||
-                    (parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
-                    parseType = 10;
-                } else {
-                    parseType = 9;
-                }
-            }
             if (noOffsetLen == 0) {
                 if (position == length) {
                     return context.setParsedField(OFFSET_SECONDS, 0, position, position);
@@ -3571,12 +3598,87 @@
             if (sign == '+' || sign == '-') {
                 // starts
                 int negative = (sign == '-' ? -1 : 1);
+                boolean isColon = isColon();
+                boolean paddedHour = isPaddedHour();
                 int[] array = new int[4];
                 array[0] = position + 1;
-                if ((parseNumber(array, 1, text, true, parseType) ||
-                        parseNumber(array, 2, text, parseType >= 3 && parseType < 9, parseType) ||
-                        parseNumber(array, 3, text, parseType == 7 || parseType == 8, parseType)) == false) {
-                    // success
+                int parseType = type;
+                // select parse type when lenient
+                if (!context.isStrict()) {
+                    if (paddedHour) {
+                        if (isColon || (parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
+                            isColon = true; // needed in cases like ("+HH", "+01:01")
+                            parseType = 10;
+                        } else {
+                            parseType = 9;
+                        }
+                    } else {
+                        if (isColon || (parseType == 11 && length > position + 3 && (text.charAt(position + 2) == ':' || text.charAt(position + 3) == ':'))) {
+                            isColon = true;
+                            parseType = 21;  // needed in cases like ("+H", "+1:01")
+                        } else {
+                            parseType = 20;
+                        }
+                    }
+                }
+                // parse according to the selected pattern
+                switch (parseType) {
+                    case 0: // +HH
+                    case 11: // +H
+                        parseHour(text, paddedHour, array);
+                        break;
+                    case 1: // +HHmm
+                    case 2: // +HH:mm
+                    case 13: // +H:mm
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, false, array);
+                        break;
+                    case 3: // +HHMM
+                    case 4: // +HH:MM
+                    case 15: // +H:MM
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        break;
+                    case 5: // +HHMMss
+                    case 6: // +HH:MM:ss
+                    case 17: // +H:MM:ss
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        parseSecond(text, isColon, false, array);
+                        break;
+                    case 7: // +HHMMSS
+                    case 8: // +HH:MM:SS
+                    case 19: // +H:MM:SS
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        parseSecond(text, isColon, true, array);
+                        break;
+                    case 9: // +HHmmss
+                    case 10: // +HH:mm:ss
+                    case 21: // +H:mm:ss
+                        parseHour(text, paddedHour, array);
+                        parseOptionalMinuteSecond(text, isColon, array);
+                        break;
+                    case 12: // +Hmm
+                        parseVariableWidthDigits(text, 1, 4, array);
+                        break;
+                    case 14: // +HMM
+                        parseVariableWidthDigits(text, 3, 4, array);
+                        break;
+                    case 16: // +HMMss
+                        parseVariableWidthDigits(text, 3, 6, array);
+                        break;
+                    case 18: // +HMMSS
+                        parseVariableWidthDigits(text, 5, 6, array);
+                        break;
+                    case 20: // +Hmmss
+                        parseVariableWidthDigits(text, 1, 6, array);
+                        break;
+                }
+                if (array[0] > 0) {
+                    if (array[1] > 23 || array[2] > 59 || array[3] > 59) {
+                        throw new DateTimeException("Value out of range: Hour[0-23], Minute[0-59], Second[0-59]");
+                    }
                     long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]);
                     return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]);
                 }
@@ -3588,42 +3690,118 @@
             return ~position;
         }
 
-        /**
-         * Parse a two digit zero-prefixed number.
-         *
-         * @param array  the array of parsed data, 0=pos,1=hours,2=mins,3=secs, not null
-         * @param arrayIndex  the index to parse the value into
-         * @param parseText  the offset ID, not null
-         * @param required  whether this number is required
-         * @param parseType the offset pattern type
-         * @return true if an error occurred
-         */
-        private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required, int parseType) {
-            if ((parseType + 3) / 2 < arrayIndex) {
-                return false;  // ignore seconds/minutes
+        private void parseHour(CharSequence parseText, boolean paddedHour, int[] array) {
+            if (paddedHour) {
+                // parse two digits
+                if (!parseDigits(parseText, false, 1, array)) {
+                    array[0] = ~array[0];
+                }
+            } else {
+                // parse one or two digits
+                parseVariableWidthDigits(parseText, 1, 2, array);
             }
+        }
+
+        private void parseMinute(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
+            if (!parseDigits(parseText, isColon, 2, array)) {
+                if (mandatory) {
+                    array[0] = ~array[0];
+                }
+            }
+        }
+
+        private void parseSecond(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
+            if (!parseDigits(parseText, isColon, 3, array)) {
+                if (mandatory) {
+                    array[0] = ~array[0];
+                }
+            }
+        }
+
+        private void parseOptionalMinuteSecond(CharSequence parseText, boolean isColon, int[] array) {
+            if (parseDigits(parseText, isColon, 2, array)) {
+                parseDigits(parseText, isColon, 3, array);
+            }
+        }
+
+        private boolean parseDigits(CharSequence parseText, boolean isColon, int arrayIndex, int[] array) {
             int pos = array[0];
-            if ((parseType % 2) == 0 && arrayIndex > 1) {
+            if (pos < 0) {
+                return true;
+            }
+            if (isColon && arrayIndex != 1) { //  ':' will precede only in case of minute/second
                 if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') {
-                    return required;
+                    return false;
                 }
                 pos++;
             }
             if (pos + 2 > parseText.length()) {
-                return required;
+                return false;
             }
             char ch1 = parseText.charAt(pos++);
             char ch2 = parseText.charAt(pos++);
             if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
-                return required;
+                return false;
             }
             int value = (ch1 - 48) * 10 + (ch2 - 48);
             if (value < 0 || value > 59) {
-                return required;
+                return false;
             }
             array[arrayIndex] = value;
             array[0] = pos;
-            return false;
+            return true;
+        }
+
+        private void parseVariableWidthDigits(CharSequence parseText, int minDigits, int maxDigits, int[] array) {
+            // scan the text to find the available number of digits up to maxDigits
+            // so long as the number available is minDigits or more, the input is valid
+            // then parse the number of available digits
+            int pos = array[0];
+            int available = 0;
+            char[] chars = new char[maxDigits];
+            for (int i = 0; i < maxDigits; i++) {
+                if (pos + 1  > parseText.length()) {
+                    break;
+                }
+                char ch = parseText.charAt(pos++);
+                if (ch < '0' || ch > '9') {
+                    pos--;
+                    break;
+                }
+                chars[i] = ch;
+                available++;
+            }
+            if (available < minDigits) {
+                array[0] = ~array[0];
+                return;
+            }
+            switch (available) {
+                case 1:
+                    array[1] = (chars[0] - 48);
+                    break;
+                case 2:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    break;
+                case 3:
+                    array[1] = (chars[0] - 48);
+                    array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
+                    break;
+                case 4:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
+                    break;
+                case 5:
+                    array[1] = (chars[0] - 48);
+                    array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
+                    array[3] = ((chars[3] - 48) * 10 + (chars[4] - 48));
+                    break;
+                case 6:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
+                    array[3] = ((chars[4] - 48) * 10 + (chars[5] - 48));
+                    break;
+            }
+            array[0] = pos;
         }
 
         @Override
--- a/src/java.base/share/classes/java/time/temporal/ChronoField.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/java/time/temporal/ChronoField.java	Thu Jul 28 09:01:30 2016 -0700
@@ -427,8 +427,11 @@
      * <p>
      * This field is strictly defined to have the same meaning in all calendar systems.
      * This is necessary to ensure interoperation between calendars.
+     * <p>
+     * Range of EpochDay is between (LocalDate.MIN.toEpochDay(), LocalDate.MAX.toEpochDay())
+     * both inclusive.
      */
-    EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of((long) (Year.MIN_VALUE * 365.25), (long) (Year.MAX_VALUE * 365.25))),
+    EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of(-365243219162L, 365241780471L)),
     /**
      * The aligned week within a month.
      * <p>
--- a/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Thu Jul 28 09:01:30 2016 -0700
@@ -153,10 +153,11 @@
      * @exception SSLPeerUnverifiedException if the peer is not verified.
      * @see #getPeerPrincipal()
      * @deprecated The {@link #getPeerCertificates()} method that returns an
-     *               array of {@code java.security.cert.Certificate} should
-     *               be used instead.
+     *          array of {@code java.security.cert.Certificate} should
+     *          be used instead.  This method is subject to removal in
+     *          a future version of Java SE.
      */
-    @Deprecated
+    @Deprecated(since="9", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException
     {
--- a/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Thu Jul 28 09:01:30 2016 -0700
@@ -273,10 +273,11 @@
      *          has not been verified
      * @see #getPeerPrincipal()
      * @deprecated The {@link #getPeerCertificates()} method that returns an
-     *               array of {@code java.security.cert.Certificate} should
-     *               be used instead.
+     *          array of {@code java.security.cert.Certificate} should
+     *          be used instead.  This method is subject to removal in
+     *          a future version of Java SE.
      */
-    @Deprecated
+    @Deprecated(since="9", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException;
 
--- a/src/java.base/share/conf/security/java.policy	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.base/share/conf/security/java.policy	Thu Jul 28 09:01:30 2016 -0700
@@ -122,6 +122,14 @@
         permission java.util.PropertyPermission "*", "read";
 };
 
+grant codeBase "jrt:/java.xml.crypto" {
+        permission java.util.PropertyPermission "*", "read";
+        permission java.security.SecurityPermission "putProviderProperty.XMLDSig";
+        permission java.security.SecurityPermission "clearProviderProperties.XMLDSig";
+        permission java.security.SecurityPermission "removeProviderProperty.XMLDSig";
+        permission java.security.SecurityPermission "com.sun.org.apache.xml.internal.security.register";
+};
+
 grant codeBase "jrt:/java.xml.ws" {
         permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
         permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapPoolManager.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapPoolManager.java	Thu Jul 28 09:01:30 2016 -0700
@@ -39,6 +39,7 @@
 
 import com.sun.jndi.ldap.pool.PoolCleaner;
 import com.sun.jndi.ldap.pool.Pool;
+import jdk.internal.misc.InnocuousThread;
 
 /**
  * Contains utilities for managing connection pools of LdapClient.
@@ -163,7 +164,17 @@
 
         if (idleTimeout > 0) {
             // Create cleaner to expire idle connections
-            new PoolCleaner(idleTimeout, pools).start();
+            PrivilegedAction<Void> pa = new PrivilegedAction<Void>() {
+                public Void run() {
+                    Thread t = InnocuousThread.newSystemThread(
+                            "LDAP PoolCleaner",
+                            new PoolCleaner(idleTimeout, pools));
+                    assert t.getContextClassLoader() == null;
+                    t.setDaemon(true);
+                    t.start();
+                    return null;
+                }};
+            AccessController.doPrivileged(pa);
         }
 
         if (debug) {
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PoolCleaner.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/pool/PoolCleaner.java	Thu Jul 28 09:01:30 2016 -0700
@@ -30,7 +30,7 @@
  *
  * @author Rosanna Lee
  */
-final public class PoolCleaner extends Thread {
+final public class PoolCleaner implements Runnable {
     final private Pool[] pools;
     final private long period;
 
@@ -42,9 +42,9 @@
         super();
         this.period = period;
         this.pools = pools.clone();
-        setDaemon(true);
     }
 
+    @Override
     public void run() {
         long threshold;
         while (true) {
--- a/src/java.rmi/share/classes/sun/rmi/transport/GC.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.rmi/share/classes/sun/rmi/transport/GC.java	Thu Jul 28 09:01:30 2016 -0700
@@ -29,6 +29,7 @@
 import java.security.PrivilegedAction;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import jdk.internal.misc.InnocuousThread;
 
 
 /**
@@ -90,8 +91,9 @@
             }});
     }
 
-    private static class Daemon extends Thread {
+    private static class Daemon implements Runnable {
 
+        @Override
         public void run() {
             for (;;) {
                 long l;
@@ -129,23 +131,17 @@
             }
         }
 
-        private Daemon(ThreadGroup tg) {
-            super(tg, null, "GC Daemon", 0L, false);
-        }
-
-        /* Create a new daemon thread in the root thread group */
+        /* Create a new daemon thread */
         public static void create() {
             PrivilegedAction<Void> pa = new PrivilegedAction<Void>() {
                 public Void run() {
-                    ThreadGroup tg = Thread.currentThread().getThreadGroup();
-                    for (ThreadGroup tgn = tg;
-                         tgn != null;
-                         tg = tgn, tgn = tg.getParent());
-                    Daemon d = new Daemon(tg);
-                    d.setDaemon(true);
-                    d.setPriority(Thread.MIN_PRIORITY + 1);
-                    d.start();
-                    GC.daemon = d;
+                    Thread t = InnocuousThread.newSystemThread("RMI GC Daemon",
+                                                               new Daemon());
+                    assert t.getContextClassLoader() == null;
+                    t.setDaemon(true);
+                    t.setPriority(Thread.MIN_PRIORITY + 1);
+                    t.start();
+                    GC.daemon = t;
                     return null;
                 }};
             AccessController.doPrivileged(pa);
--- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/TransformService.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/TransformService.java	Thu Jul 28 09:01:30 2016 -0700
@@ -39,8 +39,6 @@
 import javax.xml.crypto.XMLCryptoContext;
 import javax.xml.crypto.dsig.spec.TransformParameterSpec;
 
-import sun.security.jca.*;
-import sun.security.jca.GetInstance.Instance;
 
 /**
  * A Service Provider Interface for transform and canonicalization algorithms.
@@ -165,18 +163,23 @@
         if (mechanismType.equals("DOM")) {
             dom = true;
         }
-        List<Service> services = GetInstance.getServices("TransformService", algorithm);
-        for (Iterator<Service> t = services.iterator(); t.hasNext(); ) {
-            Service s = t.next();
-            String value = s.getAttribute("MechanismType");
-            if ((value == null && dom) ||
-                (value != null && value.equals(mechanismType))) {
-                Instance instance = GetInstance.getInstance(s, null);
-                TransformService ts = (TransformService) instance.impl;
-                ts.algorithm = algorithm;
-                ts.mechanism = mechanismType;
-                ts.provider = instance.provider;
-                return ts;
+
+        Provider[] provs = Security.getProviders();
+        for (Provider p : provs) {
+            Service s = p.getService("TransformService", algorithm);
+            if (s != null) {
+                String value = s.getAttribute("MechanismType");
+                if ((value == null && dom) ||
+                    (value != null && value.equals(mechanismType))) {
+                    Object obj = s.newInstance(null);
+                    if (obj instanceof TransformService) {
+                        TransformService ts = (TransformService) obj;
+                        ts.algorithm = algorithm;
+                        ts.mechanism = mechanismType;
+                        ts.provider = p;
+                        return ts;
+                    }
+                }
             }
         }
         throw new NoSuchAlgorithmException
@@ -215,21 +218,24 @@
         if (mechanismType.equals("DOM")) {
             dom = true;
         }
-        Service s = GetInstance.getService
-            ("TransformService", algorithm, provider);
-        String value = s.getAttribute("MechanismType");
-        if ((value == null && dom) ||
-            (value != null && value.equals(mechanismType))) {
-            Instance instance = GetInstance.getInstance(s, null);
-            TransformService ts = (TransformService) instance.impl;
-            ts.algorithm = algorithm;
-            ts.mechanism = mechanismType;
-            ts.provider = instance.provider;
-            return ts;
+        Service s = provider.getService("TransformService", algorithm);
+        if (s != null) {
+            String value = s.getAttribute("MechanismType");
+            if ((value == null && dom) ||
+                (value != null && value.equals(mechanismType))) {
+                Object obj = s.newInstance(null);
+                if (obj instanceof TransformService) {
+                    TransformService ts = (TransformService) obj;
+                    ts.algorithm = algorithm;
+                    ts.mechanism = mechanismType;
+                    ts.provider = provider;
+                    return ts;
+                }
+            }
         }
         throw new NoSuchAlgorithmException
             (algorithm + " algorithm and " + mechanismType
-                 + " mechanism not available");
+                 + " mechanism not available from " + provider.getName());
     }
 
     /**
@@ -268,21 +274,25 @@
         if (mechanismType.equals("DOM")) {
             dom = true;
         }
-        Service s = GetInstance.getService
-            ("TransformService", algorithm, provider);
-        String value = s.getAttribute("MechanismType");
-        if ((value == null && dom) ||
-            (value != null && value.equals(mechanismType))) {
-            Instance instance = GetInstance.getInstance(s, null);
-            TransformService ts = (TransformService) instance.impl;
-            ts.algorithm = algorithm;
-            ts.mechanism = mechanismType;
-            ts.provider = instance.provider;
-            return ts;
+        Provider p = Security.getProvider(provider);
+        Service s = p.getService("TransformService", algorithm);
+        if (s != null) {
+            String value = s.getAttribute("MechanismType");
+            if ((value == null && dom) ||
+                (value != null && value.equals(mechanismType))) {
+                Object obj = s.newInstance(null);
+                if (obj instanceof TransformService) {
+                    TransformService ts = (TransformService) obj;
+                    ts.algorithm = algorithm;
+                    ts.mechanism = mechanismType;
+                    ts.provider = p;
+                    return ts;
+                }
+            }
         }
         throw new NoSuchAlgorithmException
             (algorithm + " algorithm and " + mechanismType
-                 + " mechanism not available");
+                 + " mechanism not available from " + provider);
     }
 
     private static class MechanismMapEntry implements Map.Entry<String,String> {
--- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignatureFactory.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignatureFactory.java	Thu Jul 28 09:01:30 2016 -0700
@@ -43,11 +43,10 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.Provider;
+import java.security.Provider.Service;
 import java.security.Security;
 import java.util.List;
 
-import sun.security.jca.*;
-import sun.security.jca.GetInstance.Instance;
 
 /**
  * A factory for creating {@link XMLSignature} objects from scratch or
@@ -198,17 +197,26 @@
         if (mechanismType == null) {
             throw new NullPointerException("mechanismType cannot be null");
         }
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("XMLSignatureFactory", null, mechanismType);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Provider[] provs = Security.getProviders();
+        for (Provider p : provs) {
+            Service s = p.getService("XMLSignatureFactory", mechanismType);
+            if (s != null) {
+                Object obj = null;
+                try {
+                    obj = s.newInstance(null);
+                } catch (NoSuchAlgorithmException nsae) {
+                    throw new NoSuchMechanismException(nsae);
+                }
+                if (obj instanceof XMLSignatureFactory) {
+                    XMLSignatureFactory factory = (XMLSignatureFactory) obj;
+                    factory.mechanismType = mechanismType;
+                    factory.provider = p;
+                    return factory;
+                }
+            }
         }
-        XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available");
     }
 
     /**
@@ -240,17 +248,25 @@
             throw new NullPointerException("provider cannot be null");
         }
 
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("XMLSignatureFactory", null, mechanismType, provider);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Service s = provider.getService("XMLSignatureFactory", mechanismType);
+        if (s != null) {
+            Object obj = null;
+            try {
+                obj = s.newInstance(null);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchMechanismException(nsae);
+            }
+
+            if (obj instanceof XMLSignatureFactory) {
+                XMLSignatureFactory factory = (XMLSignatureFactory) obj;
+                factory.mechanismType = mechanismType;
+                factory.provider = provider;
+                return factory;
+            }
         }
-        XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available from " +
+             provider.getName());
     }
 
     /**
@@ -288,17 +304,24 @@
             throw new NoSuchProviderException();
         }
 
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("XMLSignatureFactory", null, mechanismType, provider);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Provider p = Security.getProvider(provider);
+        Service s = p.getService("XMLSignatureFactory", mechanismType);
+        if (s != null) {
+            Object obj = null;
+            try {
+                obj = s.newInstance(null);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchMechanismException(nsae);
+            }
+            if (obj instanceof XMLSignatureFactory) {
+                XMLSignatureFactory factory = (XMLSignatureFactory) obj;
+                factory.mechanismType = mechanismType;
+                factory.provider = p;
+                return factory;
+            }
         }
-        XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available from " + provider);
     }
 
     /**
--- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfoFactory.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfoFactory.java	Thu Jul 28 09:01:30 2016 -0700
@@ -32,6 +32,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.Provider;
+import java.security.Provider.Service;
 import java.security.PublicKey;
 import java.security.Security;
 import java.security.cert.X509CRL;
@@ -43,8 +44,6 @@
 import javax.xml.crypto.dom.DOMStructure;
 import javax.xml.crypto.dsig.*;
 
-import sun.security.jca.*;
-import sun.security.jca.GetInstance.Instance;
 
 /**
  * A factory for creating {@link KeyInfo} objects from scratch or for
@@ -153,17 +152,26 @@
         if (mechanismType == null) {
             throw new NullPointerException("mechanismType cannot be null");
         }
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("KeyInfoFactory", null, mechanismType);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Provider[] provs = Security.getProviders();
+        for (Provider p : provs) {
+            Service s = p.getService("KeyInfoFactory", mechanismType);
+            if (s != null) {
+                Object obj = null;
+                try {
+                    obj = s.newInstance(null);
+                } catch (NoSuchAlgorithmException nsae) {
+                    throw new NoSuchMechanismException(nsae);
+                }
+                if (obj instanceof KeyInfoFactory) {
+                    KeyInfoFactory factory = (KeyInfoFactory) obj;
+                    factory.mechanismType = mechanismType;
+                    factory.provider = p;
+                    return factory;
+                }
+            }
         }
-        KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available");
     }
 
     /**
@@ -195,17 +203,24 @@
             throw new NullPointerException("provider cannot be null");
         }
 
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("KeyInfoFactory", null, mechanismType, provider);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Service s = provider.getService("KeyInfoFactory", mechanismType);
+        if (s != null) {
+            Object obj = null;
+            try {
+                obj = s.newInstance(null);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchMechanismException(nsae);
+            }
+
+            if (obj instanceof KeyInfoFactory) {
+                KeyInfoFactory factory = (KeyInfoFactory) obj;
+                factory.mechanismType = mechanismType;
+                factory.provider = provider;
+                return factory;
+            }
         }
-        KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available from " + provider.getName());
     }
 
     /**
@@ -242,18 +257,24 @@
         } else if (provider.length() == 0) {
             throw new NoSuchProviderException();
         }
-
-        Instance instance;
-        try {
-            instance = GetInstance.getInstance
-                ("KeyInfoFactory", null, mechanismType, provider);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new NoSuchMechanismException(nsae);
+        Provider p = Security.getProvider(provider);
+        Service s = p.getService("KeyInfoFactory", mechanismType);
+        if (s != null) {
+            Object obj = null;
+            try {
+                obj = s.newInstance(null);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchMechanismException(nsae);
+            }
+            if (obj instanceof KeyInfoFactory) {
+                KeyInfoFactory factory = (KeyInfoFactory) obj;
+                factory.mechanismType = mechanismType;
+                factory.provider = p;
+                return factory;
+            }
         }
-        KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
-        factory.mechanismType = mechanismType;
-        factory.provider = instance.provider;
-        return factory;
+        throw new NoSuchMechanismException
+            ("Mechanism " + mechanismType + " not available from " + provider);
     }
 
     /**
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -58,8 +58,8 @@
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile;
 import jdk.tools.jlink.internal.ExecutableImage;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.PluginException;
 
 /**
@@ -170,10 +170,10 @@
     }
 
     @Override
-    public void storeFiles(ModulePool files) {
+    public void storeFiles(ResourcePool files) {
         try {
             files.entries().forEach(f -> {
-                if (!f.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
+                if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
                     try {
                         accept(f);
                     } catch (IOException ioExp) {
@@ -181,17 +181,17 @@
                     }
                 }
             });
-            files.modules().forEach(m -> {
+            files.moduleView().modules().forEach(m -> {
                 // Only add modules that contain packages
-                if (!m.getAllPackages().isEmpty()) {
+                if (!m.packages().isEmpty()) {
                     // Skip the fake module used by FileCopierPlugin when copying files.
-                    if (m.getName().equals(FileCopierPlugin.FAKE_MODULE)) {
+                    if (m.name().equals(FileCopierPlugin.FAKE_MODULE)) {
                         return;
                     }
-                    modules.add(m.getName());
+                    modules.add(m.name());
                 }
             });
-            storeFiles(modules, files.getReleaseProperties());
+            storeFiles(modules, files.releaseProperties());
 
             if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
                 // launchers in the bin directory need execute permission
@@ -226,16 +226,16 @@
      * @param modules The set of modules that the runtime image contains.
      * @throws IOException
      */
-    protected void prepareApplicationFiles(ModulePool imageContent, Set<String> modules) throws IOException {
+    protected void prepareApplicationFiles(ResourcePool imageContent, Set<String> modules) throws IOException {
         // generate launch scripts for the modules with a main class
         for (String module : modules) {
             String path = "/" + module + "/module-info.class";
-            Optional<ModuleEntry> res = imageContent.findEntry(path);
+            Optional<ResourcePoolEntry> res = imageContent.findEntry(path);
             if (!res.isPresent()) {
                 throw new IOException("module-info.class not found for " + module + " module");
             }
             Optional<String> mainClass;
-            ByteArrayInputStream stream = new ByteArrayInputStream(res.get().getBytes());
+            ByteArrayInputStream stream = new ByteArrayInputStream(res.get().contentBytes());
             mainClass = ModuleDescriptor.read(stream).mainClass();
             if (mainClass.isPresent()) {
                 Path cmd = root.resolve("bin").resolve(module);
@@ -298,14 +298,14 @@
         }
     }
 
-    private void accept(ModuleEntry file) throws IOException {
-        String fullPath = file.getPath();
-        String module = "/" + file.getModule() + "/";
+    private void accept(ResourcePoolEntry file) throws IOException {
+        String fullPath = file.path();
+        String module = "/" + file.moduleName() + "/";
         String filename = fullPath.substring(module.length());
         // Remove radical native|config|...
         filename = filename.substring(filename.indexOf('/') + 1);
-        try (InputStream in = file.stream()) {
-            switch (file.getType()) {
+        try (InputStream in = file.content()) {
+            switch (file.type()) {
                 case NATIVE_LIB:
                     writeEntry(in, destFile(nativeDir(filename), filename));
                     break;
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -29,7 +29,7 @@
 
 import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 /**
  * Implement this interface to develop your own image layout. First the jimage
@@ -45,7 +45,7 @@
      * @param release the release properties
      * @throws PluginException
      */
-    public default void storeFiles(ModulePool content, Properties release) {
+    public default void storeFiles(ResourcePool content, Properties release) {
         storeFiles(content);
     }
 
@@ -55,7 +55,7 @@
      * @param content Pool of module content.
      * @throws PluginException
      */
-    public default void storeFiles(ModulePool content) {
+    public default void storeFiles(ResourcePool content) {
         throw new UnsupportedOperationException("storeFiles");
     }
 
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jlink.internal;
-
-import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
-
-/**
- * A LinkModuleEntry is the elementary unit of data inside an image. It is
- * generally a file. e.g.: a java class file, a resource file, a shared library,
- * ...
- * <br>
- * A LinkModuleEntry is identified by a path of the form:
- * <ul>
- * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
- * name}</li>
- * <li>For other files (shared lib, launchers, config, ...):/{module name}/
- * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
- * </ul>
- */
-abstract class AbstractModuleEntry implements ModuleEntry {
-    private final String path;
-    private final String module;
-    private final Type type;
-
-    /**
-     * Create a new AbstractModuleEntry.
-     *
-     * @param module The module name.
-     * @param path The data path identifier.
-     * @param type The data type.
-     */
-    AbstractModuleEntry(String module, String path, Type type) {
-        this.module = Objects.requireNonNull(module);
-        this.path = Objects.requireNonNull(path);
-        this.type = Objects.requireNonNull(type);
-    }
-
-    @Override
-    public final String getModule() {
-        return module;
-    }
-
-    @Override
-    public final String getPath() {
-        return path;
-    }
-
-    @Override
-    public final Type getType() {
-        return type;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(this.path);
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (!(other instanceof AbstractModuleEntry)) {
-            return false;
-        }
-        AbstractModuleEntry f = (AbstractModuleEntry) other;
-        return f.path.equals(path);
-    }
-
-    @Override
-    public String toString() {
-        return getPath();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractResourcePoolEntry.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,95 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+
+/**
+ * A LinkResourcePoolEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library,
+ * ...
+ * <br>
+ * A LinkResourcePoolEntry is identified by a path of the form:
+ * <ul>
+ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+ * name}</li>
+ * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+ * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+ * </ul>
+ */
+abstract class AbstractResourcePoolEntry implements ResourcePoolEntry {
+    private final String path;
+    private final String module;
+    private final Type type;
+
+    /**
+     * Create a new AbstractResourcePoolEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param type The data type.
+     */
+    AbstractResourcePoolEntry(String module, String path, Type type) {
+        this.module = Objects.requireNonNull(module);
+        this.path = Objects.requireNonNull(path);
+        this.type = Objects.requireNonNull(type);
+    }
+
+    @Override
+    public final String moduleName() {
+        return module;
+    }
+
+    @Override
+    public final String path() {
+        return path;
+    }
+
+    @Override
+    public final Type type() {
+        return type;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.path);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof AbstractResourcePoolEntry)) {
+            return false;
+        }
+        AbstractResourcePoolEntry f = (AbstractResourcePoolEntry) other;
+        return f.path.equals(path);
+    }
+
+    @Override
+    public String toString() {
+        return path();
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jlink.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
-
-/**
- * A ModuleEntry backed by a given Archive Entry.
- */
-final class ArchiveEntryModuleEntry extends AbstractModuleEntry {
-    private final Archive.Entry entry;
-
-    /**
-     * Create a new ArchiveModuleEntry.
-     *
-     * @param module The module name.
-     * @param path The data path identifier.
-     * @param entry The archive Entry.
-     */
-    ArchiveEntryModuleEntry(String module, String path, Archive.Entry entry) {
-        super(module, path, getImageFileType(Objects.requireNonNull(entry)));
-        this.entry = entry;
-    }
-
-    @Override
-    public InputStream stream() {
-        try {
-            return entry.stream();
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    @Override
-    public long getLength() {
-        return entry.size();
-    }
-
-    private static ModuleEntry.Type getImageFileType(Archive.Entry entry) {
-        switch(entry.type()) {
-            case CLASS_OR_RESOURCE:
-                return ModuleEntry.Type.CLASS_OR_RESOURCE;
-            case CONFIG:
-                return ModuleEntry.Type.CONFIG;
-            case NATIVE_CMD:
-                return ModuleEntry.Type.NATIVE_CMD;
-            case NATIVE_LIB:
-                return ModuleEntry.Type.NATIVE_LIB;
-            default:
-                return ModuleEntry.Type.OTHER;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,80 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+
+/**
+ * A ResourcePoolEntry backed by a given Archive Entry.
+ */
+final class ArchiveEntryResourcePoolEntry extends AbstractResourcePoolEntry {
+    private final Archive.Entry entry;
+
+    /**
+     * Create a new ArchiveResourcePoolEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param entry The archive Entry.
+     */
+    ArchiveEntryResourcePoolEntry(String module, String path, Archive.Entry entry) {
+        super(module, path, getImageFileType(Objects.requireNonNull(entry)));
+        this.entry = entry;
+    }
+
+    @Override
+    public InputStream content() {
+        try {
+            return entry.stream();
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public long contentLength() {
+        return entry.size();
+    }
+
+    private static ResourcePoolEntry.Type getImageFileType(Archive.Entry entry) {
+        switch(entry.type()) {
+            case CLASS_OR_RESOURCE:
+                return ResourcePoolEntry.Type.CLASS_OR_RESOURCE;
+            case CONFIG:
+                return ResourcePoolEntry.Type.CONFIG;
+            case NATIVE_CMD:
+                return ResourcePoolEntry.Type.NATIVE_CMD;
+            case NATIVE_LIB:
+                return ResourcePoolEntry.Type.NATIVE_LIB;
+            default:
+                return ResourcePoolEntry.Type.OTHER;
+        }
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jlink.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.util.Objects;
-
-/**
- * A ModuleEntry backed by a given byte[].
- */
-class ByteArrayModuleEntry extends AbstractModuleEntry {
-    private final byte[] buffer;
-
-    /**
-     * Create a new ByteArrayModuleEntry.
-     *
-     * @param module The module name.
-     * @param path The data path identifier.
-     * @param type The data type.
-     * @param buf  The byte buffer.
-     */
-    ByteArrayModuleEntry(String module, String path, Type type, byte[] buffer) {
-        super(module, path, type);
-        this.buffer = Objects.requireNonNull(buffer);
-    }
-
-    @Override
-    public byte[] getBytes() {
-        return buffer.clone();
-    }
-
-    @Override
-    public InputStream stream() {
-        return new ByteArrayInputStream(buffer);
-    }
-
-    @Override
-    public void write(OutputStream out) {
-        try {
-            out.write(buffer);
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    @Override
-    public long getLength() {
-        return buffer.length;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayResourcePoolEntry.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.util.Objects;
+
+/**
+ * A ResourcePoolEntry backed by a given byte[].
+ */
+class ByteArrayResourcePoolEntry extends AbstractResourcePoolEntry {
+    private final byte[] buffer;
+
+    /**
+     * Create a new ByteArrayResourcePoolEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param type The data type.
+     * @param buf  The byte buffer.
+     */
+    ByteArrayResourcePoolEntry(String module, String path, Type type, byte[] buffer) {
+        super(module, path, type);
+        this.buffer = Objects.requireNonNull(buffer);
+    }
+
+    @Override
+    public byte[] contentBytes() {
+        return buffer.clone();
+    }
+
+    @Override
+    public InputStream content() {
+        return new ByteArrayInputStream(buffer);
+    }
+
+    @Override
+    public void write(OutputStream out) {
+        try {
+            out.write(buffer);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public long contentLength() {
+        return buffer.length;
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Thu Jul 28 09:01:30 2016 -0700
@@ -42,9 +42,10 @@
 import java.util.stream.Stream;
 import jdk.tools.jlink.internal.Archive.Entry;
 import jdk.tools.jlink.internal.Archive.Entry.EntryType;
-import jdk.tools.jlink.internal.ModulePoolImpl.CompressedModuleData;
+import jdk.tools.jlink.internal.ResourcePoolManager.CompressedModuleData;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 /**
  * An image (native endian.)
@@ -140,7 +141,7 @@
                                     }));
             ByteOrder order = ByteOrder.nativeOrder();
             BasicImageWriter writer = new BasicImageWriter(order);
-            ModulePoolImpl pool = createPools(archives, entriesForModule, order, writer);
+            ResourcePoolManager pool = createPoolManager(archives, entriesForModule, order, writer);
             try (OutputStream fos = Files.newOutputStream(jimageFile);
                     BufferedOutputStream bos = new BufferedOutputStream(fos);
                     DataOutputStream out = new DataOutputStream(bos)) {
@@ -158,52 +159,61 @@
             ByteOrder byteOrder)
             throws IOException {
         BasicImageWriter writer = new BasicImageWriter(byteOrder);
-        ModulePoolImpl allContent = createPools(archives,
+        ResourcePoolManager allContent = createPoolManager(archives,
                 entriesForModule, byteOrder, writer);
-        ModulePoolImpl result = generateJImage(allContent,
+        ResourcePool result = generateJImage(allContent,
              writer, plugins, plugins.getJImageFileOutputStream());
 
         //Handle files.
         try {
-            plugins.storeFiles(allContent, result, writer);
+            plugins.storeFiles(allContent.resourcePool(), result, writer);
         } catch (Exception ex) {
+            if (JlinkTask.DEBUG) {
+                ex.printStackTrace();
+            }
             throw new IOException(ex);
         }
     }
 
-    private static ModulePoolImpl generateJImage(ModulePoolImpl allContent,
+    private static ResourcePool generateJImage(ResourcePoolManager allContent,
             BasicImageWriter writer,
             ImagePluginStack pluginSupport,
             DataOutputStream out
     ) throws IOException {
-        ModulePoolImpl resultResources;
+        ResourcePool resultResources;
         try {
             resultResources = pluginSupport.visitResources(allContent);
         } catch (PluginException pe) {
+            if (JlinkTask.DEBUG) {
+                pe.printStackTrace();
+            }
             throw pe;
         } catch (Exception ex) {
+            if (JlinkTask.DEBUG) {
+                ex.printStackTrace();
+            }
             throw new IOException(ex);
         }
         Set<String> duplicates = new HashSet<>();
         long[] offset = new long[1];
 
-        List<ModuleEntry> content = new ArrayList<>();
+        List<ResourcePoolEntry> content = new ArrayList<>();
         List<String> paths = new ArrayList<>();
                  // the order of traversing the resources and the order of
         // the module content being written must be the same
         resultResources.entries().forEach(res -> {
-            if (res.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                String path = res.getPath();
+            if (res.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
+                String path = res.path();
                 content.add(res);
-                long uncompressedSize = res.getLength();
+                long uncompressedSize = res.contentLength();
                 long compressedSize = 0;
                 if (res instanceof CompressedModuleData) {
                     CompressedModuleData comp
                             = (CompressedModuleData) res;
-                    compressedSize = res.getLength();
+                    compressedSize = res.contentLength();
                     uncompressedSize = comp.getUncompressedSize();
                 }
-                long onFileSize = res.getLength();
+                long onFileSize = res.contentLength();
 
                 if (duplicates.contains(path)) {
                     System.err.format("duplicate resource \"%s\", skipping%n",
@@ -239,11 +249,11 @@
         return resultResources;
     }
 
-    private static ModulePoolImpl createPools(Set<Archive> archives,
+    private static ResourcePoolManager createPoolManager(Set<Archive> archives,
             Map<String, List<Entry>> entriesForModule,
             ByteOrder byteOrder,
             BasicImageWriter writer) throws IOException {
-        ModulePoolImpl resources = new ModulePoolImpl(byteOrder, new StringTable() {
+        ResourcePoolManager resources = new ResourcePoolManager(byteOrder, new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -273,7 +283,7 @@
                     path = "/" + mn + "/" + entry.path();
                 }
 
-                resources.add(new ArchiveEntryModuleEntry(mn, path, entry));
+                resources.add(new ArchiveEntryResourcePoolEntry(mn, path, entry));
             }
         }
         return resources;
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Thu Jul 28 09:01:30 2016 -0700
@@ -37,7 +37,7 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.Plugin.Category;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 /**
  * Plugins configuration.
@@ -122,7 +122,7 @@
                 }
 
                 @Override
-                public void storeFiles(ModulePool files) {
+                public void storeFiles(ResourcePool files) {
                     throw new PluginException("No directory setup to store files");
                 }
             };
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Thu Jul 28 09:01:30 2016 -0700
@@ -46,9 +46,10 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.builder.ImageBuilder;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.LinkModule;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
 
 /**
  * Plugins Stack. Plugins entry point to apply transformations onto resources
@@ -61,36 +62,47 @@
         ExecutableImage retrieve(ImagePluginStack stack) throws IOException;
     }
 
-    public static final class OrderedResourcePool extends ModulePoolImpl {
+    public static final class OrderedResourcePoolManager extends ResourcePoolManager {
+        class OrderedResourcePool extends ResourcePoolImpl {
+            List<ResourcePoolEntry> getOrderedList() {
+                return OrderedResourcePoolManager.this.getOrderedList();
+            }
+        }
 
-        private final List<ModuleEntry> orderedList = new ArrayList<>();
+        private final List<ResourcePoolEntry> orderedList = new ArrayList<>();
+        private final ResourcePoolImpl poolImpl = new OrderedResourcePool();
 
-        public OrderedResourcePool(ByteOrder order, StringTable table) {
+        public OrderedResourcePoolManager(ByteOrder order, StringTable table) {
             super(order, table);
         }
 
+        @Override
+        public ResourcePool resourcePool() {
+            return poolImpl;
+        }
+
         /**
          * Add a resource.
          *
          * @param resource The Resource to add.
          */
         @Override
-        public void add(ModuleEntry resource) {
+        public void add(ResourcePoolEntry resource) {
             super.add(resource);
             orderedList.add(resource);
         }
 
-        List<ModuleEntry> getOrderedList() {
+        List<ResourcePoolEntry> getOrderedList() {
             return Collections.unmodifiableList(orderedList);
         }
     }
 
-    private final static class CheckOrderResourcePool extends ModulePoolImpl {
+    private final static class CheckOrderResourcePoolManager extends ResourcePoolManager {
 
-        private final List<ModuleEntry> orderedList;
+        private final List<ResourcePoolEntry> orderedList;
         private int currentIndex;
 
-        public CheckOrderResourcePool(ByteOrder order, List<ModuleEntry> orderedList, StringTable table) {
+        public CheckOrderResourcePoolManager(ByteOrder order, List<ResourcePoolEntry> orderedList, StringTable table) {
             super(order, table);
             this.orderedList = Objects.requireNonNull(orderedList);
         }
@@ -101,10 +113,10 @@
          * @param resource The Resource to add.
          */
         @Override
-        public void add(ModuleEntry resource) {
-            ModuleEntry ordered = orderedList.get(currentIndex);
+        public void add(ResourcePoolEntry resource) {
+            ResourcePoolEntry ordered = orderedList.get(currentIndex);
             if (!resource.equals(ordered)) {
-                throw new PluginException("Resource " + resource.getPath() + " not in the right order");
+                throw new PluginException("Resource " + resource.path() + " not in the right order");
             }
             super.add(resource);
             currentIndex += 1;
@@ -209,17 +221,16 @@
      * @return The result of the visit.
      * @throws IOException
      */
-    public ModulePoolImpl visitResources(ModulePoolImpl resources)
+    public ResourcePool visitResources(ResourcePoolManager resources)
             throws Exception {
         Objects.requireNonNull(resources);
-        resources.setReadOnly();
         if (resources.isEmpty()) {
-            return new ModulePoolImpl(resources.getByteOrder(),
-                    resources.getStringTable());
+            return new ResourcePoolManager(resources.byteOrder(),
+                    resources.getStringTable()).resourcePool();
         }
         PreVisitStrings previsit = new PreVisitStrings();
         resourcePrevisitors.stream().forEach((p) -> {
-            p.previsit(resources, previsit);
+            p.previsit(resources.resourcePool(), previsit);
         });
 
         // Store the strings resulting from the previsit.
@@ -228,89 +239,80 @@
             resources.getStringTable().addString(s);
         });
 
-        ModulePoolImpl current = resources;
-        List<ModuleEntry> frozenOrder = null;
+        ResourcePool resPool = resources.resourcePool();
+        List<ResourcePoolEntry> frozenOrder = null;
         for (Plugin p : plugins) {
-            current.setReadOnly();
-            ModulePoolImpl output = null;
+            ResourcePoolManager resMgr = null;
             if (p == lastSorter) {
                 if (frozenOrder != null) {
                     throw new Exception("Order of resources is already frozen. Plugin "
                             + p.getName() + " is badly located");
                 }
                 // Create a special Resource pool to compute the indexes.
-                output = new OrderedResourcePool(current.getByteOrder(),
+                resMgr = new OrderedResourcePoolManager(resPool.byteOrder(),
                         resources.getStringTable());
             } else {// If we have an order, inject it
                 if (frozenOrder != null) {
-                    output = new CheckOrderResourcePool(current.getByteOrder(),
+                    resMgr = new CheckOrderResourcePoolManager(resPool.byteOrder(),
                             frozenOrder, resources.getStringTable());
                 } else {
-                    output = new ModulePoolImpl(current.getByteOrder(),
+                    resMgr = new ResourcePoolManager(resPool.byteOrder(),
                             resources.getStringTable());
                 }
             }
-            p.visit(current, output);
-            if (output.isEmpty()) {
+            resPool = p.transform(resPool, resMgr.resourcePoolBuilder());
+            if (resPool.isEmpty()) {
                 throw new Exception("Invalid resource pool for plugin " + p);
             }
-            if (output instanceof OrderedResourcePool) {
-                frozenOrder = ((OrderedResourcePool) output).getOrderedList();
+            if (resPool instanceof OrderedResourcePoolManager.OrderedResourcePool) {
+                frozenOrder = ((OrderedResourcePoolManager.OrderedResourcePool)resPool).getOrderedList();
             }
-
-            current = output;
         }
-        current.setReadOnly();
-        return current;
+        return resPool;
     }
 
     /**
-     * This pool wrap the original pool and automatically uncompress ModuleEntry
+     * This pool wrap the original pool and automatically uncompress ResourcePoolEntry
      * if needed.
      */
-    private class LastPool implements ModulePool {
-        private class LastModule implements LinkModule {
+    private class LastPoolManager extends ResourcePoolManager {
+        private class LastModule implements ResourcePoolModule {
 
-            final LinkModule module;
+            final ResourcePoolModule module;
 
-            LastModule(LinkModule module) {
+            LastModule(ResourcePoolModule module) {
                 this.module = module;
             }
 
             @Override
-            public String getName() {
-                return module.getName();
+            public String name() {
+                return module.name();
             }
 
             @Override
-            public Optional<ModuleEntry> findEntry(String path) {
-                Optional<ModuleEntry> d = module.findEntry(path);
+            public Optional<ResourcePoolEntry> findEntry(String path) {
+                Optional<ResourcePoolEntry> d = module.findEntry(path);
                 return d.isPresent()? Optional.of(getUncompressed(d.get())) : Optional.empty();
             }
 
             @Override
-            public ModuleDescriptor getDescriptor() {
-                return module.getDescriptor();
+            public ModuleDescriptor descriptor() {
+                return module.descriptor();
             }
 
             @Override
-            public void add(ModuleEntry data) {
-                throw new PluginException("pool is readonly");
-            }
-
-            @Override
-            public Set<String> getAllPackages() {
-                return module.getAllPackages();
+            public Set<String> packages() {
+                return module.packages();
             }
 
             @Override
             public String toString() {
-                return getName();
+                return name();
             }
 
             @Override
-            public Stream<ModuleEntry> entries() {
-                List<ModuleEntry> lst = new ArrayList<>();
+            public Stream<ResourcePoolEntry> entries() {
+                List<ResourcePoolEntry> lst = new ArrayList<>();
                 module.entries().forEach(md -> {
                     lst.add(getUncompressed(md));
                 });
@@ -318,31 +320,27 @@
             }
 
             @Override
-            public int getEntryCount() {
-                return module.getEntryCount();
+            public int entryCount() {
+                return module.entryCount();
             }
         }
-        private final ModulePoolImpl pool;
+
+        private final ResourcePool pool;
         Decompressor decompressor = new Decompressor();
-        Collection<ModuleEntry> content;
+        Collection<ResourcePoolEntry> content;
 
-        LastPool(ModulePoolImpl pool) {
+        LastPoolManager(ResourcePool pool) {
             this.pool = pool;
         }
 
         @Override
-        public boolean isReadOnly() {
-            return true;
-        }
-
-        @Override
-        public void add(ModuleEntry resource) {
+        public void add(ResourcePoolEntry resource) {
             throw new PluginException("pool is readonly");
         }
 
         @Override
-        public Optional<LinkModule> findModule(String name) {
-            Optional<LinkModule> module = pool.findModule(name);
+        public Optional<ResourcePoolModule> findModule(String name) {
+            Optional<ResourcePoolModule> module = pool.moduleView().findModule(name);
             return module.isPresent()? Optional.of(new LastModule(module.get())) : Optional.empty();
         }
 
@@ -352,17 +350,17 @@
          * @return The collection of modules.
          */
         @Override
-        public Stream<? extends LinkModule> modules() {
-            List<LinkModule> modules = new ArrayList<>();
-            pool.modules().forEach(m -> {
+        public Stream<ResourcePoolModule> modules() {
+            List<ResourcePoolModule> modules = new ArrayList<>();
+            pool.moduleView().modules().forEach(m -> {
                 modules.add(new LastModule(m));
             });
             return modules.stream();
         }
 
         @Override
-        public int getModuleCount() {
-            return pool.getModuleCount();
+        public int moduleCount() {
+            return pool.moduleView().moduleCount();
         }
 
         /**
@@ -371,7 +369,7 @@
          * @return The stream of resources;
          */
         @Override
-        public Stream<? extends ModuleEntry> entries() {
+        public Stream<ResourcePoolEntry> entries() {
             if (content == null) {
                 content = new ArrayList<>();
                 pool.entries().forEach(md -> {
@@ -382,8 +380,8 @@
         }
 
         @Override
-        public int getEntryCount() {
-            return pool.getEntryCount();
+        public int entryCount() {
+            return pool.entryCount();
         }
 
         /**
@@ -393,22 +391,22 @@
          * @return A Resource instance if the resource is found
          */
         @Override
-        public Optional<ModuleEntry> findEntry(String path) {
+        public Optional<ResourcePoolEntry> findEntry(String path) {
             Objects.requireNonNull(path);
-            Optional<ModuleEntry> res = pool.findEntry(path);
+            Optional<ResourcePoolEntry> res = pool.findEntry(path);
             return res.isPresent()? Optional.of(getUncompressed(res.get())) : Optional.empty();
         }
 
         @Override
-        public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
+        public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
             Objects.requireNonNull(path);
             Objects.requireNonNull(context);
-            Optional<ModuleEntry> res = pool.findEntryInContext(path, context);
+            Optional<ResourcePoolEntry> res = pool.findEntryInContext(path, context);
             return res.map(this::getUncompressed);
         }
 
         @Override
-        public boolean contains(ModuleEntry res) {
+        public boolean contains(ResourcePoolEntry res) {
             return pool.contains(res);
         }
 
@@ -418,29 +416,27 @@
         }
 
         @Override
-        public void transformAndCopy(Function<ModuleEntry, ModuleEntry> visitor, ModulePool output) {
-            pool.transformAndCopy(visitor, output);
+        public ByteOrder byteOrder() {
+            return pool.byteOrder();
         }
 
         @Override
-        public ByteOrder getByteOrder() {
-            return pool.getByteOrder();
+        public Map<String, String> releaseProperties() {
+            return pool.releaseProperties();
         }
 
-        @Override
-        public Map<String, String> getReleaseProperties() {
-            return Collections.unmodifiableMap(pool.getReleaseProperties());
-        }
-
-        private ModuleEntry getUncompressed(ModuleEntry res) {
+        private ResourcePoolEntry getUncompressed(ResourcePoolEntry res) {
             if (res != null) {
-                if (res instanceof ModulePoolImpl.CompressedModuleData) {
+                if (res instanceof ResourcePoolManager.CompressedModuleData) {
                     try {
-                        byte[] bytes = decompressor.decompressResource(getByteOrder(),
-                                (int offset) -> pool.getStringTable().getString(offset),
-                                res.getBytes());
-                        res = res.create(bytes);
+                        byte[] bytes = decompressor.decompressResource(byteOrder(),
+                                (int offset) -> ((ResourcePoolImpl)pool).getStringTable().getString(offset),
+                                res.contentBytes());
+                        res = res.copyWithContent(bytes);
                     } catch (IOException ex) {
+                        if (JlinkTask.DEBUG) {
+                            ex.printStackTrace();
+                        }
                         throw new PluginException(ex);
                     }
                 }
@@ -457,24 +453,24 @@
      * @param writer
      * @throws java.lang.Exception
      */
-    public void storeFiles(ModulePoolImpl original, ModulePoolImpl transformed,
+    public void storeFiles(ResourcePool original, ResourcePool transformed,
             BasicImageWriter writer)
             throws Exception {
         Objects.requireNonNull(original);
         Objects.requireNonNull(transformed);
-        Optional<LinkModule> javaBase = transformed.findModule("java.base");
+        Optional<ResourcePoolModule> javaBase = transformed.moduleView().findModule("java.base");
         javaBase.ifPresent(mod -> {
             try {
-                Map<String, String> release = transformed.getReleaseProperties();
+                Map<String, String> release = transformed.releaseProperties();
                 // fill release information available from transformed "java.base" module!
-                ModuleDescriptor desc = mod.getDescriptor();
+                ModuleDescriptor desc = mod.descriptor();
                 desc.osName().ifPresent(s -> release.put("OS_NAME", s));
                 desc.osVersion().ifPresent(s -> release.put("OS_VERSION", s));
                 desc.osArch().ifPresent(s -> release.put("OS_ARCH", s));
             } catch (Exception ignored) {}
         });
 
-        imageBuilder.storeFiles(new LastPool(transformed));
+        imageBuilder.storeFiles(new LastPoolManager(transformed).resourcePool());
     }
 
     public ExecutableImage getExecutableImage() throws IOException {
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Thu Jul 28 09:01:30 2016 -0700
@@ -61,7 +61,7 @@
  * ## Should use jdk.joptsimple some day.
  */
 public class JlinkTask {
-    private static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
+    static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
 
     private static <T extends Throwable> void fail(Class<T> type,
             String format,
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal;
-
-import java.nio.file.Path;
-import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
-
-public final class ModuleEntryFactory {
-    private ModuleEntryFactory() {}
-
-    public static ModuleEntry create(String path,
-            ModuleEntry.Type type, byte[] content) {
-        return new ByteArrayModuleEntry(moduleFrom(path), path, type, content);
-    }
-
-    public static ModuleEntry create(String path,
-            ModuleEntry.Type type, Path file) {
-        return new PathModuleEntry(moduleFrom(path), path, type, file);
-    }
-
-    public static ModuleEntry create(ModuleEntry original, byte[] content) {
-        return new ByteArrayModuleEntry(original.getModule(),
-                original.getPath(), original.getType(), content);
-    }
-
-    public static ModuleEntry create(ModuleEntry original, Path file) {
-        return new PathModuleEntry(original.getModule(),
-                original.getPath(), original.getType(), file);
-    }
-
-    static String moduleFrom(String path) {
-        Objects.requireNonNull(path);
-        if (path.isEmpty() || path.charAt(0) != '/') {
-            throw new IllegalArgumentException(path + " must start with /");
-        }
-        int idx = path.indexOf('/', 1);
-        if (idx == -1) {
-            throw new IllegalArgumentException("/ missing after module: " + path);
-        }
-        return path.substring(1, idx);
-    }
-
-    static String packageFrom(String path) {
-        Objects.requireNonNull(path);
-        int idx = path.lastIndexOf('/');
-        if (idx == -1) {
-            throw new IllegalArgumentException("/ missing from path: " + path);
-        }
-        if (path.startsWith("/")) {
-            int jdx = path.indexOf('/', 1);
-            if (jdx == -1) {
-                throw new IllegalArgumentException("/ missing after module: " + path);
-            }
-            return path.substring(jdx + 1, idx);
-        } else {
-            return path.substring(0, idx);
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,436 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.internal;
-
-import java.lang.module.ModuleDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import jdk.internal.jimage.decompressor.CompressedResourceHeader;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.LinkModule;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-
-/**
- * Pool of module data.
- */
-public class ModulePoolImpl implements ModulePool {
-
-    private class ModuleImpl implements LinkModule {
-
-        final Map<String, ModuleEntry> moduleContent = new LinkedHashMap<>();
-        private ModuleDescriptor descriptor;
-        final String name;
-
-        private ModuleImpl(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public Optional<ModuleEntry> findEntry(String path) {
-            if (!path.startsWith("/")) {
-                path = "/" + path;
-            }
-            if (!path.startsWith("/" + name)) {
-                path = "/" + name + path;
-            }
-            return Optional.ofNullable(moduleContent.get(path));
-        }
-
-        @Override
-        public ModuleDescriptor getDescriptor() {
-            if (descriptor == null) {
-                String p = "/" + name + "/module-info.class";
-                Optional<ModuleEntry> content = findEntry(p);
-                if (!content.isPresent()) {
-                    throw new PluginException("No module-info for " + name
-                            + " module");
-                }
-                ByteBuffer bb = ByteBuffer.wrap(content.get().getBytes());
-                descriptor = ModuleDescriptor.read(bb);
-            }
-            return descriptor;
-        }
-
-        @Override
-        public void add(ModuleEntry data) {
-            if (isReadOnly()) {
-                throw new PluginException("ModulePool is readonly");
-            }
-            Objects.requireNonNull(data);
-            if (!data.getModule().equals(name)) {
-                throw new PluginException("Can't add resource " + data.getPath()
-                        + " to module " + name);
-            }
-            ModulePoolImpl.this.add(data);
-        }
-
-        @Override
-        public Set<String> getAllPackages() {
-            Set<String> pkgs = new HashSet<>();
-            moduleContent.values().stream().filter(m -> m.getType().
-                    equals(ModuleEntry.Type.CLASS_OR_RESOURCE)).forEach(res -> {
-                // Module metadata only contains packages with .class files
-                if (ImageFileCreator.isClassPackage(res.getPath())) {
-                    String[] split = ImageFileCreator.splitPath(res.getPath());
-                    String pkg = split[1];
-                    if (pkg != null && !pkg.isEmpty()) {
-                        pkgs.add(pkg);
-                    }
-                }
-            });
-            return pkgs;
-        }
-
-        @Override
-        public String toString() {
-            return getName();
-        }
-
-        @Override
-        public Stream<? extends ModuleEntry> entries() {
-            return moduleContent.values().stream();
-        }
-
-        @Override
-        public int getEntryCount() {
-            return moduleContent.values().size();
-        }
-    }
-
-    private final Map<String, ModuleEntry> resources = new LinkedHashMap<>();
-    private final Map<String, ModuleImpl> modules = new LinkedHashMap<>();
-    private final ModuleImpl fileCopierModule = new ModuleImpl(FileCopierPlugin.FAKE_MODULE);
-    private Map<String, String> releaseProps = new HashMap<>();
-
-    private final ByteOrder order;
-
-    private boolean isReadOnly;
-    private final StringTable table;
-
-    public ModulePoolImpl() {
-        this(ByteOrder.nativeOrder());
-    }
-
-    public ModulePoolImpl(ByteOrder order) {
-        this(order, new StringTable() {
-
-            @Override
-            public int addString(String str) {
-                return -1;
-            }
-
-            @Override
-            public String getString(int id) {
-                return null;
-            }
-        });
-    }
-
-    public ModulePoolImpl(ByteOrder order, StringTable table) {
-        this.order = Objects.requireNonNull(order);
-        this.table = Objects.requireNonNull(table);
-    }
-
-    /**
-     * Add a ModuleEntry.
-     *
-     * @param data The ModuleEntry to add.
-     */
-    @Override
-    public void add(ModuleEntry data) {
-        if (isReadOnly()) {
-            throw new PluginException("ModulePool is readonly");
-        }
-        Objects.requireNonNull(data);
-        if (resources.get(data.getPath()) != null) {
-            throw new PluginException("Resource " + data.getPath()
-                    + " already present");
-        }
-        String modulename = data.getModule();
-        ModuleImpl m = modules.get(modulename);
-        // ## TODO: FileCopierPlugin should not add content to a module
-        // FAKE_MODULE is not really a module to be added in the image
-        if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
-            m = fileCopierModule;
-        }
-        if (m == null) {
-            m = new ModuleImpl(modulename);
-            modules.put(modulename, m);
-        }
-        resources.put(data.getPath(), data);
-        m.moduleContent.put(data.getPath(), data);
-    }
-
-    /**
-     * Retrieves the module for the provided name.
-     *
-     * @param name The module name
-     * @return the module of matching name, if found
-     */
-    @Override
-    public Optional<LinkModule> findModule(String name) {
-        Objects.requireNonNull(name);
-        return Optional.ofNullable(modules.get(name));
-    }
-
-    /**
-     * The stream of modules contained in this ModulePool.
-     *
-     * @return The stream of modules.
-     */
-    @Override
-    public Stream<? extends LinkModule> modules() {
-        return modules.values().stream();
-    }
-
-    /**
-     * Return the number of LinkModule count in this ModulePool.
-     *
-     * @return the module count.
-     */
-    @Override
-    public int getModuleCount() {
-        return modules.size();
-    }
-
-    /**
-     * Get all ModuleEntry contained in this ModulePool instance.
-     *
-     * @return The stream of LinkModuleEntries.
-     */
-    @Override
-    public Stream<? extends ModuleEntry> entries() {
-        return resources.values().stream();
-    }
-
-    /**
-     * Return the number of ModuleEntry count in this ModulePool.
-     *
-     * @return the entry count.
-     */
-    @Override
-    public int getEntryCount() {
-        return resources.values().size();
-    }
-
-    /**
-     * Get the ModuleEntry for the passed path.
-     *
-     * @param path A data path
-     * @return A ModuleEntry instance or null if the data is not found
-     */
-    @Override
-    public Optional<ModuleEntry> findEntry(String path) {
-        Objects.requireNonNull(path);
-        return Optional.ofNullable(resources.get(path));
-    }
-
-    /**
-     * Get the ModuleEntry for the passed path restricted to supplied context.
-     *
-     * @param path A data path
-     * @param context A context of the search
-     * @return A ModuleEntry instance or null if the data is not found
-     */
-    @Override
-    public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(context);
-        LinkModule module = modules.get(context.getModule());
-        Objects.requireNonNull(module);
-        Optional<ModuleEntry> entry = module.findEntry(path);
-        // Navigating other modules via requires and exports is problematic
-        // since we cannot construct the runtime model of loaders and layers.
-        return entry;
-     }
-
-    /**
-     * Check if the ModulePool contains the given ModuleEntry.
-     *
-     * @param data The module data to check existence for.
-     * @return The module data or null if not found.
-     */
-    @Override
-    public boolean contains(ModuleEntry data) {
-        Objects.requireNonNull(data);
-        return findEntry(data.getPath()).isPresent();
-    }
-
-    /**
-     * Check if the ModulePool contains some content at all.
-     *
-     * @return True, no content, false otherwise.
-     */
-    @Override
-    public boolean isEmpty() {
-        return resources.isEmpty();
-    }
-
-    /**
-     * Visit each ModuleEntry in this ModulePool to transform it and
-     * copy the transformed ModuleEntry to the output ModulePool.
-     *
-     * @param transform The function called for each ModuleEntry found in
-     * the ModulePool. The transform function should return a
-     * ModuleEntry instance which will be added to the output or it should
-     * return null if the passed ModuleEntry is to be ignored for the
-     * output.
-     *
-     * @param output The ModulePool to be filled with Visitor returned
-     * ModuleEntry.
-     */
-    @Override
-    public void transformAndCopy(Function<ModuleEntry, ModuleEntry> transform,
-            ModulePool output) {
-        entries().forEach(resource -> {
-            ModuleEntry res = transform.apply(resource);
-            if (res != null) {
-                output.add(res);
-            }
-        });
-    }
-
-    /**
-     * The ByteOrder currently in use when generating the jimage file.
-     *
-     * @return The ByteOrder.
-     */
-    @Override
-    public ByteOrder getByteOrder() {
-        return order;
-    }
-
-    @Override
-    public Map<String, String> getReleaseProperties() {
-        return isReadOnly()? Collections.unmodifiableMap(releaseProps) : releaseProps;
-    }
-
-    public StringTable getStringTable() {
-        return table;
-    }
-
-    /**
-     * Make this Resources instance read-only. No resource can be added.
-     */
-    public void setReadOnly() {
-        isReadOnly = true;
-    }
-
-    /**
-     * Read only state.
-     *
-     * @return true if readonly false otherwise.
-     */
-    @Override
-    public boolean isReadOnly() {
-        return isReadOnly;
-    }
-
-    /**
-     * A resource that has been compressed.
-     */
-    public static final class CompressedModuleData extends ByteArrayModuleEntry {
-
-        final long uncompressed_size;
-
-        private CompressedModuleData(String module, String path,
-                byte[] content, long uncompressed_size) {
-            super(module, path, ModuleEntry.Type.CLASS_OR_RESOURCE, content);
-            this.uncompressed_size = uncompressed_size;
-        }
-
-        public long getUncompressedSize() {
-            return uncompressed_size;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof CompressedModuleData)) {
-                return false;
-            }
-            CompressedModuleData f = (CompressedModuleData) other;
-            return f.getPath().equals(getPath());
-        }
-
-        @Override
-        public int hashCode() {
-            return super.hashCode();
-        }
-    }
-
-    public static CompressedModuleData newCompressedResource(ModuleEntry original,
-            ByteBuffer compressed,
-            String plugin, String pluginConfig, StringTable strings,
-            ByteOrder order) {
-        Objects.requireNonNull(original);
-        Objects.requireNonNull(compressed);
-        Objects.requireNonNull(plugin);
-
-        boolean isTerminal = !(original instanceof CompressedModuleData);
-        long uncompressed_size = original.getLength();
-        if (original instanceof CompressedModuleData) {
-            CompressedModuleData comp = (CompressedModuleData) original;
-            uncompressed_size = comp.getUncompressedSize();
-        }
-        int nameOffset = strings.addString(plugin);
-        int configOffset = -1;
-        if (pluginConfig != null) {
-            configOffset = strings.addString(plugin);
-        }
-        CompressedResourceHeader rh
-                = new CompressedResourceHeader(compressed.limit(), original.getLength(),
-                        nameOffset, configOffset, isTerminal);
-        // Merge header with content;
-        byte[] h = rh.getBytes(order);
-        ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
-        bb.order(order);
-        bb.put(h);
-        bb.put(compressed);
-        byte[] contentWithHeader = bb.array();
-
-        CompressedModuleData compressedResource
-                = new CompressedModuleData(original.getModule(), original.getPath(),
-                        contentWithHeader, uncompressed_size);
-        return compressedResource;
-    }
-
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classfile" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jlink.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-
-/**
- * A ModuleEntry backed by a given nio Path.
- */
-public class PathModuleEntry extends AbstractModuleEntry {
-    private final Path file;
-
-    /**
-     * Create a new PathModuleEntry.
-     *
-     * @param module The module name.
-     * @param path The path for the resource content.
-     * @param type The data type.
-     * @param file The data file identifier.
-     */
-    public PathModuleEntry(String module, String path, Type type, Path file) {
-        super(module, path, type);
-        this.file = Objects.requireNonNull(file);
-        if (!Files.isRegularFile(file)) {
-            throw new IllegalArgumentException(file + " not a file");
-        }
-    }
-
-    @Override
-    public final InputStream stream() {
-        try {
-            return Files.newInputStream(file);
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    @Override
-    public final long getLength() {
-        try {
-            return Files.size(file);
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classfile" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+
+/**
+ * A ResourcePoolEntry backed by a given nio Path.
+ */
+public class PathResourcePoolEntry extends AbstractResourcePoolEntry {
+    private final Path file;
+
+    /**
+     * Create a new PathResourcePoolEntry.
+     *
+     * @param module The module name.
+     * @param path The path for the resource content.
+     * @param type The data type.
+     * @param file The data file identifier.
+     */
+    public PathResourcePoolEntry(String module, String path, Type type, Path file) {
+        super(module, path, type);
+        this.file = Objects.requireNonNull(file);
+        if (!Files.isRegularFile(file)) {
+            throw new IllegalArgumentException(file + " not a file");
+        }
+    }
+
+    @Override
+    public final InputStream content() {
+        try {
+            return Files.newInputStream(file);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public final long contentLength() {
+        try {
+            return Files.size(file);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolEntryFactory.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.nio.file.Path;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+
+public final class ResourcePoolEntryFactory {
+    private ResourcePoolEntryFactory() {}
+
+    public static ResourcePoolEntry create(String path,
+            ResourcePoolEntry.Type type, byte[] content) {
+        return new ByteArrayResourcePoolEntry(moduleFrom(path), path, type, content);
+    }
+
+    public static ResourcePoolEntry create(String path,
+            ResourcePoolEntry.Type type, Path file) {
+        return new PathResourcePoolEntry(moduleFrom(path), path, type, file);
+    }
+
+    public static ResourcePoolEntry create(ResourcePoolEntry original, byte[] content) {
+        return new ByteArrayResourcePoolEntry(original.moduleName(),
+                original.path(), original.type(), content);
+    }
+
+    public static ResourcePoolEntry create(ResourcePoolEntry original, Path file) {
+        return new PathResourcePoolEntry(original.moduleName(),
+                original.path(), original.type(), file);
+    }
+
+    private static String moduleFrom(String path) {
+        Objects.requireNonNull(path);
+        if (path.isEmpty() || path.charAt(0) != '/') {
+            throw new IllegalArgumentException(path + " must start with /");
+        }
+        String noRoot = path.substring(1);
+        int idx = noRoot.indexOf('/');
+        if (idx == -1) {
+            throw new IllegalArgumentException("/ missing after module: " + path);
+        }
+        return noRoot.substring(0, idx);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,469 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.lang.module.ModuleDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
+import jdk.tools.jlink.plugin.ResourcePoolModuleView;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+
+/**
+ * A manager for pool of resources.
+ */
+public class ResourcePoolManager {
+
+    class ResourcePoolModuleImpl implements ResourcePoolModule {
+
+        final Map<String, ResourcePoolEntry> moduleContent = new LinkedHashMap<>();
+        private ModuleDescriptor descriptor;
+        final String name;
+
+        private ResourcePoolModuleImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+        @Override
+        public Optional<ResourcePoolEntry> findEntry(String path) {
+            if (!path.startsWith("/")) {
+                path = "/" + path;
+            }
+            if (!path.startsWith("/" + name)) {
+                path = "/" + name + path;
+            }
+            return Optional.ofNullable(moduleContent.get(path));
+        }
+
+        @Override
+        public ModuleDescriptor descriptor() {
+            if (descriptor == null) {
+                String p = "/" + name + "/module-info.class";
+                Optional<ResourcePoolEntry> content = findEntry(p);
+                if (!content.isPresent()) {
+                    throw new PluginException("No module-info for " + name
+                            + " module");
+                }
+                ByteBuffer bb = ByteBuffer.wrap(content.get().contentBytes());
+                descriptor = ModuleDescriptor.read(bb);
+            }
+            return descriptor;
+        }
+
+        @Override
+        public Set<String> packages() {
+            Set<String> pkgs = new HashSet<>();
+            moduleContent.values().stream().filter(m -> m.type().
+                    equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)).forEach(res -> {
+                // Module metadata only contains packages with .class files
+                if (ImageFileCreator.isClassPackage(res.path())) {
+                    String[] split = ImageFileCreator.splitPath(res.path());
+                    String pkg = split[1];
+                    if (pkg != null && !pkg.isEmpty()) {
+                        pkgs.add(pkg);
+                    }
+                }
+            });
+            return pkgs;
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+
+        @Override
+        public Stream<ResourcePoolEntry> entries() {
+            return moduleContent.values().stream();
+        }
+
+        @Override
+        public int entryCount() {
+            return moduleContent.values().size();
+        }
+    }
+
+    public class ResourcePoolImpl implements ResourcePool {
+        @Override
+        public ResourcePoolModuleView moduleView() {
+            return ResourcePoolManager.this.moduleView();
+        }
+
+        @Override
+        public Stream<ResourcePoolEntry> entries() {
+            return ResourcePoolManager.this.entries();
+        }
+
+        @Override
+        public int entryCount() {
+            return ResourcePoolManager.this.entryCount();
+        }
+
+        @Override
+        public Optional<ResourcePoolEntry> findEntry(String path) {
+            return ResourcePoolManager.this.findEntry(path);
+        }
+
+        @Override
+        public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
+            return ResourcePoolManager.this.findEntryInContext(path, context);
+        }
+
+        @Override
+        public boolean contains(ResourcePoolEntry data) {
+            return ResourcePoolManager.this.contains(data);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return ResourcePoolManager.this.isEmpty();
+        }
+
+        @Override
+        public ByteOrder byteOrder() {
+            return ResourcePoolManager.this.byteOrder();
+        }
+
+        @Override
+        public Map<String, String> releaseProperties() {
+            return ResourcePoolManager.this.releaseProperties();
+        }
+
+        public StringTable getStringTable() {
+            return ResourcePoolManager.this.getStringTable();
+        }
+    }
+
+    class ResourcePoolBuilderImpl implements ResourcePoolBuilder {
+        private boolean built;
+
+        @Override
+        public void add(ResourcePoolEntry data) {
+            if (built) {
+                throw new IllegalStateException("resource pool already built!");
+            }
+            ResourcePoolManager.this.add(data);
+        }
+
+        @Override
+        public ResourcePool build() {
+            built = true;
+            return ResourcePoolManager.this.resourcePool();
+        }
+    }
+
+    class ResourcePoolModuleViewImpl implements ResourcePoolModuleView {
+        @Override
+        public Optional<ResourcePoolModule> findModule(String name) {
+            return ResourcePoolManager.this.findModule(name);
+        }
+
+        @Override
+        public Stream<ResourcePoolModule> modules() {
+            return ResourcePoolManager.this.modules();
+        }
+
+        @Override
+        public int moduleCount() {
+            return ResourcePoolManager.this.moduleCount();
+        }
+    }
+
+    private final Map<String, ResourcePoolEntry> resources = new LinkedHashMap<>();
+    private final Map<String, ResourcePoolModule> modules = new LinkedHashMap<>();
+    private final ResourcePoolModuleImpl fileCopierModule = new ResourcePoolModuleImpl(FileCopierPlugin.FAKE_MODULE);
+    private Map<String, String> releaseProps = new HashMap<>();
+    private final ByteOrder order;
+    private final StringTable table;
+    private final ResourcePool poolImpl;
+    private final ResourcePoolBuilder poolBuilderImpl;
+    private final ResourcePoolModuleView moduleViewImpl;
+
+    public ResourcePoolManager() {
+        this(ByteOrder.nativeOrder());
+    }
+
+    public ResourcePoolManager(ByteOrder order) {
+        this(order, new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+    }
+
+    public ResourcePoolManager(ByteOrder order, StringTable table) {
+        this.order = Objects.requireNonNull(order);
+        this.table = Objects.requireNonNull(table);
+        this.poolImpl = new ResourcePoolImpl();
+        this.poolBuilderImpl = new ResourcePoolBuilderImpl();
+        this.moduleViewImpl = new ResourcePoolModuleViewImpl();
+    }
+
+    public ResourcePool resourcePool() {
+        return poolImpl;
+    }
+
+    public ResourcePoolBuilder resourcePoolBuilder() {
+        return poolBuilderImpl;
+    }
+
+    public ResourcePoolModuleView moduleView() {
+        return moduleViewImpl;
+    }
+
+    /**
+     * Add a ResourcePoolEntry.
+     *
+     * @param data The ResourcePoolEntry to add.
+     */
+    public void add(ResourcePoolEntry data) {
+        Objects.requireNonNull(data);
+        if (resources.get(data.path()) != null) {
+            throw new PluginException("Resource " + data.path()
+                    + " already present");
+        }
+        String modulename = data.moduleName();
+        ResourcePoolModuleImpl m = (ResourcePoolModuleImpl)modules.get(modulename);
+        // ## TODO: FileCopierPlugin should not add content to a module
+        // FAKE_MODULE is not really a module to be added in the image
+        if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
+            m = fileCopierModule;
+        }
+        if (m == null) {
+            m = new ResourcePoolModuleImpl(modulename);
+            modules.put(modulename, m);
+        }
+        resources.put(data.path(), data);
+        m.moduleContent.put(data.path(), data);
+    }
+
+    /**
+     * Retrieves the module for the provided name.
+     *
+     * @param name The module name
+     * @return the module of matching name, if found
+     */
+    public Optional<ResourcePoolModule> findModule(String name) {
+        Objects.requireNonNull(name);
+        return Optional.ofNullable(modules.get(name));
+    }
+
+    /**
+     * The stream of modules contained in this ResourcePool.
+     *
+     * @return The stream of modules.
+     */
+    public Stream<ResourcePoolModule> modules() {
+        return modules.values().stream();
+    }
+
+    /**
+     * Return the number of ResourcePoolModule count in this ResourcePool.
+     *
+     * @return the module count.
+     */
+    public int moduleCount() {
+        return modules.size();
+    }
+
+    /**
+     * Get all ResourcePoolEntry contained in this ResourcePool instance.
+     *
+     * @return The stream of ResourcePoolModuleEntries.
+     */
+    public Stream<ResourcePoolEntry> entries() {
+        return resources.values().stream();
+    }
+
+    /**
+     * Return the number of ResourcePoolEntry count in this ResourcePool.
+     *
+     * @return the entry count.
+     */
+    public int entryCount() {
+        return resources.values().size();
+    }
+
+    /**
+     * Get the ResourcePoolEntry for the passed path.
+     *
+     * @param path A data path
+     * @return A ResourcePoolEntry instance or null if the data is not found
+     */
+    public Optional<ResourcePoolEntry> findEntry(String path) {
+        Objects.requireNonNull(path);
+        return Optional.ofNullable(resources.get(path));
+    }
+
+    /**
+     * Get the ResourcePoolEntry for the passed path restricted to supplied context.
+     *
+     * @param path A data path
+     * @param context A context of the search
+     * @return A ResourcePoolEntry instance or null if the data is not found
+     */
+    public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(context);
+        ResourcePoolModule module = modules.get(context.moduleName());
+        Objects.requireNonNull(module);
+        Optional<ResourcePoolEntry> entry = module.findEntry(path);
+        // Navigating other modules via requires and exports is problematic
+        // since we cannot construct the runtime model of loaders and layers.
+        return entry;
+     }
+
+    /**
+     * Check if the ResourcePool contains the given ResourcePoolEntry.
+     *
+     * @param data The module data to check existence for.
+     * @return The module data or null if not found.
+     */
+    public boolean contains(ResourcePoolEntry data) {
+        Objects.requireNonNull(data);
+        return findEntry(data.path()).isPresent();
+    }
+
+    /**
+     * Check if the ResourcePool contains some content at all.
+     *
+     * @return True, no content, false otherwise.
+     */
+    public boolean isEmpty() {
+        return resources.isEmpty();
+    }
+
+    /**
+     * The ByteOrder currently in use when generating the jimage file.
+     *
+     * @return The ByteOrder.
+     */
+    public ByteOrder byteOrder() {
+        return order;
+    }
+
+    public Map<String, String> releaseProperties() {
+        return releaseProps;
+    }
+
+    public StringTable getStringTable() {
+        return table;
+    }
+
+    /**
+     * A resource that has been compressed.
+     */
+    public static final class CompressedModuleData extends ByteArrayResourcePoolEntry {
+
+        final long uncompressed_size;
+
+        private CompressedModuleData(String module, String path,
+                byte[] content, long uncompressed_size) {
+            super(module, path, ResourcePoolEntry.Type.CLASS_OR_RESOURCE, content);
+            this.uncompressed_size = uncompressed_size;
+        }
+
+        public long getUncompressedSize() {
+            return uncompressed_size;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof CompressedModuleData)) {
+                return false;
+            }
+            CompressedModuleData f = (CompressedModuleData) other;
+            return f.path().equals(path());
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+    }
+
+    public static CompressedModuleData newCompressedResource(ResourcePoolEntry original,
+            ByteBuffer compressed,
+            String plugin, String pluginConfig, StringTable strings,
+            ByteOrder order) {
+        Objects.requireNonNull(original);
+        Objects.requireNonNull(compressed);
+        Objects.requireNonNull(plugin);
+
+        boolean isTerminal = !(original instanceof CompressedModuleData);
+        long uncompressed_size = original.contentLength();
+        if (original instanceof CompressedModuleData) {
+            CompressedModuleData comp = (CompressedModuleData) original;
+            uncompressed_size = comp.getUncompressedSize();
+        }
+        int nameOffset = strings.addString(plugin);
+        int configOffset = -1;
+        if (pluginConfig != null) {
+            configOffset = strings.addString(plugin);
+        }
+        CompressedResourceHeader rh
+                = new CompressedResourceHeader(compressed.limit(), original.contentLength(),
+                        nameOffset, configOffset, isTerminal);
+        // Merge header with content;
+        byte[] h = rh.getBytes(order);
+        ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
+        bb.order(order);
+        bb.put(h);
+        bb.put(compressed);
+        byte[] contentWithHeader = bb.array();
+
+        CompressedModuleData compressedResource
+                = new CompressedModuleData(original.moduleName(), original.path(),
+                        contentWithHeader, uncompressed_size);
+        return compressedResource;
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Thu Jul 28 09:01:30 2016 -0700
@@ -24,7 +24,7 @@
  */
 package jdk.tools.jlink.internal;
 
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 /**
  * Plugin wishing to pre-visit the resources must implement this interface.
@@ -43,5 +43,5 @@
      * @param strings StringTable instance. Add string to the StringTable to track string
      * usage.
      */
-    public void previsit(ModulePool resources, StringTable strings);
+    public void previsit(ResourcePool resources, StringTable strings);
 }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -29,7 +29,8 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import static jdk.internal.org.objectweb.asm.ClassReader.*;
@@ -44,7 +45,7 @@
 import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
 import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
 import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 
 public final class ClassForNamePlugin implements Plugin {
@@ -55,8 +56,8 @@
                               path.length() - ".class".length());
     }
 
-    private static int getAccess(ModuleEntry resource) {
-        ClassReader cr = new ClassReader(resource.getBytes());
+    private static int getAccess(ResourcePoolEntry resource) {
+        ClassReader cr = new ClassReader(resource.contentBytes());
 
         return cr.getAccess();
     }
@@ -67,8 +68,8 @@
         return index == -1 ? "" : binaryName.substring(0, index);
     }
 
-    private ModuleEntry transform(ModuleEntry resource, ModulePool pool) {
-        byte[] inBytes = resource.getBytes();
+    private ResourcePoolEntry transform(ResourcePoolEntry resource, ResourcePool pool) {
+        byte[] inBytes = resource.contentBytes();
         ClassReader cr = new ClassReader(inBytes);
         ClassNode cn = new ClassNode();
         cr.accept(cn, EXPAND_FRAMES);
@@ -76,7 +77,7 @@
         boolean modified = false;
         LdcInsnNode ldc = null;
 
-        String thisPackage = getPackage(binaryClassName(resource.getPath()));
+        String thisPackage = getPackage(binaryClassName(resource.path()));
 
         for (MethodNode mn : ms) {
             InsnList il = mn.instructions;
@@ -96,7 +97,7 @@
                         min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
                         String ldcClassName = ldc.cst.toString();
                         String thatClassName = ldcClassName.replaceAll("\\.", "/");
-                        Optional<ModuleEntry> thatClass =
+                        Optional<ResourcePoolEntry> thatClass =
                             pool.findEntryInContext(thatClassName + ".class", resource);
 
                         if (thatClass.isPresent()) {
@@ -128,7 +129,7 @@
             cn.accept(cw);
             byte[] outBytes = cw.toByteArray();
 
-            return resource.create(outBytes);
+            return resource.copyWithContent(outBytes);
         }
 
         return resource;
@@ -140,13 +141,13 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         Objects.requireNonNull(in);
         Objects.requireNonNull(out);
 
         in.entries()
             .forEach(resource -> {
-                String path = resource.getPath();
+                String path = resource.path();
 
                 if (path.endsWith(".class") && !path.endsWith("/module-info.class")) {
                     out.add(transform(resource, in));
@@ -154,6 +155,7 @@
                     out.add(resource);
                 }
             });
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -26,10 +26,12 @@
 
 import java.util.Map;
 
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 
@@ -53,21 +55,22 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         if (ss != null && zip != null) {
-            ModulePool output = new ImagePluginStack.OrderedResourcePool(in.getByteOrder(),
-                    ((ModulePoolImpl) in).getStringTable());
-            ss.visit(in, output);
-            zip.visit(output, out);
+            ResourcePoolManager resMgr = new ImagePluginStack.OrderedResourcePoolManager(
+                    in.byteOrder(), ((ResourcePoolImpl)in).getStringTable());
+            return zip.transform(ss.transform(in, resMgr.resourcePoolBuilder()), out);
         } else if (ss != null) {
-            ss.visit(in, out);
+            return ss.transform(in, out);
         } else if (zip != null) {
-            zip.visit(in, out);
+            return zip.transform(in, out);
         }
+
+        return out.build();
     }
 
     @Override
-    public void previsit(ModulePool resources, StringTable strings) {
+    public void previsit(ResourcePool resources, StringTable strings) {
         if (ss != null) {
             ss.previsit(resources, strings);
         }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -27,8 +27,9 @@
 import java.util.Map;
 import java.util.function.Predicate;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 /**
  *
@@ -45,13 +46,14 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((file) -> {
-            if (!file.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                file = predicate.test(file.getPath()) ? file : null;
+            if (!file.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
+                file = predicate.test(file.path()) ? file : null;
             }
             return file;
         }, out);
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -27,8 +27,9 @@
 import java.util.Map;
 import java.util.function.Predicate;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 /**
  *
@@ -45,13 +46,14 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((resource) -> {
-            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                resource = predicate.test(resource.getPath()) ? resource : null;
+            if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
+                resource = predicate.test(resource.path()) ? resource : null;
             }
             return resource;
         }, out);
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -36,8 +36,9 @@
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.PluginException;
 
 /**
@@ -97,25 +98,25 @@
      * e.g.: /java.base/native/amd64/server/libjvm.so
      * /java.base/native/server/libjvm.dylib
      */
-    private List<ModuleEntry> getVMs(ModulePool in) {
+    private List<ResourcePoolEntry> getVMs(ResourcePool in) {
         String jvmlib = jvmlib();
-        List<ModuleEntry> ret = in.findModule("java.base").get().entries().filter((t) -> {
-            return t.getPath().endsWith("/" + jvmlib);
+        List<ResourcePoolEntry> ret = in.moduleView().findModule("java.base").get().entries().filter((t) -> {
+            return t.path().endsWith("/" + jvmlib);
         }).collect(Collectors.toList());
         return ret;
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         String jvmlib = jvmlib();
         TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
         TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
         if (!keepAll) {
             // First retrieve all available VM names and removed VM
-            List<ModuleEntry> jvms = getVMs(in);
+            List<ResourcePoolEntry> jvms = getVMs(in);
             for (Jvm jvm : Jvm.values()) {
-                for (ModuleEntry md : jvms) {
-                    if (md.getPath().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
+                for (ResourcePoolEntry md : jvms) {
+                    if (md.path().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
                         existing.add(jvm);
                         if (isRemoved(md)) {
                             removed.add(jvm);
@@ -134,8 +135,8 @@
         // Rewrite the jvm.cfg file.
         in.transformAndCopy((file) -> {
             if (!keepAll) {
-                if (file.getType().equals(ModuleEntry.Type.NATIVE_LIB)) {
-                    if (file.getPath().endsWith(JVM_CFG)) {
+                if (file.type().equals(ResourcePoolEntry.Type.NATIVE_LIB)) {
+                    if (file.path().endsWith(JVM_CFG)) {
                         try {
                             file = handleJvmCfgFile(file, existing, removed);
                         } catch (IOException ex) {
@@ -148,10 +149,11 @@
             return file;
         }, out);
 
+        return out.build();
     }
 
-    private boolean isRemoved(ModuleEntry file) {
-        return !predicate.test(file.getPath());
+    private boolean isRemoved(ResourcePoolEntry file) {
+        return !predicate.test(file.path());
     }
 
     @Override
@@ -206,7 +208,7 @@
         predicate = ResourceFilter.excludeFilter(exclude);
     }
 
-    private ModuleEntry handleJvmCfgFile(ModuleEntry orig,
+    private ResourcePoolEntry handleJvmCfgFile(ResourcePoolEntry orig,
             TreeSet<Jvm> existing,
             TreeSet<Jvm> removed) throws IOException {
         if (keepAll) {
@@ -215,7 +217,7 @@
         StringBuilder builder = new StringBuilder();
         // Keep comments
         try (BufferedReader reader
-                = new BufferedReader(new InputStreamReader(orig.stream(),
+                = new BufferedReader(new InputStreamReader(orig.content(),
                         StandardCharsets.UTF_8))) {
             reader.lines().forEach((s) -> {
                 if (s.startsWith("#")) {
@@ -242,7 +244,7 @@
 
         byte[] content = builder.toString().getBytes(StandardCharsets.UTF_8);
 
-        return orig.create(content);
+        return orig.copyWithContent(content);
     }
 
     private static String jvmlib() {
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -37,10 +37,11 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import jdk.tools.jlink.internal.PathModuleEntry;
+import jdk.tools.jlink.internal.PathResourcePoolEntry;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.Utils;
 
@@ -64,12 +65,12 @@
     /**
      * Symbolic link to another path.
      */
-    public static abstract class SymImageFile extends PathModuleEntry {
+    public static abstract class SymImageFile extends PathResourcePoolEntry {
 
         private final String targetPath;
 
         public SymImageFile(String targetPath, String module, String path,
-                ModuleEntry.Type type, Path file) {
+                ResourcePoolEntry.Type type, Path file) {
             super(module, path, type, file);
             this.targetPath = targetPath;
         }
@@ -82,7 +83,7 @@
     private static final class SymImageFileImpl extends SymImageFile {
 
         public SymImageFileImpl(String targetPath, Path file, String module,
-                String path, ModuleEntry.Type type) {
+                String path, ResourcePoolEntry.Type type) {
             super(targetPath, module, path, type, file);
         }
     }
@@ -90,11 +91,11 @@
     private static final class DirectoryCopy implements FileVisitor<Path> {
 
         private final Path source;
-        private final ModulePool pool;
+        private final ResourcePoolBuilder pool;
         private final String targetDir;
         private final List<SymImageFile> symlinks = new ArrayList<>();
 
-        DirectoryCopy(Path source, ModulePool pool, String targetDir) {
+        DirectoryCopy(Path source, ResourcePoolBuilder pool, String targetDir) {
             this.source = source;
             this.pool = pool;
             this.targetDir = targetDir;
@@ -128,7 +129,7 @@
                 }
                 SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(),
                         file, path, Objects.requireNonNull(file.getFileName()).toString(),
-                        ModuleEntry.Type.OTHER);
+                        ResourcePoolEntry.Type.OTHER);
                 symlinks.add(impl);
             } else {
                 addFile(pool, file, path);
@@ -152,14 +153,14 @@
         }
     }
 
-    private static void addFile(ModulePool pool, Path file, String path)
+    private static void addFile(ResourcePoolBuilder pool, Path file, String path)
             throws IOException {
         Objects.requireNonNull(pool);
         Objects.requireNonNull(file);
         Objects.requireNonNull(path);
-        ModuleEntry impl = ModuleEntry.create(
+        ResourcePoolEntry impl = ResourcePoolEntry.create(
                 "/" + FAKE_MODULE + "/other/" + path,
-                ModuleEntry.Type.OTHER, file);
+                ResourcePoolEntry.Type.OTHER, file);
         try {
             pool.add(impl);
         } catch (Exception ex) {
@@ -211,7 +212,7 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((file) -> {
             return file;
         }, out);
@@ -238,6 +239,8 @@
         } catch (IOException ex) {
             throw new UncheckedIOException(ex);
         }
+
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -31,9 +31,10 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 
 /**
@@ -145,22 +146,22 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.entries().forEach(data -> {
-            if (("/java.base/" + BMH + ".class").equals(data.getPath())) {
+            if (("/java.base/" + BMH + ".class").equals(data.path())) {
                 // Add BoundMethodHandle unchanged
                 out.add(data);
                 speciesTypes.forEach(types -> generateConcreteClass(types, data, out));
             } else {
-                if (!out.contains(data)) {
-                    out.add(data);
-                }
+                out.add(data);
             }
         });
+
+        return out.build();
     }
 
     @SuppressWarnings("unchecked")
-    private void generateConcreteClass(String types, ModuleEntry data, ModulePool out) {
+    private void generateConcreteClass(String types, ResourcePoolEntry data, ResourcePoolBuilder out) {
         try {
             // Generate class
             Map.Entry<String, byte[]> result = (Map.Entry<String, byte[]>)
@@ -169,12 +170,10 @@
             byte[] bytes = result.getValue();
 
             // Add class to pool
-            ModuleEntry ndata = ModuleEntry.create(
+            ResourcePoolEntry ndata = ResourcePoolEntry.create(
                     "/java.base/" + className + ".class",
                     bytes);
-            if (!out.contains(ndata)) {
-                out.add(ndata);
-            }
+            out.add(ndata);
         } catch (Exception ex) {
             throw new PluginException(ex);
         }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -42,10 +42,11 @@
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
-import jdk.tools.jlink.plugin.LinkModule;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 import sun.util.cldr.CLDRBaseLocaleDataMetaInfo;
 import sun.util.locale.provider.LocaleProviderAdapter;
@@ -151,24 +152,26 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((resource) -> {
-            if (resource.getModule().equals(MODULENAME)) {
-                String path = resource.getPath();
+            if (resource.moduleName().equals(MODULENAME)) {
+                String path = resource.path();
                 resource = predicate.test(path) ? resource: null;
                 if (resource != null &&
-                    resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                    byte[] bytes = resource.getBytes();
+                    resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
+                    byte[] bytes = resource.contentBytes();
                     ClassReader cr = new ClassReader(bytes);
                     if (Arrays.stream(cr.getInterfaces())
                         .anyMatch(i -> i.contains(METAINFONAME)) &&
                         stripUnsupportedLocales(bytes, cr)) {
-                        resource = resource.create(bytes);
+                        resource = resource.copyWithContent(bytes);
                     }
                 }
             }
             return resource;
         }, out);
+
+        return out.build();
     }
 
     @Override
@@ -205,14 +208,14 @@
     }
 
     @Override
-    public void previsit(ModulePool resources, StringTable strings) {
+    public void previsit(ResourcePool resources, StringTable strings) {
         final Pattern p = Pattern.compile(".*((Data_)|(Names_))(?<tag>.*)\\.class");
-        Optional<LinkModule> optMod = resources.findModule(MODULENAME);
+        Optional<ResourcePoolModule> optMod = resources.moduleView().findModule(MODULENAME);
 
         // jdk.localedata module validation
         if (optMod.isPresent()) {
-            LinkModule module = optMod.get();
-            Set<String> packages = module.getAllPackages();
+            ResourcePoolModule module = optMod.get();
+            Set<String> packages = module.packages();
             if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
                 throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
                     LOCALEDATA_PACKAGES.stream()
@@ -221,7 +224,7 @@
             }
 
             available = Stream.concat(module.entries()
-                                        .map(md -> p.matcher(md.getPath()))
+                                        .map(md -> p.matcher(md.path()))
                                         .filter(m -> m.matches())
                                         .map(m -> m.group("tag").replaceAll("_", "-")),
                                     Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag)))
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -35,8 +35,9 @@
 import java.util.Map;
 import java.util.function.ToIntFunction;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.Utils;
 
@@ -62,20 +63,20 @@
     }
 
     static class SortWrapper {
-        private final ModuleEntry resource;
+        private final ResourcePoolEntry resource;
         private final int ordinal;
 
-        SortWrapper(ModuleEntry resource, int ordinal) {
+        SortWrapper(ResourcePoolEntry resource, int ordinal) {
             this.resource = resource;
             this.ordinal = ordinal;
         }
 
-        ModuleEntry getResource() {
+        ResourcePoolEntry getResource() {
             return resource;
         }
 
         String getPath() {
-            return resource.getPath();
+            return resource.path();
         }
 
         int getOrdinal() {
@@ -95,8 +96,8 @@
         return path;
     }
 
-    private int getOrdinal(ModuleEntry resource) {
-        String path = resource.getPath();
+    private int getOrdinal(ResourcePoolEntry resource) {
+        String path = resource.path();
 
         Integer value = orderedPaths.get(stripModule(path));
 
@@ -126,17 +127,19 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.entries()
-                .filter(resource -> resource.getType()
-                        .equals(ModuleEntry.Type.CLASS_OR_RESOURCE))
+                .filter(resource -> resource.type()
+                        .equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE))
                 .map((resource) -> new SortWrapper(resource, getOrdinal(resource)))
                 .sorted(OrderResourcesPlugin::compare)
                 .forEach((wrapper) -> out.add(wrapper.getResource()));
         in.entries()
-                .filter(other -> !other.getType()
-                        .equals(ModuleEntry.Type.CLASS_OR_RESOURCE))
+                .filter(other -> !other.type()
+                        .equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE))
                 .forEach((other) -> out.add(other));
+
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -33,7 +33,8 @@
 import java.util.Set;
 import java.util.function.Function;
 import jdk.tools.jlink.internal.Utils;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin.Category;
 import jdk.tools.jlink.plugin.Plugin.State;
 import jdk.tools.jlink.plugin.Plugin;
@@ -117,9 +118,8 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
-        in.transformAndCopy(Function.identity(), out);
-        out.getReleaseProperties().putAll(in.getReleaseProperties());
-        out.getReleaseProperties().putAll(release);
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
+        in.releaseProperties().putAll(release);
+        return in;
     }
 }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -55,11 +55,13 @@
 import jdk.internal.jimage.decompressor.CompressIndexes;
 import jdk.internal.jimage.decompressor.SignatureParser;
 import jdk.internal.jimage.decompressor.StringSharingDecompressor;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 
@@ -226,22 +228,22 @@
             }
         }
 
-        public byte[] transform(ModuleEntry resource, ModulePool out,
+        public byte[] transform(ResourcePoolEntry resource, ResourcePoolBuilder out,
                 StringTable strings) throws IOException, Exception {
-            byte[] content = resource.getBytes();
+            byte[] content = resource.contentBytes();
             ClassFile cf;
             try (InputStream stream = new ByteArrayInputStream(content)) {
                 cf = ClassFile.read(stream);
             } catch (ConstantPoolException ex) {
                 throw new IOException("Compressor EX " + ex + " for "
-                        + resource.getPath() + " content.length " + content.length, ex);
+                        + resource.path() + " content.length " + content.length, ex);
             }
             DescriptorsScanner scanner = new DescriptorsScanner(cf);
             return optimize(resource, out, strings, scanner.scan(), content);
         }
 
         @SuppressWarnings("fallthrough")
-        private byte[] optimize(ModuleEntry resource, ModulePool resources,
+        private byte[] optimize(ResourcePoolEntry resource, ResourcePoolBuilder resources,
                 StringTable strings,
                 Set<Integer> descriptorIndexes, byte[] content) throws Exception {
             DataInputStream stream = new DataInputStream(new ByteArrayInputStream(content));
@@ -347,23 +349,25 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool result) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder result) {
         CompactCPHelper visit = new CompactCPHelper();
         in.transformAndCopy((resource) -> {
-            ModuleEntry res = resource;
-            if (predicate.test(resource.getPath()) && resource.getPath().endsWith(".class")) {
+            ResourcePoolEntry res = resource;
+            if (predicate.test(resource.path()) && resource.path().endsWith(".class")) {
                 byte[] compressed = null;
                 try {
-                    compressed = visit.transform(resource, result, ((ModulePoolImpl) in).getStringTable());
+                    compressed = visit.transform(resource, result, ((ResourcePoolImpl)in).getStringTable());
                 } catch (Exception ex) {
                     throw new PluginException(ex);
                 }
-                res = ModulePoolImpl.newCompressedResource(resource,
+                res = ResourcePoolManager.newCompressedResource(resource,
                         ByteBuffer.wrap(compressed), getName(), null,
-                        ((ModulePoolImpl) in).getStringTable(), in.getByteOrder());
+                        ((ResourcePoolImpl)in).getStringTable(), in.byteOrder());
             }
             return res;
         }, result);
+
+        return result.build();
     }
 
     @Override
@@ -392,11 +396,11 @@
     }
 
     @Override
-    public void previsit(ModulePool resources, StringTable strings) {
+    public void previsit(ResourcePool resources, StringTable strings) {
         CompactCPHelper preVisit = new CompactCPHelper();
         resources.entries().forEach(resource -> {
-            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)
-                    && resource.getPath().endsWith(".class") && predicate.test(resource.getPath())) {
+            if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
+                    && resource.path().endsWith(".class") && predicate.test(resource.path())) {
                 try {
                     preVisit.transform(resource, null, strings);
                 } catch (Exception ex) {
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -27,8 +27,9 @@
 import java.util.function.Predicate;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 
 /**
@@ -58,27 +59,29 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         //remove *.diz files as well as debug attributes.
         in.transformAndCopy((resource) -> {
-            ModuleEntry res = resource;
-            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                String path = resource.getPath();
+            ResourcePoolEntry res = resource;
+            if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
+                String path = resource.path();
                 if (path.endsWith(".class")) {
                     if (path.endsWith("module-info.class")) {
                         // XXX. Do we have debug info? Is Asm ready for module-info?
                     } else {
-                        ClassReader reader = new ClassReader(resource.getBytes());
+                        ClassReader reader = new ClassReader(resource.contentBytes());
                         ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                         reader.accept(writer, ClassReader.SKIP_DEBUG);
                         byte[] content = writer.toByteArray();
-                        res = resource.create(content);
+                        res = resource.copyWithContent(content);
                     }
                 }
-            } else if (predicate.test(res.getPath())) {
+            } else if (predicate.test(res.path())) {
                 res = null;
             }
             return res;
         }, out);
+
+        return out.build();
     }
 }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -24,8 +24,9 @@
  */
 package jdk.tools.jlink.internal.plugins;
 
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 
 /**
@@ -47,10 +48,12 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((file) -> {
-            return file.getType() == ModuleEntry.Type.NATIVE_CMD ? null : file;
+            return file.type() == ResourcePoolEntry.Type.NATIVE_CMD ? null : file;
         }, out);
+
+        return out.build();
     }
 
     @Override
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -51,10 +51,11 @@
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 /**
  * Jlink plugin to reconstitute module descriptors for installed modules.
@@ -107,7 +108,7 @@
 
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         if (!enabled) {
             throw new PluginException(NAME + " was set");
         }
@@ -116,30 +117,30 @@
 
         // generate the byte code to create ModuleDescriptors
         // skip parsing module-info.class and skip name check
-        in.modules().forEach(module -> {
-            Optional<ModuleEntry> optData = module.findEntry("module-info.class");
+        in.moduleView().modules().forEach(module -> {
+            Optional<ResourcePoolEntry> optData = module.findEntry("module-info.class");
             if (! optData.isPresent()) {
                 // automatic module not supported yet
                 throw new PluginException("module-info.class not found for " +
-                                          module.getName() + " module");
+                                          module.name() + " module");
             }
-            ModuleEntry data = optData.get();
-            assert module.getName().equals(data.getModule());
+            ResourcePoolEntry data = optData.get();
+            assert module.name().equals(data.moduleName());
             try {
-                ByteArrayInputStream bain = new ByteArrayInputStream(data.getBytes());
+                ByteArrayInputStream bain = new ByteArrayInputStream(data.contentBytes());
                 ModuleDescriptor md = ModuleDescriptor.read(bain);
                 validateNames(md);
 
-                ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages());
+                ModuleDescriptorBuilder mbuilder = builder.module(md, module.packages());
                 int packages = md.exports().size() + md.conceals().size();
                 if (md.conceals().isEmpty() &&
-                        packages != module.getAllPackages().size()) {
+                        packages != module.packages().size()) {
                     // add ConcealedPackages attribute if not exist
                     bain.reset();
                     ModuleInfoRewriter minfoWriter =
                         new ModuleInfoRewriter(bain, mbuilder.conceals());
                     // replace with the overridden version
-                    data = data.create(minfoWriter.getBytes());
+                    data = data.copyWithContent(minfoWriter.getBytes());
                 }
                 out.add(data);
             } catch (IOException e) {
@@ -150,16 +151,18 @@
         // Generate the new class
         ClassWriter cwriter = builder.build();
         in.entries().forEach(data -> {
-            if (data.getPath().endsWith("module-info.class"))
+            if (data.path().endsWith("module-info.class"))
                 return;
-            if (builder.isOverriddenClass(data.getPath())) {
+            if (builder.isOverriddenClass(data.path())) {
                 byte[] bytes = cwriter.toByteArray();
-                ModuleEntry ndata = data.create(bytes);
+                ResourcePoolEntry ndata = data.copyWithContent(bytes);
                 out.add(ndata);
             } else {
                 out.add(data);
             }
         });
+
+        return out.build();
     }
 
     /*
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -31,9 +31,11 @@
 import java.util.Map;
 import java.util.function.Predicate;
 import java.util.zip.Deflater;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.Plugin;
 
 /**
@@ -112,18 +114,20 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy((resource) -> {
-            ModuleEntry res = resource;
-            if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)
-                    && predicate.test(resource.getPath())) {
+            ResourcePoolEntry res = resource;
+            if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
+                    && predicate.test(resource.path())) {
                 byte[] compressed;
-                compressed = compress(resource.getBytes());
-                res = ModulePoolImpl.newCompressedResource(resource,
+                compressed = compress(resource.contentBytes());
+                res = ResourcePoolManager.newCompressedResource(resource,
                         ByteBuffer.wrap(compressed), getName(), null,
-                        ((ModulePoolImpl) in).getStringTable(), in.getByteOrder());
+                        ((ResourcePoolImpl)in).getStringTable(), in.byteOrder());
             }
             return res;
         }, out);
+
+        return out.build();
     }
 }
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.plugin;
-
-import java.lang.module.ModuleDescriptor;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Stream;
-
-/**
-  * Link-time representation of a Java module.
-  */
-public interface LinkModule {
-
-    /**
-     * The module name.
-     *
-     * @return The name.
-     */
-    public String getName();
-
-    /**
-     * Retrieves a LinkModuleEntry from the given path (e.g:
-     * /mymodule/com.foo.bar/MyClass.class)
-     *
-     * @param path The piece of data path.
-     * @return A LinkModuleEntry of the given path, if found.
-     */
-    public Optional<ModuleEntry> findEntry(String path);
-
-    /**
-     * The module descriptor of this module.
-     *
-     * @return The module descriptor.
-     */
-    public ModuleDescriptor getDescriptor();
-
-    /**
-     * Add a LinkModuleEntry to this module.
-     *
-     * @param data The LinkModuleEntry to add.
-     */
-    public void add(ModuleEntry data);
-
-    /**
-     * Retrieves all the packages located in this module.
-     *
-     * @return The set of packages.
-     */
-    public Set<String> getAllPackages();
-
-    /**
-     * Retrieves the stream of LinkModuleEntry.
-     *
-     * @return The LinkModuleEntry stream.
-     */
-    public Stream<? extends ModuleEntry> entries();
-
-    /**
-     * Return the number of LinkModuleEntry count in this LinkModule.
-     *
-     * @return the entry count.
-     */
-    public int getEntryCount();
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.plugin;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import jdk.tools.jlink.internal.ModuleEntryFactory;
-
-/**
- * A ModuleEntry is the elementary unit of data inside an image. It is
- * generally a file. e.g.: a java class file, a resource file, a shared library.
- * <br>
- * A ModuleEntry is identified by a path of the form:
- * <ul>
- * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
- * name}</li>
- * <li>For other files (shared lib, launchers, config, ...):/{module name}/
- * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name}</li>
- * </ul>
- */
-public interface ModuleEntry {
-
-    /**
-     * Type of module data.
-     * <li>
-     * <ul>CLASS_OR_RESOURCE: A java class or resource file.</ul>
-     * <ul>CONFIG: A configuration file.</ul>
-     * <ul>NATIVE_CMD: A native process launcher.</ul>
-     * <ul>NATIVE_LIB: A native library.</ul>
-     * <ul>OTHER: Other kind of file.</ul>
-     * </li>
-     */
-    public enum Type {
-        CLASS_OR_RESOURCE,
-        CONFIG,
-        NATIVE_CMD,
-        NATIVE_LIB,
-        OTHER
-    }
-    /**
-     * The ModuleEntry module name.
-     *
-     * @return The module name.
-     */
-    public String getModule();
-
-    /**
-     * The ModuleEntry path.
-     *
-     * @return The module path.
-     */
-    public String getPath();
-
-    /**
-     * The ModuleEntry's type.
-     *
-     * @return The data type.
-     */
-    public Type getType();
-
-    /**
-     * The ModuleEntry content as an array of bytes.
-     *
-     * @return An Array of bytes.
-     */
-    public default byte[] getBytes() {
-        try (InputStream is = stream()) {
-            return is.readAllBytes();
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    /**
-     * The ModuleEntry content length.
-     *
-     * @return The length.
-     */
-    public long getLength();
-
-    /**
-     * The ModuleEntry stream.
-     *
-     * @return The module data stream.
-     */
-    public InputStream stream();
-
-    /**
-     * Write the content of this ModuleEntry to stream.
-     *
-     * @param out the output stream
-     */
-    public default void write(OutputStream out) {
-        try {
-            out.write(getBytes());
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    /**
-     * Create a ModuleEntry with new content but other information
-     * copied from this ModuleEntry.
-     *
-     * @param content The new resource content.
-     * @return A new ModuleEntry.
-     */
-    public default ModuleEntry create(byte[] content) {
-        return ModuleEntryFactory.create(this, content);
-    }
-
-    /**
-     * Create a ModuleEntry with new content but other information
-     * copied from this ModuleEntry.
-     *
-     * @param file The new resource content.
-     * @return A new ModuleEntry.
-     */
-    public default ModuleEntry create(Path file) {
-        return ModuleEntryFactory.create(this, file);
-    }
-
-    /**
-     * Create a ModuleEntry for a resource of the given type.
-     *
-     * @param path The resource path.
-     * @param type The ModuleEntry type.
-     * @param content The resource content.
-     * @return A new ModuleEntry.
-     */
-    public static ModuleEntry create(String path,
-            ModuleEntry.Type type, byte[] content) {
-        return ModuleEntryFactory.create(path, type, content);
-    }
-
-    /**
-     * Create a ModuleEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
-     *
-     * @param path The resource path.
-     * @param content The resource content.
-     * @return A new ModuleEntry.
-     */
-    public static ModuleEntry create(String path, byte[] content) {
-        return create(path, Type.CLASS_OR_RESOURCE, content);
-    }
-
-    /**
-     * Create a ModuleEntry for a resource of the given type.
-     *
-     * @param path The resource path.
-     * @param type The ModuleEntry type.
-     * @param file The resource file.
-     * @return A new ModuleEntry.
-     */
-    public static ModuleEntry create(String path,
-            ModuleEntry.Type type, Path file) {
-        return ModuleEntryFactory.create(path, type, file);
-    }
-
-    /**
-     * Create a ModuleEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
-     *
-     * @param path The resource path.
-     * @param file The resource file.
-     * @return A new ModuleEntry.
-     */
-    public static ModuleEntry create(String path, Path file) {
-        return create(path, Type.CLASS_OR_RESOURCE, file);
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java	Tue Jul 26 14:45:11 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jlink.plugin;
-
-import java.nio.ByteOrder;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-/**
- * Pool of module data.
- */
-public interface ModulePool {
-/**
-     * Is this a read-only ModulePool?
-     *
-     * @return true if this is a read-only configuration.
-     */
-    public boolean isReadOnly();
-
-    /**
-     * Add a ModuleEntry.
-     *
-     * @param data The ModuleEntry to add.
-     */
-    public void add(ModuleEntry data);
-    /**
-     * Retrieves the module for the provided name.
-     *
-     * @param name The module name
-     * @return the module of matching name, if found
-     */
-    public Optional<LinkModule> findModule(String name);
-
-    /**
-     * The stream of modules contained in this ModulePool.
-     *
-     * @return The stream of modules.
-     */
-    public Stream<? extends LinkModule> modules();
-
-    /**
-     * Return the number of LinkModule count in this ModulePool.
-     *
-     * @return the module count.
-     */
-    public int getModuleCount();
-
-    /**
-     * Get all ModuleEntry contained in this ModulePool instance.
-     *
-     * @return The stream of LinkModuleEntries.
-     */
-    public Stream<? extends ModuleEntry> entries();
-
-    /**
-     * Return the number of ModuleEntry count in this ModulePool.
-     *
-     * @return the entry count.
-     */
-    public int getEntryCount();
-
-    /**
-     * Get the ModuleEntry for the passed path.
-     *
-     * @param path A data path
-     * @return A ModuleEntry instance or null if the data is not found
-     */
-    public Optional<ModuleEntry> findEntry(String path);
-
-    /**
-     * Get the ModuleEntry for the passed path restricted to supplied context.
-     *
-     * @param path A data path
-     * @param context A context of the search
-     * @return A ModuleEntry instance or null if the data is not found
-     */
-    public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context);
-
-    /**
-     * Check if the ModulePool contains the given ModuleEntry.
-     *
-     * @param data The module data to check existence for.
-     * @return The module data or null if not found.
-     */
-    public boolean contains(ModuleEntry data);
-
-    /**
-     * Check if the ModulePool contains some content at all.
-     *
-     * @return True, no content, false otherwise.
-     */
-    public boolean isEmpty();
-
-    /**
-     * Visit each ModuleEntry in this ModulePool to transform it and copy
-     * the transformed ModuleEntry to the output ModulePool.
-     *
-     * @param transform The function called for each ModuleEntry found in the
-     * ModulePool. The transform function should return a ModuleEntry
-     * instance which will be added to the output or it should return null if
-     * the passed ModuleEntry is to be ignored for the output.
-     *
-     * @param output The ModulePool to be filled with Visitor returned
-     * ModuleEntry.
-     */
-    public void transformAndCopy(Function<ModuleEntry, ModuleEntry> transform, ModulePool output);
-
-    /**
-     * The ByteOrder currently in use when generating the jimage file.
-     *
-     * @return The ByteOrder.
-     */
-    public ByteOrder getByteOrder();
-
-    /**
-     * Release properties such as OS, CPU name, version etc.
-     *
-     * @return the release properties
-     */
-    public Map<String, String> getReleaseProperties();
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -191,5 +191,5 @@
      *
      * @throws PluginException
      */
-    public void visit(ModulePool in, ModulePool out);
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePool.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.nio.ByteOrder;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * A Pool of Java resources.
+ */
+public interface ResourcePool {
+    /**
+     * Return the module view of this resource pool.
+     *
+     * @return a module based view of this resource pool.
+     */
+    public ResourcePoolModuleView moduleView();
+
+    /**
+     * Get all ResourcePoolEntry contained in this ResourcePool instance.
+     *
+     * @return The stream of ResourcePoolEntries.
+     */
+    public Stream<ResourcePoolEntry> entries();
+
+    /**
+     * Return the number of ResourcePoolEntry count in this ResourcePool.
+     *
+     * @return the entry count.
+     */
+    public int entryCount();
+
+    /**
+     * Get the ResourcePoolEntry for the passed path.
+     *
+     * @param path A data path
+     * @return A ResourcePoolEntry instance or null if the data is not found
+     */
+    public Optional<ResourcePoolEntry> findEntry(String path);
+
+    /**
+     * Get the ModuleEntry for the passed path restricted to supplied context.
+     *
+     * @param path A data path
+     * @param context A context of the search
+     * @return A ModuleEntry instance or null if the data is not found
+     */
+    public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context);
+
+    /**
+     * Check if the ResourcePool contains the given ResourcePoolEntry.
+     *
+     * @param data The module data to check existence for.
+     * @return The module data or null if not found.
+     */
+    public boolean contains(ResourcePoolEntry data);
+
+    /**
+     * Check if the ResourcePool contains some content at all.
+     *
+     * @return True, no content, false otherwise.
+     */
+    public boolean isEmpty();
+
+    /**
+     * The ByteOrder currently in use when generating the jimage file.
+     *
+     * @return The ByteOrder.
+     */
+    public ByteOrder byteOrder();
+
+    /**
+     * Release properties such as OS, CPU name, version etc.
+     *
+     * @return the release properties
+     */
+    public Map<String, String> releaseProperties();
+
+    /**
+     * Visit each ResourcePoolEntry in this ResourcePool to transform it and copy
+     * the transformed ResourcePoolEntry to the output ResourcePoolBuilder.
+     *
+     * @param transform The function called for each ResourcePoolEntry found in the
+     * ResourcePool. The transform function should return a ResourcePoolEntry
+     * instance which will be added to the output or it should return null if
+     * the passed ResourcePoolEntry is to be ignored for the output.
+     *
+     * @param outBuilder The ResourcePoolBuilder to be filled with Visitor returned
+     * ResourcePoolEntries.
+     */
+    public default void transformAndCopy(
+            Function<ResourcePoolEntry, ResourcePoolEntry> transform,
+            ResourcePoolBuilder outBuilder) {
+        entries().forEach(resource -> {
+            ResourcePoolEntry res = transform.apply(resource);
+            if (res != null) {
+                outBuilder.add(res);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,52 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.nio.ByteOrder;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Resource pool builder to build a resource pool by incrementally
+ * adding a set of resources one at a time.
+ */
+public interface ResourcePoolBuilder {
+    /**
+     * Add a ResourcePoolEntry.
+     *
+     * @param data The ResourcePoolEntry to add.
+     */
+    public void add(ResourcePoolEntry data);
+
+    /**
+     * Done with adding resource entries. Construct
+     * a ResourcePool with the added resource entries.
+     *
+     * @return a new ResourcePool filled with entries added.
+     */
+    public ResourcePool build();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,198 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import jdk.tools.jlink.internal.ResourcePoolEntryFactory;
+
+/**
+ * A ResourcePoolEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library.
+ * <br>
+ * A ResourcePoolEntry is identified by a path of the form:
+ * <ul>
+ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+ * name}</li>
+ * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+ * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name}</li>
+ * </ul>
+ */
+public interface ResourcePoolEntry {
+
+    /**
+     * Type of module data.
+     * <li>
+     * <ul>CLASS_OR_RESOURCE: A java class or resource file.</ul>
+     * <ul>CONFIG: A configuration file.</ul>
+     * <ul>NATIVE_CMD: A native process launcher.</ul>
+     * <ul>NATIVE_LIB: A native library.</ul>
+     * <ul>OTHER: Other kind of file.</ul>
+     * </li>
+     */
+    public enum Type {
+        CLASS_OR_RESOURCE,
+        CONFIG,
+        NATIVE_CMD,
+        NATIVE_LIB,
+        OTHER
+    }
+
+    /**
+     * The module name of this ResourcePoolEntry.
+     *
+     * @return The module name.
+     */
+    public String moduleName();
+
+    /**
+     * The path of this ResourcePoolEntry.
+     *
+     * @return The module path.
+     */
+    public String path();
+
+    /**
+     * The ResourcePoolEntry's type.
+     *
+     * @return The data type.
+     */
+    public Type type();
+
+    /**
+     * The ResourcePoolEntry content length.
+     *
+     * @return The content length.
+     */
+    public long contentLength();
+
+    /**
+     * The ResourcePoolEntry content as an InputStream.
+     *
+     * @return The resource content as an InputStream.
+     */
+    public InputStream content();
+
+    /**
+     * The ResourcePoolEntry content as an array of bytes.
+     *
+     * @return An Array of bytes.
+     */
+    public default byte[] contentBytes() {
+        try (InputStream is = content()) {
+            return is.readAllBytes();
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    /**
+     * Write the content of this ResourcePoolEntry to an OutputStream.
+     *
+     * @param out the output stream
+     */
+    public default void write(OutputStream out) {
+        try {
+            out.write(contentBytes());
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    /**
+     * Create a ResourcePoolEntry with new content but other information
+     * copied from this ResourcePoolEntry.
+     *
+     * @param content The new resource content.
+     * @return A new ResourcePoolEntry.
+     */
+    public default ResourcePoolEntry copyWithContent(byte[] content) {
+        return ResourcePoolEntryFactory.create(this, content);
+    }
+
+    /**
+     * Create a ResourcePoolEntry with new content but other information
+     * copied from this ResourcePoolEntry.
+     *
+     * @param file The new resource content.
+     * @return A new ResourcePoolEntry.
+     */
+    public default ResourcePoolEntry copyWithContent(Path file) {
+        return ResourcePoolEntryFactory.create(this, file);
+    }
+
+    /**
+     * Create a ResourcePoolEntry for a resource of the given type.
+     *
+     * @param path The resource path.
+     * @param type The ResourcePoolEntry type.
+     * @param content The resource content.
+     * @return A new ResourcePoolEntry.
+     */
+    public static ResourcePoolEntry create(String path,
+            ResourcePoolEntry.Type type, byte[] content) {
+        return ResourcePoolEntryFactory.create(path, type, content);
+    }
+
+    /**
+     * Create a ResourcePoolEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
+     *
+     * @param path The resource path.
+     * @param content The resource content.
+     * @return A new ResourcePoolEntry.
+     */
+    public static ResourcePoolEntry create(String path, byte[] content) {
+        return create(path, Type.CLASS_OR_RESOURCE, content);
+    }
+
+    /**
+     * Create a ResourcePoolEntry for a resource of the given type.
+     *
+     * @param path The resource path.
+     * @param type The ResourcePoolEntry type.
+     * @param file The resource file.
+     * @return A new ResourcePoolEntry.
+     */
+    public static ResourcePoolEntry create(String path,
+            ResourcePoolEntry.Type type, Path file) {
+        return ResourcePoolEntryFactory.create(path, type, file);
+    }
+
+    /**
+     * Create a ResourcePoolEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
+     *
+     * @param path The resource path.
+     * @param file The resource file.
+     * @return A new ResourcePoolEntry.
+     */
+    public static ResourcePoolEntry create(String path, Path file) {
+        return create(path, Type.CLASS_OR_RESOURCE, file);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModule.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.lang.module.ModuleDescriptor;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+  * Link-time representation of a module.
+  */
+public interface ResourcePoolModule {
+    /**
+     * The module name.
+     *
+     * @return The module name.
+     */
+    public String name();
+
+    /**
+     * Retrieves a ResourcePoolEntry from the given path (e.g:
+     * /mymodule/com.foo.bar/MyClass.class)
+     *
+     * @param path The piece of data path.
+     * @return A ResourcePoolEntry of the given path, if found.
+     */
+    public Optional<ResourcePoolEntry> findEntry(String path);
+
+    /**
+     * The module descriptor of this module.
+     *
+     * @return The module descriptor.
+     */
+    public ModuleDescriptor descriptor();
+
+    /**
+     * Retrieves all the packages located in this module.
+     *
+     * @return The set of packages.
+     */
+    public Set<String> packages();
+
+    /**
+     * Retrieves the stream of ResourcePoolEntry.
+     *
+     * @return The ResourcePoolEntry stream.
+     */
+    public Stream<ResourcePoolEntry> entries();
+
+    /**
+     * Return the number of ResourcePoolEntry count in this ResourcePoolModule.
+     *
+     * @return the entry count.
+     */
+    public int entryCount();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModuleView.java	Thu Jul 28 09:01:30 2016 -0700
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * The module view of a ResourcePool.
+ */
+public interface ResourcePoolModuleView {
+    /**
+     * Find the module, if any, of the given name.
+     *
+     * @param name name of the module
+     * @return Optional containing the module of the given name.
+     */
+    public Optional<ResourcePoolModule> findModule(String name);
+
+    /**
+     * Find the module, if any, of the given ResourcePoolEntry
+     *
+     * @param entry The ResourcePoolEntry whose module is looked up.
+     * @return Optional containing the module of the given ResourcePoolEntry
+     */
+    public default Optional<ResourcePoolModule> findModule(ResourcePoolEntry entry) {
+        String name = Objects.requireNonNull(entry).moduleName();
+        return name != null? findModule(name) : Optional.empty();
+    }
+
+    /**
+     * The stream of modules contained in this ResourcePool.
+     *
+     * @return The stream of modules.
+     */
+    public Stream<ResourcePoolModule> modules();
+
+    /**
+     * Return the number of ResourcePoolModule count in this ResourcePool.
+     *
+     * @return the module count.
+     */
+    public int moduleCount();
+}
--- a/test/java/nio/file/Files/probeContentType/Basic.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/nio/file/Files/probeContentType/Basic.java	Thu Jul 28 09:01:30 2016 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887 8129632 8129633
+ * @bug 4313887 8129632 8129633 8162624
  * @summary Unit test for probeContentType method
  * @library ../..
  * @build Basic SimpleFileTypeDetector
--- a/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -407,6 +407,127 @@
                 {"+HH:mm:ss", 2, 0, 45, "+02:00:45"},
                 {"+HH:mm:ss", 2, 30, 45, "+02:30:45"},
 
+                {"+H", 2, 0, 0, "+2"},
+                {"+H", -2, 0, 0, "-2"},
+                {"+H", 2, 30, 0, "+2"},
+                {"+H", 2, 0, 45, "+2"},
+                {"+H", 2, 30, 45, "+2"},
+                {"+H", 12, 0, 0, "+12"},
+                {"+H", -12, 0, 0, "-12"},
+                {"+H", 12, 30, 0, "+12"},
+                {"+H", 12, 0, 45, "+12"},
+                {"+H", 12, 30, 45, "+12"},
+
+                {"+Hmm", 2, 0, 0, "+2"},
+                {"+Hmm", -2, 0, 0, "-2"},
+                {"+Hmm", 2, 30, 0, "+230"},
+                {"+Hmm", 2, 0, 45, "+2"},
+                {"+Hmm", 2, 30, 45, "+230"},
+                {"+Hmm", 12, 0, 0, "+12"},
+                {"+Hmm", -12, 0, 0, "-12"},
+                {"+Hmm", 12, 30, 0, "+1230"},
+                {"+Hmm", 12, 0, 45, "+12"},
+                {"+Hmm", 12, 30, 45, "+1230"},
+
+                {"+H:mm", 2, 0, 0, "+2"},
+                {"+H:mm", -2, 0, 0, "-2"},
+                {"+H:mm", 2, 30, 0, "+2:30"},
+                {"+H:mm", 2, 0, 45, "+2"},
+                {"+H:mm", 2, 30, 45, "+2:30"},
+                {"+H:mm", 12, 0, 0, "+12"},
+                {"+H:mm", -12, 0, 0, "-12"},
+                {"+H:mm", 12, 30, 0, "+12:30"},
+                {"+H:mm", 12, 0, 45, "+12"},
+                {"+H:mm", 12, 30, 45, "+12:30"},
+
+                {"+HMM", 2, 0, 0, "+200"},
+                {"+HMM", -2, 0, 0, "-200"},
+                {"+HMM", 2, 30, 0, "+230"},
+                {"+HMM", 2, 0, 45, "+200"},
+                {"+HMM", 2, 30, 45, "+230"},
+                {"+HMM", 12, 0, 0, "+1200"},
+                {"+HMM", -12, 0, 0, "-1200"},
+                {"+HMM", 12, 30, 0, "+1230"},
+                {"+HMM", 12, 0, 45, "+1200"},
+                {"+HMM", 12, 30, 45, "+1230"},
+
+                {"+H:MM", 2, 0, 0, "+2:00"},
+                {"+H:MM", -2, 0, 0, "-2:00"},
+                {"+H:MM", 2, 30, 0, "+2:30"},
+                {"+H:MM", 2, 0, 45, "+2:00"},
+                {"+H:MM", 2, 30, 45, "+2:30"},
+                {"+H:MM", 12, 0, 0, "+12:00"},
+                {"+H:MM", -12, 0, 0, "-12:00"},
+                {"+H:MM", 12, 30, 0, "+12:30"},
+                {"+H:MM", 12, 0, 45, "+12:00"},
+                {"+H:MM", 12, 30, 45, "+12:30"},
+
+                {"+HMMss", 2, 0, 0, "+200"},
+                {"+HMMss", -2, 0, 0, "-200"},
+                {"+HMMss", 2, 30, 0, "+230"},
+                {"+HMMss", 2, 0, 45, "+20045"},
+                {"+HMMss", 2, 30, 45, "+23045"},
+                {"+HMMss", 12, 0, 0, "+1200"},
+                {"+HMMss", -12, 0, 0, "-1200"},
+                {"+HMMss", 12, 30, 0, "+1230"},
+                {"+HMMss", 12, 0, 45, "+120045"},
+                {"+HMMss", 12, 30, 45, "+123045"},
+
+                {"+H:MM:ss", 2, 0, 0, "+2:00"},
+                {"+H:MM:ss", -2, 0, 0, "-2:00"},
+                {"+H:MM:ss", 2, 30, 0, "+2:30"},
+                {"+H:MM:ss", 2, 0, 45, "+2:00:45"},
+                {"+H:MM:ss", 2, 30, 45, "+2:30:45"},
+                {"+H:MM:ss", 12, 0, 0, "+12:00"},
+                {"+H:MM:ss", -12, 0, 0, "-12:00"},
+                {"+H:MM:ss", 12, 30, 0, "+12:30"},
+                {"+H:MM:ss", 12, 0, 45, "+12:00:45"},
+                {"+H:MM:ss", 12, 30, 45, "+12:30:45"},
+
+                {"+HMMSS", 2, 0, 0, "+20000"},
+                {"+HMMSS", -2, 0, 0, "-20000"},
+                {"+HMMSS", 2, 30, 0, "+23000"},
+                {"+HMMSS", 2, 0, 45, "+20045"},
+                {"+HMMSS", 2, 30, 45, "+23045"},
+                {"+HMMSS", 12, 0, 0, "+120000"},
+                {"+HMMSS", -12, 0, 0, "-120000"},
+                {"+HMMSS", 12, 30, 0, "+123000"},
+                {"+HMMSS", 12, 0, 45, "+120045"},
+                {"+HMMSS", 12, 30, 45, "+123045"},
+
+                {"+H:MM:SS", 2, 0, 0, "+2:00:00"},
+                {"+H:MM:SS", -2, 0, 0, "-2:00:00"},
+                {"+H:MM:SS", 2, 30, 0, "+2:30:00"},
+                {"+H:MM:SS", 2, 0, 45, "+2:00:45"},
+                {"+H:MM:SS", 2, 30, 45, "+2:30:45"},
+                {"+H:MM:SS", 12, 0, 0, "+12:00:00"},
+                {"+H:MM:SS", -12, 0, 0, "-12:00:00"},
+                {"+H:MM:SS", 12, 30, 0, "+12:30:00"},
+                {"+H:MM:SS", 12, 0, 45, "+12:00:45"},
+                {"+H:MM:SS", 12, 30, 45, "+12:30:45"},
+
+                {"+Hmmss", 2, 0, 0, "+2"},
+                {"+Hmmss", -2, 0, 0, "-2"},
+                {"+Hmmss", 2, 30, 0, "+230"},
+                {"+Hmmss", 2, 0, 45, "+20045"},
+                {"+Hmmss", 2, 30, 45, "+23045"},
+                {"+Hmmss", 12, 0, 0, "+12"},
+                {"+Hmmss", -12, 0, 0, "-12"},
+                {"+Hmmss", 12, 30, 0, "+1230"},
+                {"+Hmmss", 12, 0, 45, "+120045"},
+                {"+Hmmss", 12, 30, 45, "+123045"},
+
+                {"+H:mm:ss", 2, 0, 0, "+2"},
+                {"+H:mm:ss", -2, 0, 0, "-2"},
+                {"+H:mm:ss", 2, 30, 0, "+2:30"},
+                {"+H:mm:ss", 2, 0, 45, "+2:00:45"},
+                {"+H:mm:ss", 2, 30, 45, "+2:30:45"},
+                {"+H:mm:ss", 12, 0, 0, "+12"},
+                {"+H:mm:ss", -12, 0, 0, "-12"},
+                {"+H:mm:ss", 12, 30, 0, "+12:30"},
+                {"+H:mm:ss", 12, 0, 45, "+12:00:45"},
+                {"+H:mm:ss", 12, 30, 45, "+12:30:45"},
+
 
         };
     }
@@ -437,8 +558,6 @@
             {"HH:MM:ss"},
             {"HHMMSS"},
             {"HH:MM:SS"},
-            {"+H"},
-            {"+HMM"},
             {"+HHM"},
             {"+A"},
         };
@@ -1188,6 +1307,146 @@
             {"+HH:mm:ss", "+01", 3600},
             {"+HH:mm:ss", "+01:01", 3660},
             {"+HH:mm:ss", "+01:01:01", 3661},
+
+            {"+H", "+1", 3600},
+            {"+H", "+101", 3660},
+            {"+H", "+10101", 3661},
+            {"+H", "+1:01", 3660},
+            {"+H", "+1:01:01", 3661},
+            {"+H", "+01", 3600},
+            {"+H", "+0101", 3660},
+            {"+H", "+010101", 3661},
+            {"+H", "+01:01", 3660},
+            {"+H", "+01:01:01", 3661},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+Hmm", "+10101", 3661},
+            {"+Hmm", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+Hmm", "+010101", 3661},
+            {"+H:mm", "+1", 3600},
+            {"+H:mm", "+1:01", 3660},
+            {"+H:mm", "+1:01:01", 3661},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+01:01:01", 3661},
+            {"+HMM", "+1", 3600},
+            {"+HMM", "+101", 3660},
+            {"+HMM", "+10101", 3661},
+            {"+HMM", "+01", 3600},
+            {"+HMM", "+0101", 3660},
+            {"+HMM", "+010101", 3661},
+            {"+H:MM", "+1", 3600},
+            {"+H:MM", "+1:01", 3660},
+            {"+H:MM", "+1:01:01", 3661},
+            {"+H:MM", "+01", 3600},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+01:01:01", 3661},
+            {"+HMMss", "+1", 3600},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+HMMss", "+01", 3600},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+1", 3600},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+H:MM:ss", "+01", 3600},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+HMMSS", "+1", 3600},
+            {"+HMMSS", "+101", 3660},
+            {"+HMMSS", "+10101", 3661},
+            {"+HMMSS", "+01", 3600},
+            {"+HMMSS", "+0101", 3660},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+1", 3600},
+            {"+H:MM:SS", "+1:01", 3660},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+H:MM:SS", "+01", 3600},
+            {"+H:MM:SS", "+01:01", 3660},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+1", 3600},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+        };
+    }
+
+    @DataProvider(name="strictDoubleDigitHourOffsetParseData")
+    Object[][] data_strictDoubleDigitHour_offset_parse() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HHMMss", "+0101", 3660},
+            {"+HHMMss", "+010101", 3661},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+01", 3600},
+            {"+HHmmss", "+0101", 3660},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+        };
+    }
+
+    @DataProvider(name="strictSingleDigitHourOffsetParseData")
+    Object[][] data_strictSingleDigitHour_offset_parse() {
+        return new Object[][] {
+            {"+H", "+01", 3600},
+            {"+H", "+1", 3600},
+            {"+Hmm", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1", 3600},
+            {"+H:mm", "+1:01", 3660},
+            {"+HMM", "+0101", 3660},
+            {"+HMM", "+101", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+HMMSS", "+10101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+010101", 3661},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1", 3600},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
         };
     }
 
@@ -1203,22 +1462,226 @@
                      3600);
     }
 
+    @Test(dataProvider="strictDoubleDigitHourOffsetParseData")
+    public void test_strictDoubleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
+                .parse(offset).get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictDoubleDigitHourOffsetParseData")
+    public void test_strictDoubleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictSingleDigitHourOffsetParseData")
+    public void test_strictSingleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
+                .parse(offset).get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictSingleDigitHourOffsetParseData")
+    public void test_strictSingleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @DataProvider(name="strictOffsetAdjacentParseValidPatternData")
+    Object[][] data_strict_offset_adjacentParse_validPattern() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HHMMss", "+010101", 3661},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+
+            {"+H", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1:01", 3660},
+            {"+HMM", "+0101", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+        };
+    }
+
+    @Test(dataProvider="strictOffsetAdjacentParseValidPatternData")
+    public void test_strict_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+        assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
+        assertEquals(tmp.get(HOUR_OF_DAY), 12);
+    }
+
+    @DataProvider(name="strictOffsetAdjacentParseInvalidPatternData")
+    Object[][] data_strict_offset_adjacentParse_invalidPattern() {
+        return new Object[][] {
+            {"+HHmm", "+01", 3600},
+            {"+HHMMss", "+0101", 3660},
+            {"+HHmmss", "+01", 3600},
+            {"+HHmmss", "+0101", 3660},
+            {"+H", "+1", 3600},
+            {"+Hmm", "+01", 3600},
+            {"+H:mm", "+1", 3600},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+HMM", "+101", 3660},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+HMMSS", "+10101", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+H:mm:ss", "+1", 3600},
+        };
+    }
+
+    @Test(dataProvider="strictOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
+    public void test_strict_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
+       new DateTimeFormatterBuilder().appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2)
+               .toFormatter().parse(offset + "12");
+    }
+
+    @DataProvider(name="lenientOffsetAdjacentParseValidPatternData")
+    Object[][] data_lenient_offset_adjacentParse_validPattern() {
+        return new Object[][] {
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1:01", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+        };
+    }
+
+    @Test(dataProvider="lenientOffsetAdjacentParseValidPatternData")
+    public void test_lenient_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
+                .appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+        assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
+        assertEquals(tmp.get(HOUR_OF_DAY), 12);
+    }
+
+    @Test
+    public void test_lenient_offset_adjacentValidPattern_parse1() {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
+                .appendOffset("+HMMSS", "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse("+10101" + "12");
+        //Equivalent to +101011. In lenient mode, offset will parse upto 6 digit if possible.
+        //It will take 1 digit from HOUR_OF_DAY.
+        assertEquals(tmp.get(OFFSET_SECONDS), 36611);
+        assertEquals(tmp.get(HOUR_OF_DAY), 2);
+    }
+
+  @DataProvider(name="lenientOffsetAdjacentParseInvalidPatternData")
+    Object[][] data_lenient_offset_adjacentParse_invalidPattern() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+H", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+HMM", "+0101", 3660},
+        };
+    }
+
+    @Test(dataProvider="lenientOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
+    public void test_lenient_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
+       new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z")
+               .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+    }
+
+    @DataProvider(name="badValues")
+    Object[][] data_badOffsetValues() {
+        return new Object[][] {
+            {"+HH", "+24"},
+            {"+HHMM", "-1361"},
+            {"+HH:MM:ss", "+13:12:66"},
+            {"+HH:MM:SS", "+24:60:60"},
+            {"+HHMMSS", "369999"},
+            {"+H:MM", "+28:12"},
+        };
+    }
+
+    @Test(dataProvider="badValues", expectedExceptions=DateTimeParseException.class)
+    public void test_badOffset_parse(String pattern, String offset) {
+        new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter().parse(offset);
+    }
+
     @Test(expectedExceptions=DateTimeParseException.class)
     public void test_strict_appendOffsetId() {
-        assertEquals(new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS),
-                     3600);
+        new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01");
     }
 
     @Test(expectedExceptions=DateTimeParseException.class)
     public void test_strict_appendOffset_1() {
-        assertEquals(new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
-                     3600);
+        new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01");
     }
 
     @Test(expectedExceptions=DateTimeParseException.class)
     public void test_strict_appendOffset_2() {
-        assertEquals(new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
-                     3600);
+        new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_3() {
+        new DateTimeFormatterBuilder().appendOffset("+H:MM:ss", "Z").toFormatter().parse("+1");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_4() {
+        new DateTimeFormatterBuilder().appendOffset("+HMMss", "Z").toFormatter().parse("+1");
     }
 
     @Test
--- a/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java	Thu Jul 28 09:01:30 2016 -0700
@@ -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
@@ -93,6 +93,14 @@
     private static final ZoneOffset OFFSET_M000045 = ZoneOffset.ofHoursMinutesSeconds(0, 0, -45);
     private static final LocalDateTime DT_2012_06_30_12_30_40 = LocalDateTime.of(2012, 6, 30, 12, 30, 40);
 
+    private static final ZoneOffset OFFSET_P1100 = ZoneOffset.ofHours(11);
+    private static final ZoneOffset OFFSET_P1123 = ZoneOffset.ofHoursMinutes(11, 23);
+    private static final ZoneOffset OFFSET_P1023 = ZoneOffset.ofHoursMinutes(10, 23);
+    private static final ZoneOffset OFFSET_P112345 = ZoneOffset.ofHoursMinutesSeconds(11, 23, 45);
+    private static final ZoneOffset OFFSET_P100045 = ZoneOffset.ofHoursMinutesSeconds(10, 0, 45);
+    private static final ZoneOffset OFFSET_M1100 = ZoneOffset.ofHours(-11);
+    private static final ZoneOffset OFFSET_M1123 = ZoneOffset.ofHoursMinutes(-11, -23);
+    private static final ZoneOffset OFFSET_M112345 = ZoneOffset.ofHoursMinutesSeconds(-11, -23, -45);
     private DateTimeFormatterBuilder builder;
 
     @BeforeMethod
@@ -223,6 +231,212 @@
                 {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"},
                 {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"},
                 {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"},
+
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+10000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+12300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+02300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-10000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-12300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-02300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11"},
+
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
+
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+1000"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
+
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23"},
+
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
+
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+110000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+112300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+102300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-110000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-112300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
+
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
         };
     }
 
--- a/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Thu Jul 28 09:01:30 2016 -0700
@@ -484,8 +484,6 @@
             {"HH:MM:ss"},
             {"HHMMSS"},
             {"HH:MM:SS"},
-            {"+H"},
-            {"+HMM"},
             {"+HHM"},
             {"+A"},
         };
--- a/test/java/time/test/java/time/format/TestZoneOffsetParser.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/time/test/java/time/format/TestZoneOffsetParser.java	Thu Jul 28 09:01:30 2016 -0700
@@ -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
@@ -296,7 +296,7 @@
     @DataProvider(name="bigOffsets")
     Object[][] provider_bigOffsets() {
         return new Object[][] {
-            {"+HH", "+59", 59 * 3600},
+            {"+HH", "+19", 19 * 3600},
             {"+HH", "-19", -(19 * 3600)},
 
             {"+HHMM", "+1801", 18 * 3600 + 1 * 60},
--- a/test/java/util/TimeZone/TimeZoneTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/java/util/TimeZone/TimeZoneTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
- *      8008577 8077685 8098547 8133321 8138716 8148446 8151876
+ *      8008577 8077685 8098547 8133321 8138716 8148446 8151876 8159684
  * @modules java.base/sun.util.resources
  * @library /java/text/testlib
  * @summary test TimeZone
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/xml/crypto/dsig/GetInstanceTests.java	Thu Jul 28 09:01:30 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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 8159488
+ * @summary Basic tests for the various getInstance() methods of
+ * XMLSignatureFactory, TransformService, and KeyInfoFactory classes
+ * @run main GetInstanceTests
+ */
+import java.security.*;
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+
+
+public class GetInstanceTests {
+
+    public static void main(String[] argv) throws Exception {
+        TestTransformService(CanonicalizationMethod.INCLUSIVE, "DOM");
+        TestTransformService(CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, "DOM");
+        TestTransformService(Transform.BASE64, "DOM");
+        TestTransformService(Transform.XPATH2, "DOM");
+        TestXMLSignatureFactory();
+        TestKeyInfoFactory();
+    }
+
+    private static void TestTransformService(String algo,
+        String mechType) throws Exception {
+        TransformService ts = TransformService.getInstance(algo, mechType);
+        Provider p = ts.getProvider();
+        try {
+            ts = TransformService.getInstance(algo, mechType, p);
+            ts = TransformService.getInstance(algo, mechType, p.getName());
+        } catch (Exception ex) {
+            throw new RuntimeException("Error: Unexpected exception", ex);
+        }
+    }
+
+    private static void TestXMLSignatureFactory() throws Exception {
+        XMLSignatureFactory fac = XMLSignatureFactory.getInstance();
+        Provider p = fac.getProvider();
+        String mechType = fac.getMechanismType();
+        Provider p2;
+        try {
+            fac = XMLSignatureFactory.getInstance(mechType);
+            p2 = fac.getProvider();
+            fac = XMLSignatureFactory.getInstance(mechType, p);
+            fac = XMLSignatureFactory.getInstance(mechType, p.getName());
+        } catch (Exception ex) {
+            throw new RuntimeException("Error: Unexpected exception", ex);
+        }
+        if (p2.getName() != p.getName()) {
+            throw new RuntimeException("Error: Provider equality check failed");
+        }
+        if (p2.getName() != p.getName()) {
+            throw new RuntimeException("Error: Provider equality check failed");
+        }
+    }
+
+    private static void TestKeyInfoFactory() throws Exception {
+        KeyInfoFactory fac = KeyInfoFactory.getInstance();
+        Provider p = fac.getProvider();
+        String mechType = fac.getMechanismType();
+        Provider p2;
+        try {
+            fac = KeyInfoFactory.getInstance(mechType);
+            p2 = fac.getProvider();
+            fac = KeyInfoFactory.getInstance(mechType, p);
+            fac = KeyInfoFactory.getInstance(mechType, p.getName());
+        } catch (Exception ex) {
+            throw new RuntimeException("Error: Unexpected exception", ex);
+        }
+        if (p2.getName() != p.getName()) {
+            throw new RuntimeException("Error: Provider equality check failed");
+        }
+    }
+}
--- a/test/sun/util/calendar/zi/tzdata/VERSION	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/VERSION	Thu Jul 28 09:01:30 2016 -0700
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2016d
+tzdata2016f
--- a/test/sun/util/calendar/zi/tzdata/africa	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/africa	Thu Jul 28 09:01:30 2016 -0700
@@ -366,6 +366,12 @@
 # decision to abandon DST permanently.  See Ahram Online 2015-04-24.
 # http://english.ahram.org.eg/NewsContent/1/64/128509/Egypt/Politics-/Sisi-cancels-daylight-saving-time-in-Egypt.aspx
 
+# From Steffen Thorsen (2016-04-29):
+# Egypt will have DST from July 7 until the end of October....
+# http://english.ahram.org.eg/NewsContentP/1/204655/Egypt/Daylight-savings-time-returning-to-Egypt-on--July.aspx
+# From Mina Samuel (2016-07-04):
+# Egyptian government took the decision to cancel the DST,
+
 Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
 Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
 Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
@@ -881,11 +887,11 @@
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0:00	0	-
 Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
 Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
 Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
 Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
 Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
 Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
--- a/test/sun/util/calendar/zi/tzdata/antarctica	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/antarctica	Thu Jul 28 09:01:30 2016 -0700
@@ -36,7 +36,7 @@
 #
 # Except for the French entries,
 # I made up all time zone abbreviations mentioned here; corrections welcome!
-# FORMAT is 'zzz' and GMTOFF is 0 for locations while uninhabited.
+# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -90,22 +90,22 @@
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Casey	0	-	zzz	1969
+Zone Antarctica/Casey	0	-	-00	1969
 			8:00	-	AWST	2009 Oct 18  2:00
 						# Australian Western Std Time
 			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
 			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
 			8:00	-	AWST
-Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
+Zone Antarctica/Davis	0	-	-00	1957 Jan 13
 			7:00	-	DAVT	1964 Nov    # Davis Time
-			0	-	zzz	1969 Feb
+			0	-	-00	1969 Feb
 			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
 			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
-Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
+Zone Antarctica/Mawson	0	-	-00	1954 Feb 13
 			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
@@ -160,7 +160,7 @@
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
+Zone Indian/Kerguelen	0	-	-00	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
@@ -171,9 +171,9 @@
 # It was destroyed by fire on 1952-01-14.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/DumontDUrville 0 -	zzz	1947
+Zone Antarctica/DumontDUrville 0 -	-00	1947
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
-			0	-	zzz	1956 Nov
+			0	-	-00	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
 
 # France & Italy - year-round base
@@ -199,7 +199,7 @@
 # was established on 1957-01-29.  Since Syowa station is still the main
 # station of Japan, it's appropriate for the principal location.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
+Zone Antarctica/Syowa	0	-	-00	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
 # NIPR Antarctic Research Activities (1999-08-17)
@@ -249,7 +249,7 @@
 # Remove the following line when uncommenting the above '#Rule' lines.
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
+Zone Antarctica/Troll	0	-	-00	2005 Feb 12
 			0:00	Troll	%s
 
 # Poland - year-round base
@@ -290,7 +290,7 @@
 # happened to be during their visit.  So we still don't really know what time
 # it is at Vostok.  But we'll guess UTC+6.
 #
-Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
+Zone Antarctica/Vostok	0	-	-00	1957 Dec 16
 			6:00	-	VOST	# Vostok time
 
 # S Africa - year-round bases
@@ -323,7 +323,7 @@
 # <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Rothera	0	-	zzz	1976 Dec  1
+Zone Antarctica/Rothera	0	-	-00	1976 Dec  1
 			-3:00	-	ROTT	# Rothera time
 
 # Uruguay - year round base
--- a/test/sun/util/calendar/zi/tzdata/asia	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/asia	Thu Jul 28 09:01:30 2016 -0700
@@ -169,7 +169,7 @@
 			3:00	-	BAKT	1957 Mar    # Baku Time
 			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
-			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
+			3:00 RussiaAsia	AZ%sT	1992 Sep lastSun  2:00s
 			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
--- a/test/sun/util/calendar/zi/tzdata/australasia	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/australasia	Thu Jul 28 09:01:30 2016 -0700
@@ -266,11 +266,11 @@
 # will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
-Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
+Zone Antarctica/Macquarie 0	-	-00	1899 Nov
 			10:00	-	AEST	1916 Oct  1  2:00
 			10:00	1:00	AEDT	1917 Feb
 			10:00	Aus	AE%sT	1919 Apr  1  0:00s
-			0	-	zzz	1948 Mar 25
+			0	-	-00	1948 Mar 25
 			10:00	Aus	AE%sT	1967
 			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
--- a/test/sun/util/calendar/zi/tzdata/europe	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/europe	Thu Jul 28 09:01:30 2016 -0700
@@ -778,6 +778,14 @@
 			1:00	EU	CE%sT
 
 # Belarus
+#
+# From Stepan Golosunov (2016-07-02):
+# http://www.lawbelarus.com/repub/sub30/texf9611.htm
+# (Act of the Cabinet of Ministers of the Republic of Belarus from
+# 1992-03-25 No. 157) ... says clocks were to be moved forward at 2:00
+# on last Sunday of March and backward at 3:00 on last Sunday of September
+# (the same as previous USSR and contemporary Russian regulations).
+#
 # From Yauhen Kharuzhy (2011-09-16):
 # By latest Belarus government act Europe/Minsk timezone was changed to
 # GMT+3 without DST (was GMT+2 with DST).
@@ -801,9 +809,6 @@
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
 			3:00	-	MSK	1991 Mar 31  2:00s
-			2:00	1:00	EEST	1991 Sep 29  2:00s
-			2:00	-	EET	1992 Mar 29  0:00s
-			2:00	1:00	EEST	1992 Sep 27  0:00s
 			2:00	Russia	EE%sT	2011 Mar 27  2:00s
 			3:00	-	FET	2014 Oct 26  1:00s
 			3:00	-	MSK
@@ -2746,14 +2751,22 @@
 # Asia/Novosibirsk covers:
 # 54	RU-NVS	Novosibirsk Oblast
 
+# From Stepan Golosunov (2016-05-30):
+# http://asozd2.duma.gov.ru/main.nsf/(Spravka)?OpenAgent&RN=1085784-6
+# moves Novosibirsk oblast from UTC+6 to UTC+7.
+# From Stepan Golosunov (2016-07-04):
+# The law was signed yesterday and published today on
+# http://publication.pravo.gov.ru/Document/View/0001201607040064
+
 Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
-			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
-			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
-			 7:00	-	NOVT	2014 Oct 26  2:00s
-			 6:00	-	NOVT
+			 6:00	-	+06	1930 Jun 21
+			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
+			 6:00	Russia	+06/+07	1992 Jan 19  2:00s
+			 7:00	Russia	+07/+08	1993 May 23 # say Shanks & P.
+			 6:00	Russia	+06/+07	2011 Mar 27  2:00s
+			 7:00	-	+07	2014 Oct 26  2:00s
+			 6:00	-	+06	2016 Jul 24  2:00s
+			 7:00	-	+07
 
 # From Paul Eggert (2016-03-18):
 # Asia/Tomsk covers:
@@ -2794,6 +2807,9 @@
 # approved by the Federation Council on 2016-04-20, signed by the President and
 # published as a law around 2016-04-26.
 
+# From Matt Johnson (2016-04-26):
+# http://publication.pravo.gov.ru/Document/View/0001201604260048
+
 Zone	Asia/Tomsk	 5:39:51 -	LMT	1919 Dec 22
 			 6:00	-	+06	1930 Jun 21
 			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
@@ -2833,14 +2849,12 @@
 # realigning itself with KRAT.
 
 Zone Asia/Novokuznetsk	 5:48:48 -	LMT	1924 May  1
-			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
-			 7:00	-	NOVT	2014 Oct 26  2:00s
-			 7:00	-	KRAT	# Krasnoyarsk Time
-
+			 6:00	-	+06	1930 Jun 21
+			 7:00	Russia	+07/+08	1991 Mar 31  2:00s
+			 6:00	Russia	+06/+07	1992 Jan 19  2:00s
+			 7:00	Russia	+07/+08	2010 Mar 28  2:00s
+			 6:00	Russia	+06/+07	2011 Mar 27  2:00s
+			 7:00	-	+07
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
 # Asia/Krasnoyarsk covers...
--- a/test/sun/util/calendar/zi/tzdata/northamerica	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/northamerica	Thu Jul 28 09:01:30 2016 -0700
@@ -2214,39 +2214,39 @@
 Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
-Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
+Zone America/Pangnirtung 0	-	-00	1921 # trading post est.
 			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
 			-5:00	Canada	E%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
-Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
+Zone America/Iqaluit	0	-	-00	1942 Aug # Frobisher Bay est.
 			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
-Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
+Zone America/Resolute	0	-	-00	1947 Aug 31 # Resolute founded
 			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT	2006 Oct 29  2:00
 			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
-Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
+Zone America/Rankin_Inlet 0	-	-00	1957 # Rankin Inlet founded
 			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
-Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
+Zone America/Cambridge_Bay 0	-	-00	1920 # trading post est.?
 			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
 			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	-	EST	2000 Nov  5  0:00
 			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
-Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
+Zone America/Yellowknife 0	-	-00	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
-Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
+Zone America/Inuvik	0	-	-00	1953 # Inuvik founded
 			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
--- a/test/sun/util/calendar/zi/tzdata/southamerica	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/sun/util/calendar/zi/tzdata/southamerica	Thu Jul 28 09:01:30 2016 -0700
@@ -1332,7 +1332,7 @@
 # Palmer used to be supplied from Argentina.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Antarctica/Palmer	0	-	zzz	1965
+Zone Antarctica/Palmer	0	-	-00	1965
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1982 May
 			-4:00	Chile	CL%sT
@@ -1782,16 +1782,16 @@
 # https://actualidad.rt.com/actualidad/204758-venezuela-modificar-huso-horario-sequia-elnino
 #
 # From Paul Eggert (2016-04-15):
-# Clocks advance 30 minutes on 2016-05-01 at 02:30. See:
-# Barboza AD. Huso horario en Venezuela volverá a 4 horas menos con
-# respecto al "Greenwich". Panorama 2016-04-15 12:20 -0430.
-# http://www.panorama.com.ve/ciudad/Huso-horario-en-Venezuela-volvera-a-4-horas-menos-con-respecto-al-Greenwich-20160415-0032.html
-#
+# Clocks advance 30 minutes on 2016-05-01 at 02:30....
 # "'Venezuela's new time-zone: hours without light, hours without water,
-# hours of presidential broadcasts, hours of lines," quipped comedian
-# Jean Mary Curro ...". See: Cawthorne A, Kai D. Venezuela scraps
+# hours of presidential broadcasts, hours of lines,' quipped comedian
+# Jean Mary Curró ...". See: Cawthorne A, Kai D. Venezuela scraps
 # half-hour time difference set by Chavez. Reuters 2016-04-15 14:50 -0400
 # http://www.reuters.com/article/us-venezuela-timezone-idUSKCN0XC2BE
+#
+# From Matt Johnson (2016-04-20):
+# ... published in the official Gazette [2016-04-18], here:
+# http://historico.tsj.gob.ve/gaceta_ext/abril/1842016/E-1842016-4551.pdf
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
--- a/test/tools/jlink/DefaultProviderTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/DefaultProviderTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -32,7 +32,8 @@
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import tests.Helper;
 
 /*
@@ -69,7 +70,7 @@
         }
 
         @Override
-        public void visit(ModulePool in, ModulePool out) {
+        public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
             if (!enabled) {
                 throw new PluginException(NAME + " was set");
             }
@@ -78,6 +79,8 @@
             in.transformAndCopy(content -> {
                 return content;
             }, out);
+
+            return out.build();
         }
 
         @Override
--- a/test/tools/jlink/ImageFileCreatorTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/ImageFileCreatorTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -39,7 +39,7 @@
 import jdk.tools.jlink.internal.ImagePluginStack;
 import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.builder.ImageBuilder;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 
 /*
@@ -215,7 +215,7 @@
             }
 
             @Override
-            public void storeFiles(ModulePool content) {
+            public void storeFiles(ResourcePool content) {
             }
         };
 
--- a/test/tools/jlink/ImageFilePoolTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/ImageFilePoolTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -33,10 +33,10 @@
 import java.io.ByteArrayInputStream;
 import java.util.Optional;
 import java.util.function.Function;
-import jdk.tools.jlink.internal.ModuleEntryFactory;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.internal.ResourcePoolEntryFactory;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 public class ImageFilePoolTest {
     public static void main(String[] args) throws Exception {
@@ -51,55 +51,55 @@
     private static final String SUFFIX = "END";
 
     private void checkVisitor() throws Exception {
-        ModulePool input = new ModulePoolImpl();
+        ResourcePoolManager input = new ResourcePoolManager();
         for (int i = 0; i < 1000; ++i) {
             String module = "module" + (i / 100);
             input.add(newInMemoryImageFile("/" + module + "/java/class" + i,
-                    ModuleEntry.Type.CONFIG, "class" + i));
+                    ResourcePoolEntry.Type.CONFIG, "class" + i));
         }
-        if (input.getEntryCount() != 1000) {
+        if (input.entryCount() != 1000) {
             throw new AssertionError();
         }
-        ModulePool output = new ModulePoolImpl();
+        ResourcePoolManager output = new ResourcePoolManager();
         ResourceVisitor visitor = new ResourceVisitor();
-        input.transformAndCopy(visitor, output);
+        input.resourcePool().transformAndCopy(visitor, output.resourcePoolBuilder());
         if (visitor.getAmountBefore() == 0) {
             throw new AssertionError("Resources not found");
         }
-        if (visitor.getAmountBefore() != input.getEntryCount()) {
+        if (visitor.getAmountBefore() != input.entryCount()) {
             throw new AssertionError("Number of visited resources. Expected: " +
-                    visitor.getAmountBefore() + ", got: " + input.getEntryCount());
+                    visitor.getAmountBefore() + ", got: " + input.entryCount());
         }
-        if (visitor.getAmountAfter() != output.getEntryCount()) {
+        if (visitor.getAmountAfter() != output.entryCount()) {
             throw new AssertionError("Number of added resources. Expected: " +
-                    visitor.getAmountAfter() + ", got: " + output.getEntryCount());
+                    visitor.getAmountAfter() + ", got: " + output.entryCount());
         }
         output.entries().forEach(outFile -> {
-            String path = outFile.getPath().replaceAll(SUFFIX + "$", "");
-            Optional<ModuleEntry> inFile = input.findEntry(path);
+            String path = outFile.path().replaceAll(SUFFIX + "$", "");
+            Optional<ResourcePoolEntry> inFile = input.findEntry(path);
             if (!inFile.isPresent()) {
                 throw new AssertionError("Unknown resource: " + path);
             }
         });
     }
 
-    private static class ResourceVisitor implements Function<ModuleEntry, ModuleEntry> {
+    private static class ResourceVisitor implements Function<ResourcePoolEntry, ResourcePoolEntry> {
 
         private int amountBefore;
         private int amountAfter;
 
         @Override
-        public ModuleEntry apply(ModuleEntry file) {
+        public ResourcePoolEntry apply(ResourcePoolEntry file) {
             int index = ++amountBefore % 3;
             switch (index) {
                 case 0:
                     ++amountAfter;
-                    return newInMemoryImageFile(file.getPath() + SUFFIX,
-                            file.getType(), file.getPath());
+                    return newInMemoryImageFile(file.path() + SUFFIX,
+                            file.type(), file.path());
                 case 1:
                     ++amountAfter;
-                    return newInMemoryImageFile(file.getPath(),
-                            file.getType(), file.getPath());
+                    return newInMemoryImageFile(file.path(),
+                            file.type(), file.path());
             }
             return null;
         }
@@ -114,7 +114,7 @@
     }
 
     private void checkNegative() throws Exception {
-        ModulePoolImpl input = new ModulePoolImpl();
+        ResourcePoolManager input = new ResourcePoolManager();
         try {
             input.add(null);
             throw new AssertionError("NullPointerException is not thrown");
@@ -128,29 +128,22 @@
             // expected
         }
         if (input.findEntry("unknown").isPresent()) {
-            throw new AssertionError("ImageFileModulePool does not return null for unknown file");
+            throw new AssertionError("ImageFileResourcePool does not return null for unknown file");
         }
-        if (input.contains(newInMemoryImageFile("/unknown/foo", ModuleEntry.Type.CONFIG, "unknown"))) {
+        if (input.contains(newInMemoryImageFile("/unknown/foo", ResourcePoolEntry.Type.CONFIG, "unknown"))) {
             throw new AssertionError("'contain' returns true for /unknown/foo file");
         }
-        input.add(newInMemoryImageFile("/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
+        input.add(newInMemoryImageFile("/aaa/bbb", ResourcePoolEntry.Type.CONFIG, ""));
         try {
-            input.add(newInMemoryImageFile("/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
-            throw new AssertionError("Exception expected");
-        } catch (Exception e) {
-            // expected
-        }
-        input.setReadOnly();
-        try {
-            input.add(newInMemoryImageFile("/aaa/ccc", ModuleEntry.Type.CONFIG, ""));
+            input.add(newInMemoryImageFile("/aaa/bbb", ResourcePoolEntry.Type.CONFIG, ""));
             throw new AssertionError("Exception expected");
         } catch (Exception e) {
             // expected
         }
     }
 
-    private static ModuleEntry newInMemoryImageFile(String path,
-            ModuleEntry.Type type, String content) {
-        return ModuleEntryFactory.create(path, type, content.getBytes());
+    private static ResourcePoolEntry newInMemoryImageFile(String path,
+            ResourcePoolEntry.Type type, String content) {
+        return ResourcePoolEntryFactory.create(path, type, content.getBytes());
     }
 }
--- a/test/tools/jlink/IntegrationTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/IntegrationTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -39,7 +39,8 @@
 import jdk.tools.jlink.Jlink.JlinkConfiguration;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.internal.ExecutableImage;
 import jdk.tools.jlink.internal.PostProcessor;
@@ -100,8 +101,9 @@
         }
 
         @Override
-        public void visit(ModulePool in, ModulePool out) {
+        public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
             in.transformAndCopy(Function.identity(), out);
+            return out.build();
         }
     }
 
--- a/test/tools/jlink/JLinkOptionsTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/JLinkOptionsTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -24,7 +24,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.plugin.Plugin;
 
@@ -62,8 +63,8 @@
         }
 
         @Override
-        public void visit(ModulePool in, ModulePool out) {
-
+        public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
+            return out.build();
         }
 
         @Override
--- a/test/tools/jlink/JLinkPostProcessingTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/JLinkPostProcessingTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -31,7 +31,8 @@
 import java.util.function.Function;
 
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.PostProcessor;
 import jdk.tools.jlink.internal.ExecutableImage;
@@ -71,8 +72,9 @@
         }
 
         @Override
-        public void visit(ModulePool in, ModulePool out) {
+        public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
             in.transformAndCopy(Function.identity(), out);
+            return out.build();
         }
 
         @Override
--- a/test/tools/jlink/ResourcePoolTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/ResourcePoolTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -40,11 +40,11 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.LinkModule;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class ResourcePoolTest {
 
@@ -61,51 +61,51 @@
     private static final String SUFFIX = "END";
 
     private void checkResourceVisitor() throws Exception {
-        ModulePool input = new ModulePoolImpl();
+        ResourcePoolManager input = new ResourcePoolManager();
         for (int i = 0; i < 1000; ++i) {
             String module = "/module" + (i / 10);
             String resourcePath = module + "/java/package" + i;
             byte[] bytes = resourcePath.getBytes();
-            input.add(ModuleEntry.create(resourcePath, bytes));
+            input.add(ResourcePoolEntry.create(resourcePath, bytes));
         }
-        ModulePool output = new ModulePoolImpl();
+        ResourcePoolManager output = new ResourcePoolManager();
         ResourceVisitor visitor = new ResourceVisitor();
-        input.transformAndCopy(visitor, output);
+        input.resourcePool().transformAndCopy(visitor, output.resourcePoolBuilder());
         if (visitor.getAmountBefore() == 0) {
             throw new AssertionError("Resources not found");
         }
-        if (visitor.getAmountBefore() != input.getEntryCount()) {
+        if (visitor.getAmountBefore() != input.entryCount()) {
             throw new AssertionError("Number of visited resources. Expected: " +
-                    visitor.getAmountBefore() + ", got: " + input.getEntryCount());
+                    visitor.getAmountBefore() + ", got: " + input.entryCount());
         }
-        if (visitor.getAmountAfter() != output.getEntryCount()) {
+        if (visitor.getAmountAfter() != output.entryCount()) {
             throw new AssertionError("Number of added resources. Expected: " +
-                    visitor.getAmountAfter() + ", got: " + output.getEntryCount());
+                    visitor.getAmountAfter() + ", got: " + output.entryCount());
         }
         output.entries().forEach(outResource -> {
-            String path = outResource.getPath().replaceAll(SUFFIX + "$", "");
+            String path = outResource.path().replaceAll(SUFFIX + "$", "");
             if (!input.findEntry(path).isPresent()) {
                 throw new AssertionError("Unknown resource: " + path);
             }
         });
     }
 
-    private static class ResourceVisitor implements Function<ModuleEntry, ModuleEntry> {
+    private static class ResourceVisitor implements Function<ResourcePoolEntry, ResourcePoolEntry> {
 
         private int amountBefore;
         private int amountAfter;
 
         @Override
-        public ModuleEntry apply(ModuleEntry resource) {
+        public ResourcePoolEntry apply(ResourcePoolEntry resource) {
             int index = ++amountBefore % 3;
             switch (index) {
                 case 0:
                     ++amountAfter;
-                    return ModuleEntry.create(resource.getPath() + SUFFIX,
-                            resource.getType(), resource.getBytes());
+                    return ResourcePoolEntry.create(resource.path() + SUFFIX,
+                            resource.type(), resource.contentBytes());
                 case 1:
                     ++amountAfter;
-                    return resource.create(resource.getBytes());
+                    return resource.copyWithContent(resource.contentBytes());
             }
             return null;
         }
@@ -129,17 +129,17 @@
         samples.add("javax/management/ObjectName");
         test(samples, (resources, module, path) -> {
             try {
-                resources.add(ModuleEntry.create(path, new byte[0]));
+                resources.add(ResourcePoolEntry.create(path, new byte[0]));
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
         });
         test(samples, (resources, module, path) -> {
             try {
-                resources.add(ModulePoolImpl.
-                        newCompressedResource(ModuleEntry.create(path, new byte[0]),
+                resources.add(ResourcePoolManager.
+                        newCompressedResource(ResourcePoolEntry.create(path, new byte[0]),
                                 ByteBuffer.allocate(99), "bitcruncher", null,
-                                ((ModulePoolImpl)resources).getStringTable(), ByteOrder.nativeOrder()));
+                                ((ResourcePoolManager)resources).getStringTable(), ByteOrder.nativeOrder()));
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -150,7 +150,7 @@
         if (samples.isEmpty()) {
             throw new AssertionError("No sample to test");
         }
-        ModulePool resources = new ModulePoolImpl();
+        ResourcePoolManager resources = new ResourcePoolManager();
         Set<String> modules = new HashSet<>();
         for (int i = 0; i < samples.size(); i++) {
             String module = samples.get(i);
@@ -165,68 +165,68 @@
             i++;
             String clazz = samples.get(i);
             String path = "/" + module + "/" + clazz + ".class";
-            Optional<ModuleEntry> res = resources.findEntry(path);
+            Optional<ResourcePoolEntry> res = resources.findEntry(path);
             if (!res.isPresent()) {
                 throw new AssertionError("Resource not found " + path);
             }
-            checkModule(resources, res.get());
+            checkModule(resources.resourcePool(), res.get());
             if (resources.findEntry(clazz).isPresent()) {
                 throw new AssertionError("Resource found " + clazz);
             }
         }
-        if (resources.getEntryCount() != samples.size() / 2) {
+        if (resources.entryCount() != samples.size() / 2) {
             throw new AssertionError("Invalid number of resources");
         }
     }
 
-    private void checkModule(ModulePool resources, ModuleEntry res) {
-        Optional<LinkModule> optMod = resources.findModule(res.getModule());
+    private void checkModule(ResourcePool resources, ResourcePoolEntry res) {
+        Optional<ResourcePoolModule> optMod = resources.moduleView().findModule(res.moduleName());
         if (!optMod.isPresent()) {
-            throw new AssertionError("No module " + res.getModule());
+            throw new AssertionError("No module " + res.moduleName());
         }
-        LinkModule m = optMod.get();
-        if (!m.getName().equals(res.getModule())) {
-            throw new AssertionError("Not right module name " + res.getModule());
+        ResourcePoolModule m = optMod.get();
+        if (!m.name().equals(res.moduleName())) {
+            throw new AssertionError("Not right module name " + res.moduleName());
         }
-        if (!m.findEntry(res.getPath()).isPresent()) {
-            throw new AssertionError("resource " + res.getPath()
-                    + " not in module " + m.getName());
+        if (!m.findEntry(res.path()).isPresent()) {
+            throw new AssertionError("resource " + res.path()
+                    + " not in module " + m.name());
         }
     }
 
     private void checkResourcesAfterCompression() throws Exception {
-        ModulePoolImpl resources1 = new ModulePoolImpl();
-        ModuleEntry res1 = ModuleEntry.create("/module1/toto1", new byte[0]);
-        ModuleEntry res2 = ModuleEntry.create("/module2/toto1", new byte[0]);
+        ResourcePoolManager resources1 = new ResourcePoolManager();
+        ResourcePoolEntry res1 = ResourcePoolEntry.create("/module1/toto1", new byte[0]);
+        ResourcePoolEntry res2 = ResourcePoolEntry.create("/module2/toto1", new byte[0]);
         resources1.add(res1);
         resources1.add(res2);
 
         checkResources(resources1, res1, res2);
-        ModulePool resources2 = new ModulePoolImpl();
-        ModuleEntry res3 = ModuleEntry.create("/module2/toto1", new byte[7]);
+        ResourcePoolManager resources2 = new ResourcePoolManager();
+        ResourcePoolEntry res3 = ResourcePoolEntry.create("/module2/toto1", new byte[7]);
         resources2.add(res3);
-        resources2.add(ModulePoolImpl.newCompressedResource(res1,
+        resources2.add(ResourcePoolManager.newCompressedResource(res1,
                 ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(),
                 ByteOrder.nativeOrder()));
         checkResources(resources2, res1, res2);
     }
 
-    private void checkResources(ModulePool resources, ModuleEntry... expected) {
+    private void checkResources(ResourcePoolManager resources, ResourcePoolEntry... expected) {
         List<String> modules = new ArrayList();
         resources.modules().forEach(m -> {
-            modules.add(m.getName());
+            modules.add(m.name());
         });
-        for (ModuleEntry res : expected) {
+        for (ResourcePoolEntry res : expected) {
             if (!resources.contains(res)) {
                 throw new AssertionError("Resource not found: " + res);
             }
 
-            if (!resources.findEntry(res.getPath()).isPresent()) {
+            if (!resources.findEntry(res.path()).isPresent()) {
                 throw new AssertionError("Resource not found: " + res);
             }
 
-            if (!modules.contains(res.getModule())) {
-                throw new AssertionError("Module not found: " + res.getModule());
+            if (!modules.contains(res.moduleName())) {
+                throw new AssertionError("Module not found: " + res.moduleName());
             }
 
             if (!resources.contains(res)) {
@@ -241,20 +241,15 @@
             }
         }
 
-        if (resources.isReadOnly()) {
-            throw new AssertionError("ReadOnly resources");
-        }
-
-        ((ModulePoolImpl) resources).setReadOnly();
         try {
-            resources.add(ModuleEntry.create("/module2/toto1", new byte[0]));
-            throw new AssertionError("ModulePool is read-only, but an exception is not thrown");
+            resources.add(ResourcePoolEntry.create("/module2/toto1", new byte[0]));
+            throw new AssertionError("ResourcePool is read-only, but an exception is not thrown");
         } catch (Exception ex) {
             // Expected
         }
     }
 
     interface ResourceAdder {
-        void add(ModulePool resources, String module, String path);
+        void add(ResourcePoolManager resources, String module, String path);
     }
 }
--- a/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -25,8 +25,9 @@
 import java.util.Collections;
 import java.util.Map;
 import java.util.function.Function;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 
 public class CustomPlugin implements Plugin {
@@ -37,8 +38,9 @@
     }
 
     @Override
-    public void visit(ModulePool in, ModulePool out) {
+    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         in.transformAndCopy(Function.identity(), out);
+        return out.build();
     }
 
     @Override
--- a/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Thu Jul 28 09:01:30 2016 -0700
@@ -27,8 +27,9 @@
 import java.io.UncheckedIOException;
 import java.util.Collections;
 import java.util.Map;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.Plugin;
 
 /**
@@ -47,7 +48,7 @@
     }
 
     @Override
-    public void visit(ModulePool inResources, ModulePool outResources) {
+    public ResourcePool transform(ResourcePool inResources, ResourcePoolBuilder outResources) {
         try {
             System.out.println("Hello!!!!!!!!!!");
             File f = new File(OUTPUT_FILE);
@@ -58,6 +59,7 @@
         } catch (IOException ex) {
             throw new UncheckedIOException(ex);
         }
+        return outResources.build();
     }
 
     @Override
--- a/test/tools/jlink/plugins/CompressorPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/CompressorPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -53,14 +53,15 @@
 import jdk.internal.jimage.decompressor.ResourceDecompressorFactory;
 import jdk.internal.jimage.decompressor.StringSharingDecompressorFactory;
 import jdk.internal.jimage.decompressor.ZipDecompressorFactory;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
 import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
 import jdk.tools.jlink.internal.plugins.ZipPlugin;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class CompressorPluginTest {
 
@@ -85,7 +86,7 @@
                     new ZipDecompressorFactory()
                 });
 
-        ModulePool classes = gatherClasses(javabase);
+        ResourcePool classes = gatherClasses(javabase);
         // compress = String sharing
         checkCompress(classes, new StringSharingPlugin(), null,
                 new ResourceDecompressorFactory[]{
@@ -168,8 +169,8 @@
                 }, Collections.singletonList(".*Exception.class"));
     }
 
-    private ModulePool gatherResources(Path module) throws Exception {
-        ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+    private ResourcePool gatherResources(Path module) throws Exception {
+        ResourcePoolManager poolMgr = new ResourcePoolManager(ByteOrder.nativeOrder(), new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -181,20 +182,22 @@
                 return null;
             }
         });
+
+        ResourcePoolBuilder poolBuilder = poolMgr.resourcePoolBuilder();
         try (Stream<Path> stream = Files.walk(module)) {
             for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
                 Path p = iterator.next();
                 if (Files.isRegularFile(p)) {
                     byte[] content = Files.readAllBytes(p);
-                    pool.add(ModuleEntry.create(p.toString(), content));
+                    poolBuilder.add(ResourcePoolEntry.create(p.toString(), content));
                 }
             }
         }
-        return pool;
+        return poolBuilder.build();
     }
 
-    private ModulePool gatherClasses(Path module) throws Exception {
-        ModulePool pool = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+    private ResourcePool gatherClasses(Path module) throws Exception {
+        ResourcePoolManager poolMgr = new ResourcePoolManager(ByteOrder.nativeOrder(), new StringTable() {
 
             @Override
             public int addString(String str) {
@@ -206,25 +209,27 @@
                 return null;
             }
         });
+
+        ResourcePoolBuilder poolBuilder = poolMgr.resourcePoolBuilder();
         try (Stream<Path> stream = Files.walk(module)) {
             for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
                 Path p = iterator.next();
                 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
                     byte[] content = Files.readAllBytes(p);
-                    pool.add(ModuleEntry.create(p.toString(), content));
+                    poolBuilder.add(ResourcePoolEntry.create(p.toString(), content));
                 }
             }
         }
-        return pool;
+        return poolBuilder.build();
     }
 
-    private void checkCompress(ModulePool resources, Plugin prov,
+    private void checkCompress(ResourcePool resources, Plugin prov,
             Properties config,
             ResourceDecompressorFactory[] factories) throws Exception {
         checkCompress(resources, prov, config, factories, Collections.emptyList());
     }
 
-    private void checkCompress(ModulePool resources, Plugin prov,
+    private void checkCompress(ResourcePool resources, Plugin prov,
             Properties config,
             ResourceDecompressorFactory[] factories,
             List<String> includes) throws Exception {
@@ -243,7 +248,7 @@
             }
             prov.configure(props);
             final Map<Integer, String> strings = new HashMap<>();
-            ModulePoolImpl inputResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+            ResourcePoolManager inputResourcesMgr = new ResourcePoolManager(ByteOrder.nativeOrder(), new StringTable() {
                 @Override
                 public int addString(String str) {
                     int id = strID;
@@ -257,11 +262,11 @@
                     return strings.get(id);
                 }
             });
-            inputResources.add(resource);
-            ModulePool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns);
-            original[0] += resource.getLength();
-            compressed[0] += compressedResources.findEntry(resource.getPath()).get().getLength();
-            applyDecompressors(factories, inputResources, compressedResources, strings, includesPatterns);
+            inputResourcesMgr.add(resource);
+            ResourcePool compressedResources = applyCompressor(prov, inputResourcesMgr, resource, includesPatterns);
+            original[0] += resource.contentLength();
+            compressed[0] += compressedResources.findEntry(resource.path()).get().contentLength();
+            applyDecompressors(factories, inputResourcesMgr.resourcePool(), compressedResources, strings, includesPatterns);
         });
         String compressors = Stream.of(factories)
                 .map(Object::getClass)
@@ -274,16 +279,18 @@
         }
     }
 
-    private ModulePool applyCompressor(Plugin plugin,
-            ModulePoolImpl inputResources,
-            ModuleEntry res,
+    private ResourcePool applyCompressor(Plugin plugin,
+            ResourcePoolManager inputResources,
+            ResourcePoolEntry res,
             List<Pattern> includesPatterns) {
-        ModulePool compressedModulePool = new ModulePoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable());
-        plugin.visit(inputResources, compressedModulePool);
-        String path = res.getPath();
-        ModuleEntry compressed = compressedModulePool.findEntry(path).get();
+        ResourcePoolManager resMgr = new ResourcePoolManager(ByteOrder.nativeOrder(),
+                inputResources.getStringTable());
+        ResourcePool compressedResourcePool = plugin.transform(inputResources.resourcePool(),
+            resMgr.resourcePoolBuilder());
+        String path = res.path();
+        ResourcePoolEntry compressed = compressedResourcePool.findEntry(path).get();
         CompressedResourceHeader header
-                = CompressedResourceHeader.readFromResource(ByteOrder.nativeOrder(), compressed.getBytes());
+                = CompressedResourceHeader.readFromResource(ByteOrder.nativeOrder(), compressed.contentBytes());
         if (isIncluded(includesPatterns, path)) {
             if (header == null) {
                 throw new AssertionError("Path should be compressed: " + path);
@@ -299,23 +306,23 @@
         } else if (header != null) {
             throw new AssertionError("Path should not be compressed: " + path);
         }
-        return compressedModulePool;
+        return compressedResourcePool;
     }
 
     private void applyDecompressors(ResourceDecompressorFactory[] decompressors,
-            ModulePool inputResources,
-            ModulePool compressedResources,
+            ResourcePool inputResources,
+            ResourcePool compressedResources,
             Map<Integer, String> strings,
             List<Pattern> includesPatterns) {
         compressedResources.entries().forEach(compressed -> {
             CompressedResourceHeader header = CompressedResourceHeader.readFromResource(
-                    ByteOrder.nativeOrder(), compressed.getBytes());
-            String path = compressed.getPath();
-            ModuleEntry orig = inputResources.findEntry(path).get();
+                    ByteOrder.nativeOrder(), compressed.contentBytes());
+            String path = compressed.path();
+            ResourcePoolEntry orig = inputResources.findEntry(path).get();
             if (!isIncluded(includesPatterns, path)) {
                 return;
             }
-            byte[] decompressed = compressed.getBytes();
+            byte[] decompressed = compressed.contentBytes();
             for (ResourceDecompressorFactory factory : decompressors) {
                 try {
                     ResourceDecompressor decompressor = factory.newDecompressor(new Properties());
@@ -327,11 +334,11 @@
                 }
             }
 
-            if (decompressed.length != orig.getLength()) {
+            if (decompressed.length != orig.contentLength()) {
                 throw new AssertionError("Invalid uncompressed size "
                         + header.getUncompressedSize());
             }
-            byte[] origContent = orig.getBytes();
+            byte[] origContent = orig.contentBytes();
             for (int i = 0; i < decompressed.length; i++) {
                 if (decompressed[i] != origContent[i]) {
                     throw new AssertionError("Decompressed and original differ at index " + i);
--- a/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -35,11 +35,11 @@
 import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 
 import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class ExcludeFilesPluginTest {
     public static void main(String[] args) throws Exception {
@@ -71,20 +71,20 @@
         prop.put(ExcludeFilesPlugin.NAME, s);
         ExcludeFilesPlugin fplug = new ExcludeFilesPlugin();
         fplug.configure(prop);
-        ModulePoolImpl files = new ModulePoolImpl();
-        ModulePoolImpl fresult = new ModulePoolImpl();
-        ModuleEntry f = ModuleEntry.create("/" + module + "/" + sample,
-                ModuleEntry.Type.CONFIG, new byte[0]);
+        ResourcePoolManager files = new ResourcePoolManager();
+        ResourcePoolManager fresult = new ResourcePoolManager();
+        ResourcePoolEntry f = ResourcePoolEntry.create("/" + module + "/" + sample,
+                ResourcePoolEntry.Type.CONFIG, new byte[0]);
         files.add(f);
 
-        fplug.visit(files, fresult);
+        ResourcePool resPool = fplug.transform(files.resourcePool(), fresult.resourcePoolBuilder());
 
         if (exclude) {
-            if (fresult.contains(f)) {
+            if (resPool.contains(f)) {
                 throw new Exception(sample + " should be excluded by " + s);
             }
         } else {
-            if (!fresult.contains(f)) {
+            if (!resPool.contains(f)) {
                 throw new Exception(sample + " shouldn't be excluded by " + s);
             }
         }
--- a/test/tools/jlink/plugins/ExcludePluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/ExcludePluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -34,11 +34,12 @@
 import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 
 import jdk.tools.jlink.internal.plugins.ExcludePlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class ExcludePluginTest {
 
@@ -75,17 +76,18 @@
         prop.put(ExcludePlugin.NAME, s);
         ExcludePlugin excludePlugin = new ExcludePlugin();
         excludePlugin.configure(prop);
-        ModulePool resources = new ModulePoolImpl();
-        ModuleEntry resource = ModuleEntry.create(sample, new byte[0]);
-        resources.add(resource);
-        ModulePool result = new ModulePoolImpl();
-        excludePlugin.visit(resources, result);
+        ResourcePoolManager resourcesMgr = new ResourcePoolManager();
+        ResourcePoolEntry resource = ResourcePoolEntry.create(sample, new byte[0]);
+        resourcesMgr.add(resource);
+        ResourcePoolManager resultMgr = new ResourcePoolManager();
+        ResourcePool resPool = excludePlugin.transform(resourcesMgr.resourcePool(),
+                resultMgr.resourcePoolBuilder());
         if (exclude) {
-            if (result.contains(resource)) {
+            if (resPool.contains(resource)) {
                 throw new AssertionError(sample + " should be excluded by " + s);
             }
         } else {
-            if (!result.contains(resource)) {
+            if (!resPool.contains(resource)) {
                 throw new AssertionError(sample + " shouldn't be excluded by " + s);
             }
         }
--- a/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -32,12 +32,12 @@
 import java.io.ByteArrayInputStream;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 
 import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class ExcludeVMPluginTest {
 
@@ -163,14 +163,15 @@
     private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
         // Create a pool with jvm.cfg and the input paths.
         byte[] jvmcfgContent = jvmcfg.getBytes();
-        ModulePool pool = new ModulePoolImpl();
-        pool.add(ModuleEntry.create("/java.base/native/jvm.cfg",
-                ModuleEntry.Type.NATIVE_LIB, jvmcfgContent));
+        ResourcePoolManager poolMgr = new ResourcePoolManager();
+        poolMgr.add(
+            ResourcePoolEntry.create("/java.base/native/jvm.cfg",
+                ResourcePoolEntry.Type.NATIVE_LIB, jvmcfgContent));
         for (String in : input) {
-            pool.add(ModuleEntry.create(in,
-                    ModuleEntry.Type.NATIVE_LIB, new byte[0]));
+            poolMgr.add(ResourcePoolEntry.create(in,
+                    ResourcePoolEntry.Type.NATIVE_LIB, new byte[0]));
         }
-        ModulePool out = new ModulePoolImpl();
+        ResourcePoolManager outMgr = new ResourcePoolManager();
 
         Plugin p = new ExcludeVMPlugin();
         Map<String, String> config = new HashMap<>();
@@ -178,34 +179,34 @@
             config.put(ExcludeVMPlugin.NAME, vm);
         }
         p.configure(config);
-        p.visit(pool, out);
+        ResourcePool out = p.transform(poolMgr.resourcePool(), outMgr.resourcePoolBuilder());
 
-        String newContent = new String(out.findEntry("/java.base/native/jvm.cfg").get().stream().readAllBytes());
+        String newContent = new String(out.findEntry("/java.base/native/jvm.cfg").get().contentBytes());
 
         if (!expectdJvmCfg.equals(newContent)) {
             throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
         }
 
-        if (out.getEntryCount() != (expectedOutput.length + 1)) {
+        if (out.entryCount() != (expectedOutput.length + 1)) {
             out.entries().forEach(m -> {
-                System.err.println(m.getPath());
+                System.err.println(m.path());
             });
-            throw new Exception("Invalid output size " + out.getEntryCount() + " expected " + (expectedOutput.length + 1));
+            throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 1));
         }
 
         out.entries().forEach(md -> {
-            if (md.getPath().equals("/java.base/native/jvm.cfg")) {
+            if (md.path().equals("/java.base/native/jvm.cfg")) {
                 return;
             }
             boolean contained = false;
             for (String o : expectedOutput) {
-                if (md.getPath().equals(o)) {
+                if (md.path().equals(o)) {
                     contained = true;
                     break;
                 }
             }
             if (!contained) {
-                throw new RuntimeException(md.getPath() + " not expected");
+                throw new RuntimeException(md.path() + " not expected");
             }
         });
 
--- a/test/tools/jlink/plugins/FileCopierPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/FileCopierPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -37,12 +37,12 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
 
 import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
 
 public class FileCopierPluginTest {
 
@@ -85,18 +85,20 @@
         Map<String, String> conf = new HashMap<>();
         conf.put(FileCopierPlugin.NAME, builder.toString());
         plug.configure(conf);
-        ModulePool pool = new ModulePoolImpl();
-        plug.visit(new ModulePoolImpl(), pool);
-        if (pool.getEntryCount() != expected) {
+        ResourcePoolManager poolMgr = new ResourcePoolManager();
+        ResourcePool pool = plug.transform(
+                new ResourcePoolManager().resourcePool(),
+                poolMgr.resourcePoolBuilder());
+        if (pool.entryCount() != expected) {
             throw new AssertionError("Wrong number of added files");
         }
         pool.entries().forEach(f -> {
-            if (!f.getType().equals(ModuleEntry.Type.OTHER)) {
-                throw new AssertionError("Invalid type " + f.getType()
-                        + " for file " + f.getPath());
+            if (!f.type().equals(ResourcePoolEntry.Type.OTHER)) {
+                throw new AssertionError("Invalid type " + f.type()
+                        + " for file " + f.path());
             }
-            if (f.stream() == null) {
-                throw new AssertionError("Null stream for file " + f.getPath());
+            if (f.content() == null) {
+                throw new AssertionError("Null stream for file " + f.path());
             }
         });
         Path root = new File(".").toPath();
--- a/test/tools/jlink/plugins/LastSorterTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/LastSorterTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -39,12 +39,13 @@
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class LastSorterTest {
 
@@ -78,7 +79,7 @@
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        ModulePoolImpl res = fillOutResourceModulePool();
+        ResourcePoolManager res = fillOutResourceResourcePool();
 
         try {
             stack.visitResources(res);
@@ -89,18 +90,18 @@
         }
     }
 
-    private ModulePoolImpl fillOutResourceModulePool() throws Exception {
-        ModulePoolImpl res = new ModulePoolImpl();
-        res.add(ModuleEntry.create("/eee/bbb/res1.class", new byte[90]));
-        res.add(ModuleEntry.create("/aaaa/bbb/res2.class", new byte[90]));
-        res.add(ModuleEntry.create("/bbb/aa/res1.class", new byte[90]));
-        res.add(ModuleEntry.create("/aaaa/bbb/res3.class", new byte[90]));
-        res.add(ModuleEntry.create("/bbb/aa/res2.class", new byte[90]));
-        res.add(ModuleEntry.create("/fff/bbb/res1.class", new byte[90]));
-        res.add(ModuleEntry.create("/aaaa/bbb/res1.class", new byte[90]));
-        res.add(ModuleEntry.create("/bbb/aa/res3.class", new byte[90]));
-        res.add(ModuleEntry.create("/ccc/bbb/res1.class", new byte[90]));
-        res.add(ModuleEntry.create("/ddd/bbb/res1.class", new byte[90]));
+    private ResourcePoolManager fillOutResourceResourcePool() throws Exception {
+        ResourcePoolManager res = new ResourcePoolManager();
+        res.add(ResourcePoolEntry.create("/eee/bbb/res1.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/aaaa/bbb/res2.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/bbb/aa/res1.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/aaaa/bbb/res3.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/bbb/aa/res2.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/fff/bbb/res1.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/aaaa/bbb/res1.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/bbb/aa/res3.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/ccc/bbb/res1.class", new byte[90]));
+        res.add(ResourcePoolEntry.create("/ddd/bbb/res1.class", new byte[90]));
         return res;
     }
 
@@ -122,7 +123,7 @@
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        ModulePoolImpl res = fillOutResourceModulePool();
+        ResourcePoolManager res = fillOutResourceResourcePool();
 
         stack.visitResources(res);
     }
@@ -157,7 +158,7 @@
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
 
         // check order
-        ModulePoolImpl res = fillOutResourceModulePool();
+        ResourcePoolManager res = fillOutResourceResourcePool();
         try {
             stack.visitResources(res);
             throw new AssertionError("Order was changed after the last sorter, but no exception occurred");
@@ -176,19 +177,21 @@
         }
 
         @Override
-        public void visit(ModulePool resources, ModulePool output) {
-            List<ModuleEntry> paths = new ArrayList<>();
+        public ResourcePool transform(ResourcePool resources, ResourcePoolBuilder output) {
+            List<ResourcePoolEntry> paths = new ArrayList<>();
             resources.entries().forEach(res -> {
-                if (res.getPath().startsWith(starts)) {
+                if (res.path().startsWith(starts)) {
                     paths.add(0, res);
                 } else {
                     paths.add(res);
                 }
             });
 
-            for (ModuleEntry r : paths) {
+            for (ResourcePoolEntry r : paths) {
                 output.add(r);
             }
+
+            return output.build();
         }
 
         @Override
--- a/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -1,145 +0,0 @@
-/*
- * 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
- * @summary Test sorter plugin
- * @author Jean-Francois Denise
- * @modules jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins
- * @run main OrderResourcesPluginTest
- */
-
-import java.io.File;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.plugin.Plugin;
-
-public class OrderResourcesPluginTest {
-
-    public static void main(String[] args) throws Exception {
-        new OrderResourcesPluginTest().test();
-    }
-
-    public void test() throws Exception {
-        ModuleEntry[] array = {
-                ModuleEntry.create("/module1/toto1.class", new byte[0]),
-                ModuleEntry.create("/module2/toto2.class", new byte[0]),
-                ModuleEntry.create("/module3/toto3.class", new byte[0]),
-                ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
-                ModuleEntry.create("/zazou/toto.class", new byte[0]),
-                ModuleEntry.create("/module4/zazou.class", new byte[0]),
-                ModuleEntry.create("/module5/toto5.class", new byte[0]),
-                ModuleEntry.create("/module6/toto6/module-info.class", new byte[0])
-        };
-
-        ModuleEntry[] sorted = {
-                ModuleEntry.create("/zazou/toto.class", new byte[0]),
-                ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
-                ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]),
-                ModuleEntry.create("/module1/toto1.class", new byte[0]),
-                ModuleEntry.create("/module2/toto2.class", new byte[0]),
-                ModuleEntry.create("/module3/toto3.class", new byte[0]),
-                ModuleEntry.create("/module4/zazou.class", new byte[0]),
-                ModuleEntry.create("/module5/toto5.class", new byte[0])
-        };
-
-        ModuleEntry[] sorted2 = {
-            ModuleEntry.create("/module5/toto5.class", new byte[0]),
-            ModuleEntry.create("/module6/toto6/module-info.class", new byte[0]),
-            ModuleEntry.create("/module4/zazou.class", new byte[0]),
-            ModuleEntry.create("/module3/toto3.class", new byte[0]),
-            ModuleEntry.create("/module3/toto3/module-info.class", new byte[0]),
-            ModuleEntry.create("/module1/toto1.class", new byte[0]),
-            ModuleEntry.create("/module2/toto2.class", new byte[0]),
-            ModuleEntry.create("/zazou/toto.class", new byte[0])
-        };
-
-        ModulePool resources = new ModulePoolImpl();
-        for (ModuleEntry r : array) {
-            resources.add(r);
-        }
-
-        {
-            ModulePool out = new ModulePoolImpl();
-            Map<String, String> config = new HashMap<>();
-            config.put(OrderResourcesPlugin.NAME, "/zazou/**,**/module-info.class");
-            Plugin p = new OrderResourcesPlugin();
-            p.configure(config);
-            p.visit(resources, out);
-            check(out.entries().collect(Collectors.toList()), sorted);
-        }
-
-        {
-            // Order of resources in the file, then un-ordered resources.
-            File order = new File("resources.order");
-            order.createNewFile();
-            StringBuilder builder = new StringBuilder();
-            // 5 first resources come from file
-            for (int i = 0; i < 5; i++) {
-                String path = sorted2[i].getPath();
-                int index = path.indexOf('/', 1);
-                path = path.substring(index + 1, path.length() - ".class".length());
-                builder.append(path).append("\n");
-            }
-            Files.write(order.toPath(), builder.toString().getBytes());
-
-            ModulePool out = new ModulePoolImpl();
-            Map<String, String> config = new HashMap<>();
-            config.put(OrderResourcesPlugin.NAME, "@" + order.getAbsolutePath());
-            Plugin p = new OrderResourcesPlugin();
-            p.configure(config);
-            p.visit(resources, out);
-            check(out.entries().collect(Collectors.toList()), sorted2);
-
-        }
-    }
-
-    private void check(Collection<ModuleEntry> outResources,
-            ModuleEntry[] sorted) {
-        if (outResources.size() != sorted.length) {
-            throw new AssertionError("Wrong number of resources:\n"
-                    + "expected: " + Arrays.toString(sorted) + ",\n"
-                    + "     got: " + outResources);
-        }
-        int i = 0;
-        for (ModuleEntry r : outResources) {
-            System.err.println("Resource: " + r);
-            if (!sorted[i].getPath().equals(r.getPath())) {
-                throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n"
-                        + "expected: " + Arrays.toString(sorted) + ",\n"
-                        + "     got: " + outResources);
-            }
-            i++;
-        }
-    }
-}
--- a/test/tools/jlink/plugins/PluginsNegativeTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/PluginsNegativeTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -38,12 +38,13 @@
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.Jlink.PluginsConfiguration;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class PluginsNegativeTest {
 
@@ -95,8 +96,8 @@
         plugins.add(createPlugin("plugin"));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
                 null, null));
-        ModulePoolImpl inResources = new ModulePoolImpl();
-        inResources.add(ModuleEntry.create("/aaa/bbb/A", new byte[10]));
+        ResourcePoolManager inResources = new ResourcePoolManager();
+        inResources.add(ResourcePoolEntry.create("/aaa/bbb/A", new byte[10]));
         try {
             stack.visitResources(inResources);
             throw new AssertionError("Exception expected when output resource is empty");
@@ -109,8 +110,8 @@
         plugins.add(createPlugin("plugin"));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
                 null, null));
-        ModulePoolImpl inResources = new ModulePoolImpl();
-        ModulePoolImpl outResources = (ModulePoolImpl) stack.visitResources(inResources);
+        ResourcePoolManager inResources = new ResourcePoolManager();
+        ResourcePool outResources = stack.visitResources(inResources);
         if (!outResources.isEmpty()) {
             throw new AssertionError("Output resource is not empty");
         }
@@ -125,8 +126,9 @@
         }
 
         @Override
-        public void visit(ModulePool inResources, ModulePool outResources) {
-            // do nothing
+        public ResourcePool transform(ResourcePool inResources, ResourcePoolBuilder outResources) {
+            // don't add anything to the builder
+            return outResources.build();
         }
 
         @Override
--- a/test/tools/jlink/plugins/PrevisitorTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/PrevisitorTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -42,13 +42,15 @@
 import jdk.tools.jlink.internal.ImagePluginConfiguration;
 import jdk.tools.jlink.internal.PluginRepository;
 import jdk.tools.jlink.internal.ImagePluginStack;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
 import jdk.tools.jlink.internal.ResourcePrevisitor;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.Jlink;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePool;
+import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 public class PrevisitorTest {
 
@@ -67,13 +69,13 @@
         plugins.add(createPlugin(CustomPlugin.NAME));
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new Jlink.PluginsConfiguration(plugins,
                 null, null));
-        ModulePoolImpl inResources = new ModulePoolImpl(ByteOrder.nativeOrder(), new CustomStringTable());
-        inResources.add(ModuleEntry.create("/aaa/bbb/res1.class", new byte[90]));
-        inResources.add(ModuleEntry.create("/aaa/bbb/res2.class", new byte[90]));
-        inResources.add(ModuleEntry.create("/aaa/bbb/res3.class", new byte[90]));
-        inResources.add(ModuleEntry.create("/aaa/ddd/res1.class", new byte[90]));
-        inResources.add(ModuleEntry.create("/aaa/res1.class", new byte[90]));
-        ModulePool outResources = stack.visitResources(inResources);
+        ResourcePoolManager inResources = new ResourcePoolManager(ByteOrder.nativeOrder(), new CustomStringTable());
+        inResources.add(ResourcePoolEntry.create("/aaa/bbb/res1.class", new byte[90]));
+        inResources.add(ResourcePoolEntry.create("/aaa/bbb/res2.class", new byte[90]));
+        inResources.add(ResourcePoolEntry.create("/aaa/bbb/res3.class", new byte[90]));
+        inResources.add(ResourcePoolEntry.create("/aaa/ddd/res1.class", new byte[90]));
+        inResources.add(ResourcePoolEntry.create("/aaa/res1.class", new byte[90]));
+        ResourcePool outResources = stack.visitResources(inResources);
         Collection<String> input = inResources.entries()
                 .map(Object::toString)
                 .collect(Collectors.toList());
@@ -113,19 +115,18 @@
         private boolean isPrevisitCalled = false;
 
         @Override
-        public void visit(ModulePool inResources, ModulePool outResources) {
+        public ResourcePool transform(ResourcePool inResources, ResourcePoolBuilder outResources) {
             if (!isPrevisitCalled) {
                 throw new AssertionError("Previsit was not called");
             }
-            CustomStringTable table = (CustomStringTable)
-                    ((ModulePoolImpl) inResources).getStringTable();
+            CustomStringTable table = (CustomStringTable)((ResourcePoolImpl)inResources).getStringTable();
             if (table.size() == 0) {
                 throw new AssertionError("Table is empty");
             }
             Map<String, Integer> count = new HashMap<>();
             for (int i = 0; i < table.size(); ++i) {
                 String s = table.getString(i);
-                Optional<ModuleEntry> e = inResources.findEntry(s);
+                Optional<ResourcePoolEntry> e = inResources.findEntry(s);
                 if (e.isPresent()) {
                     throw new AssertionError();
                 }
@@ -139,6 +140,8 @@
             inResources.entries().forEach(r -> {
                 outResources.add(r);
             });
+
+            return outResources.build();
         }
 
         @Override
@@ -147,10 +150,10 @@
         }
 
         @Override
-        public void previsit(ModulePool resources, StringTable strings) {
+        public void previsit(ResourcePool resources, StringTable strings) {
             isPrevisitCalled = true;
             resources.entries().forEach(r -> {
-                String s = r.getPath();
+                String s = r.path();
                 int lastIndexOf = s.lastIndexOf('/');
                 if (lastIndexOf >= 0) {
                     strings.addString(s.substring(0, lastIndexOf));
--- a/test/tools/jlink/plugins/StringSharingPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/StringSharingPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -52,11 +52,11 @@
 
 import jdk.internal.jimage.decompressor.CompressedResourceHeader;
 import jdk.internal.jimage.decompressor.StringSharingDecompressor;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.internal.StringTable;
 import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.Plugin;
 import tests.Helper;
 import tests.JImageValidator;
@@ -80,7 +80,7 @@
         Map<String, Integer> map = new HashMap<>();
         Map<Integer, String> reversedMap = new HashMap<>();
 
-        ModulePoolImpl resources = new ModulePoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+        ResourcePoolManager resources = new ResourcePoolManager(ByteOrder.nativeOrder(), new StringTable() {
             @Override
             public int addString(String str) {
                 Integer id = map.get(str);
@@ -109,7 +109,7 @@
                     if (path.charAt(0) != '/') {
                         path = "/" + path;
                     }
-                    ModuleEntry res = ModuleEntry.create(path, content);
+                    ResourcePoolEntry res = ResourcePoolEntry.create(path, content);
                     resources.add(res);
                 } catch (Exception ex) {
                     throw new RuntimeException(ex);
@@ -120,17 +120,17 @@
             stream.forEach(c);
         }
         Plugin plugin = new StringSharingPlugin();
-        ModulePoolImpl result = new ModulePoolImpl(resources.getByteOrder(), resources.getStringTable());
-        plugin.visit(resources, result);
+        ResourcePoolManager resultMgr = new ResourcePoolManager(resources.byteOrder(), resources.getStringTable());
+        ResourcePool result = plugin.transform(resources.resourcePool(), resultMgr.resourcePoolBuilder());
 
         if (result.isEmpty()) {
             throw new AssertionError("No result");
         }
 
         result.entries().forEach(res -> {
-            if (res.getPath().endsWith(".class")) {
+            if (res.path().endsWith(".class")) {
                 try {
-                    byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(),
+                    byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.contentBytes(),
                         CompressedResourceHeader.getSize());
                     JImageValidator.readClass(uncompacted);
                 } catch (IOException exp) {
--- a/test/tools/jlink/plugins/StripDebugPluginTest.java	Tue Jul 26 14:45:11 2016 -0700
+++ b/test/tools/jlink/plugins/StripDebugPluginTest.java	Thu Jul 28 09:01:30 2016 -0700
@@ -54,10 +54,10 @@
 import com.sun.tools.classfile.Method;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.tools.jlink.internal.ModulePoolImpl;
+import jdk.tools.jlink.internal.ResourcePoolManager;
 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.Plugin;
 import tests.Helper;
 
@@ -106,36 +106,38 @@
         path = path.replace('\\', '/');
         StripDebugPlugin debug = new StripDebugPlugin();
         debug.configure(new HashMap<>());
-        ModuleEntry result1 = stripDebug(debug, ModuleEntry.create(path,content), path, infoPath, moduleInfo);
+        ResourcePoolEntry result1 = stripDebug(debug, ResourcePoolEntry.create(path,content), path, infoPath, moduleInfo);
 
         if (!path.endsWith("module-info.class")) {
-            if (result1.getLength() >= content.length) {
+            if (result1.contentLength() >= content.length) {
                 throw new AssertionError("Class size not reduced, debug info not "
                         + "removed for " + path);
             }
-            checkDebugAttributes(result1.getBytes());
+            checkDebugAttributes(result1.contentBytes());
         }
 
-        ModuleEntry result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
-        if (result1.getLength() != result2.getLength()) {
+        ResourcePoolEntry result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
+        if (result1.contentLength() != result2.contentLength()) {
             throw new AssertionError("removing debug info twice reduces class size of "
                     + path);
         }
-        checkDebugAttributes(result1.getBytes());
+        checkDebugAttributes(result1.contentBytes());
     }
 
-    private ModuleEntry stripDebug(Plugin debug, ModuleEntry classResource,
+    private ResourcePoolEntry stripDebug(Plugin debug, ResourcePoolEntry classResource,
             String path, String infoPath, byte[] moduleInfo) throws Exception {
-        ModulePool resources = new ModulePoolImpl();
+        ResourcePoolManager resources = new ResourcePoolManager();
         resources.add(classResource);
         if (!path.endsWith("module-info.class")) {
-            ModuleEntry res2 = ModuleEntry.create(infoPath, moduleInfo);
+            ResourcePoolEntry res2 = ResourcePoolEntry.create(infoPath, moduleInfo);
             resources.add(res2);
         }
-        ModulePool results = new ModulePoolImpl();
-        debug.visit(resources, results);
-        System.out.println(classResource.getPath());
-        return results.findEntry(classResource.getPath()).get();
+        ResourcePoolManager results = new ResourcePoolManager();
+        ResourcePool resPool = debug.transform(resources.resourcePool(),
+                results.resourcePoolBuilder());
+        System.out.println(classResource.path());
+
+        return resPool.findEntry(classResource.path()).get();
     }
 
     private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException {