8162538: plugin API should avoid read only pool, have module view separated from resource view and have pool builder to modify
authorsundar
Thu, 28 Jul 2016 19:34:58 +0530
changeset 39834 53a6fb443c20
parent 39833 f5a1bd5db861
child 39835 4ecd563fecf6
8162538: plugin API should avoid read only pool, have module view separated from resource view and have pool builder to modify Reviewed-by: jlaskey, psandoz
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractResourcePoolEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayResourcePoolEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolEntryFactory.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePool.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolBuilder.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModule.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModuleView.java
jdk/test/tools/jlink/DefaultProviderTest.java
jdk/test/tools/jlink/ImageFileCreatorTest.java
jdk/test/tools/jlink/ImageFilePoolTest.java
jdk/test/tools/jlink/IntegrationTest.java
jdk/test/tools/jlink/JLinkOptionsTest.java
jdk/test/tools/jlink/JLinkPostProcessingTest.java
jdk/test/tools/jlink/ResourcePoolTest.java
jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
jdk/test/tools/jlink/plugins/CompressorPluginTest.java
jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
jdk/test/tools/jlink/plugins/ExcludePluginTest.java
jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
jdk/test/tools/jlink/plugins/LastSorterTest.java
jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java
jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
jdk/test/tools/jlink/plugins/PrevisitorTest.java
jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractResourcePoolEntry.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryResourcePoolEntry.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayResourcePoolEntry.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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);
-        }
-
-        @Override
-        public ByteOrder getByteOrder() {
-            return pool.getByteOrder();
+        public ByteOrder byteOrder() {
+            return pool.byteOrder();
         }
 
         @Override
-        public Map<String, String> getReleaseProperties() {
-            return Collections.unmodifiableMap(pool.getReleaseProperties());
+        public Map<String, String> releaseProperties() {
+            return pool.releaseProperties();
         }
 
-        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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathResourcePoolEntry.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolEntryFactory.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/LinkModule.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java	Thu Jul 28 13:29:34 2016 +0100
+++ /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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePool.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolBuilder.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolEntry.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModule.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModuleView.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/DefaultProviderTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/ImageFileCreatorTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/ImageFilePoolTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/IntegrationTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/IntegrationTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/JLinkOptionsTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/JLinkPostProcessingTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/ResourcePoolTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/CompressorPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/ExcludePluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/LastSorterTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/OrderResourcesPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/PrevisitorTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java	Thu Jul 28 13:29:34 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java	Thu Jul 28 19:34:58 2016 +0530
@@ -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 {