changeset 13709:f46e12661ebb

jimage recereate unit test. Removed unused files. Reviewed-by: jlaskey
author jfdenise
date Tue, 18 Aug 2015 15:07:50 +0200
parents ec4517852b4e
children 06c41682a172
files src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java src/java.base/share/classes/jdk/internal/jimage/ResourcePool.java src/java.base/share/classes/jdk/internal/jimage/ResourcePoolImpl.java test/jdk/jigsaw/tools/jimage/JImageTest.java test/jdk/jigsaw/tools/jimage/JImageToolTest.java
diffstat 5 files changed, 14 insertions(+), 829 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java	Fri Aug 14 14:52:04 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import jdk.internal.jimage.Archive.Entry;
-import jdk.internal.jimage.Archive.Entry.EntryType;
-import static jdk.internal.jimage.BasicImageWriter.BOOT_NAME;
-import static jdk.internal.jimage.BasicImageWriter.IMAGE_EXT;
-
-/**
- * An image (native endian.)
- * <pre>{@code
- * {
- *   u4 magic;
- *   u2 major_version;
- *   u2 minor_version;
- *   u4 resource_count;
- *   u4 table_length;
- *   u4 location_attributes_size;
- *   u4 strings_size;
- *   u4 redirect[table_length];
- *   u4 offsets[table_length];
- *   u1 location_attributes[location_attributes_size];
- *   u1 strings[strings_size];
- *   u1 content[if !EOF];
- * }
- * }</pre>
- */
-public final class ImageFileCreator {
-    private final Path root;
-    private final Path mdir;
-    private final Map<String, List<Entry>> entriesForModule = new HashMap<>();
-    private ImageFileCreator(Path path) {
-        this.root = path;
-        this.mdir = root.resolve(path.getFileSystem().getPath("lib", "modules"));
-    }
-
-    public static ImageFileCreator create(Path output,
-            Set<Archive> archives)
-            throws IOException {
-        return create(output, BOOT_NAME, archives, ByteOrder.nativeOrder());
-    }
-
-    public static ImageFileCreator create(Path output,
-            Set<Archive> archives,
-            ByteOrder byteOrder)
-            throws IOException {
-        return create(output, BOOT_NAME, archives, byteOrder);
-    }
-
-    public static ImageFileCreator create(Path output,
-                                   String fileName,
-                                   Set<Archive> archives,
-                                   ByteOrder byteOrder)
-        throws IOException
-    {
-        ImageFileCreator image = new ImageFileCreator(output);
-        // get all entries
-        Map<String, Set<String>> modulePackagesMap = new HashMap<>();
-        image.readAllEntries(modulePackagesMap, archives);
-        // write to modular image
-        image.writeImage(fileName, modulePackagesMap, archives, byteOrder);
-        return image;
-    }
-
-    private void readAllEntries(Map<String, Set<String>> modulePackagesMap,
-                                  Set<Archive> archives) {
-        archives.stream().forEach((archive) -> {
-            Map<Boolean, List<Entry>> es;
-            try(Stream<Entry> entries = archive.entries()) {
-                es = entries.collect(Collectors.partitioningBy(n -> n.type()
-                        == EntryType.CLASS_OR_RESOURCE));
-            }
-            String mn = archive.moduleName();
-            List<Entry> all = new ArrayList<>();
-            all.addAll(es.get(false));
-            all.addAll(es.get(true));
-            entriesForModule.put(mn, all);
-            // Extract package names
-            Set<String> pkgs = es.get(true).stream().map(Entry::name)
-                    .filter(n -> isClassPackage(n))
-                    .map(ImageFileCreator::toPackage)
-                    .collect(Collectors.toSet());
-            modulePackagesMap.put(mn, pkgs);
-        });
-    }
-
-    public static boolean isClassPackage(String path) {
-        return path.endsWith(".class");
-    }
-
-    public static boolean isResourcePackage(String path) {
-        path = path.substring(1);
-        path = path.substring(path.indexOf("/")+1);
-        return !path.startsWith("META-INF/");
-    }
-
-    public static void recreateJimage(Path jimageFile,
-            Set<Archive> archives,
-            Map<String, Set<String>> modulePackages)
-            throws IOException {
-        Map<String, List<Entry>> entriesForModule
-                = archives.stream().collect(Collectors.toMap(
-                                Archive::moduleName,
-                                a -> {
-                                    try(Stream<Entry> entries = a.entries()) {
-                                        return entries.collect(Collectors.toList());
-                                    }
-                                }));
-        Map<String, Archive> nameToArchive
-                = archives.stream()
-                .collect(Collectors.toMap(Archive::moduleName, Function.identity()));
-        ByteOrder order = ByteOrder.nativeOrder();
-        ResourcePoolImpl resources = createResources(modulePackages, nameToArchive,
-                (Entry t) -> {
-            throw new UnsupportedOperationException("Not supported, no external file "
-                    + "in a jimage file");
-        }, entriesForModule, order);
-        String fileName = jimageFile.getFileName().toString();
-        if (fileName.endsWith(IMAGE_EXT)) {
-            fileName = fileName.substring(0, fileName.length()
-                    - BasicImageWriter.IMAGE_EXT.length());
-        }
-        generateJImage(jimageFile, fileName, resources, order);
-    }
-
-    private void writeImage(String fileName,
-            Map<String, Set<String>> modulePackagesMap,
-            Set<Archive> archives,
-            ByteOrder byteOrder)
-            throws IOException {
-        Files.createDirectories(mdir);
-        ExternalFilesWriter filesWriter = new ExternalFilesWriter(root);
-        // name to Archive file
-        Map<String, Archive> nameToArchive
-                = archives.stream()
-                .collect(Collectors.toMap(Archive::moduleName, Function.identity()));
-        ResourcePoolImpl resources = createResources(modulePackagesMap,
-                nameToArchive, filesWriter,
-                entriesForModule, byteOrder);
-        generateJImage(mdir.resolve(fileName + IMAGE_EXT), fileName, resources,
-                byteOrder);
-    }
-
-    private static void generateJImage(Path img,
-            String fileName,
-            ResourcePoolImpl resources,
-            ByteOrder byteOrder
-    ) throws IOException {
-        BasicImageWriter writer = new BasicImageWriter(byteOrder);
-
-        Map<String, Set<String>> modulePackagesMap = resources.getModulePackages();
-
-        try (OutputStream fos = Files.newOutputStream(img);
-                BufferedOutputStream bos = new BufferedOutputStream(fos);
-                DataOutputStream out = new DataOutputStream(bos)) {
-            Set<String> duplicates = new HashSet<>();
-            ImageModuleDataWriter moduleData =
-            ImageModuleDataWriter.buildModuleData(writer, modulePackagesMap);
-            moduleData.addLocation(fileName, writer);
-            long offset = moduleData.size();
-
-            List<ResourcePool.Resource> 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
-            for (ResourcePool.Resource res : resources.getResources()) {
-                String path = res.getPath();
-                int index = path.indexOf("/META-INF/");
-                if (index != -1) {
-                    path = path.substring(index + 1);
-                }
-
-                content.add(res);
-                long uncompressedSize = res.getLength();
-                long compressedSize = 0;
-                if (res instanceof ResourcePool.CompressedResource) {
-                    ResourcePool.CompressedResource comp =
-                            (ResourcePool.CompressedResource) res;
-                    compressedSize = res.getLength();
-                    uncompressedSize = comp.getUncompressedSize();
-                }
-                long onFileSize = res.getLength();
-
-                if (duplicates.contains(path)) {
-                    System.err.format("duplicate resource \"%s\", skipping%n",
-                            path);
-                     // TODO Need to hang bytes on resource and write
-                    // from resource not zip.
-                    // Skipping resource throws off writing from zip.
-                    offset += onFileSize;
-                    continue;
-                }
-                duplicates.add(path);
-                writer.addLocation(path, offset, compressedSize, uncompressedSize);
-                paths.add(path);
-                offset += onFileSize;
-            }
-
-            ImageResourcesTree tree = new ImageResourcesTree(offset, writer, paths);
-
-            // write header and indices
-            byte[] bytes = writer.getBytes();
-            out.write(bytes, 0, bytes.length);
-
-            // write module meta data
-            moduleData.writeTo(out);
-
-            // write module content
-            for(ResourcePool.Resource res : content) {
-                byte[] buf = res.getByteArray();
-                out.write(buf, 0, buf.length);
-            }
-
-            tree.addContent(out);
-        }
-    }
-
-    private static ResourcePoolImpl createResources(Map<String, Set<String>> modulePackagesMap,
-            Map<String, Archive> nameToArchive,
-            Consumer<Entry> externalFileHandler,
-            Map<String, List<Entry>> entriesForModule,
-            ByteOrder byteOrder) throws IOException {
-        ResourcePoolImpl resources = new ResourcePoolImpl(byteOrder);
-        Set<String> mods = modulePackagesMap.keySet();
-        for (String mn : mods) {
-            for (Entry entry : entriesForModule.get(mn)) {
-                String path = entry.name();
-                if (entry.type() == EntryType.CLASS_OR_RESOURCE) {
-                    if (!entry.path().endsWith(BOOT_NAME)) {
-                        try (InputStream stream = entry.stream()) {
-                            byte[] bytes = readAllBytes(stream);
-                            path = "/" + mn + "/" + path;
-                            try {
-                                resources.addResource(new ResourcePool.Resource(path,
-                                        ByteBuffer.wrap(bytes)));
-                            } catch (Exception ex) {
-                                throw new IOException(ex);
-                            }
-                        }
-                    }
-                } else {
-                    externalFileHandler.accept(entry);
-                }
-            }
-            // Done with this archive, close it.
-            Archive archive = nameToArchive.get(mn);
-            archive.close();
-        }
-        return resources;
-    }
-
-    private static final int BUF_SIZE = 8192;
-
-    private static byte[] readAllBytes(InputStream is) throws IOException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] buf = new byte[BUF_SIZE];
-        while (true) {
-            int n = is.read(buf);
-            if (n < 0) {
-                break;
-            }
-            baos.write(buf, 0, n);
-        }
-        return baos.toByteArray();
-    }
-
-    /**
-     * Helper method that splits a Resource path onto 3 items: module, parent
-     * and resource name.
-     *
-     * @param path
-     * @return An array containing module, parent and name.
-     */
-    public static String[] splitPath(String path) {
-        Objects.requireNonNull(path);
-        String noRoot = path.substring(1);
-        int pkgStart = noRoot.indexOf("/");
-        String module = noRoot.substring(0, pkgStart);
-        List<String> result = new ArrayList<>();
-        result.add(module);
-        String pkg = noRoot.substring(pkgStart + 1);
-        String resName;
-        int pkgEnd = pkg.lastIndexOf("/");
-        if (pkgEnd == -1) { // No package.
-            resName = pkg;
-        } else {
-            resName = pkg.substring(pkgEnd + 1);
-        }
-
-        pkg = toPackage(pkg, false);
-        result.add(pkg);
-        result.add(resName);
-
-        String[] array = new String[result.size()];
-        return result.toArray(array);
-    }
-
-    private static String toPackage(String name) {
-        String pkg = toPackage(name, true);
-        return pkg;
-    }
-
-    private static String toPackage(String name, boolean log) {
-        int index = name.lastIndexOf('/');
-        if (index > 0) {
-            return name.substring(0, index).replace('/', '.');
-        } else {
-            // ## unnamed package
-            if (log) {
-                System.err.format("Warning: %s in unnamed package%n", name);
-            }
-            return "";
-        }
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jimage/ResourcePool.java	Fri Aug 14 14:52:04 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +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.internal.jimage;
-
-import jdk.internal.jimage.decompressor.CompressedResourceHeader;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Pool of resources. This class contain the content of a jimage file in the
- * matter of Resource.
- */
-public interface ResourcePool {
-
-    /**
-     * Resources visitor
-     */
-    public interface Visitor {
-
-        /**
-         * Called for each visited Resource.
-         *
-         * @param resource The resource to deal with.
-         * @param order Byte order
-         * @param strings
-         * @return A resource or null if the passed resource is to be removed
-         * from the jimage.
-         * @throws Exception
-         */
-        public Resource visit(Resource resource, ByteOrder order,
-                StringTable strings) throws Exception;
-    }
-
-    /**
-     * A JImage Resource. Fully identified by its path.
-     */
-    public static class Resource {
-
-        private final String path;
-        private final ByteBuffer content;
-
-        private final String module;
-
-        public Resource(String path, ByteBuffer content) {
-            Objects.requireNonNull(path);
-            Objects.requireNonNull(content);
-            this.path = path;
-            this.content = content.asReadOnlyBuffer();
-            String[] split = ImageFileCreator.splitPath(path);
-            module = split[0];
-        }
-
-        public String getPath() {
-            return path;
-        }
-
-        public String getModule() {
-            return module;
-        }
-
-        /**
-         * The resource content.
-         *
-         * @return A read only buffer.
-         */
-        public ByteBuffer getContent() {
-            return content;
-        }
-
-        public int getLength() {
-            return content.limit();
-        }
-
-        public byte[] getByteArray() {
-            content.rewind();
-            byte[] array = new byte[content.remaining()];
-            content.get(array);
-            return array;
-        }
-
-        @Override
-        public String toString() {
-            return getPath();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof Resource)) {
-                return false;
-            }
-            Resource res = (Resource) obj;
-            return res.path.equals(path);
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 7;
-            hash = 53 * hash + Objects.hashCode(this.path);
-            return hash;
-        }
-    }
-
-    /**
-     * A resource that has been compressed.
-     */
-    public static final class CompressedResource extends Resource {
-
-        private final long uncompressed_size;
-
-        private CompressedResource(String path, ByteBuffer content,
-                long uncompressed_size) {
-            super(path, content);
-            this.uncompressed_size = uncompressed_size;
-        }
-
-        public long getUncompressedSize() {
-            return uncompressed_size;
-        }
-
-        public static CompressedResource newCompressedResource(Resource original,
-                ByteBuffer compressed,
-                String plugin, String pluginConfig, StringTable strings,
-                ByteOrder order) throws Exception {
-            Objects.requireNonNull(original);
-            Objects.requireNonNull(compressed);
-            Objects.requireNonNull(plugin);
-
-            boolean isTerminal = !(original instanceof CompressedResource);
-            long uncompressed_size = original.getLength();
-            if (original instanceof CompressedResource) {
-                CompressedResource comp = (CompressedResource) 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);
-            ByteBuffer contentWithHeader = ByteBuffer.wrap(bb.array());
-
-            CompressedResource compressedResource =
-                    new CompressedResource(original.getPath(),
-                    contentWithHeader, uncompressed_size);
-            return compressedResource;
-        }
-    }
-
-    /**
-     * Read only state.
-     *
-     * @return true if readonly false otherwise.
-     */
-    public boolean isReadOnly();
-
-    /**
-     * The byte order
-     *
-     * @return
-     */
-    public ByteOrder getByteOrder();
-
-    /**
-     * Add a resource.
-     *
-     * @param resource The Resource to add.
-     * @throws java.lang.Exception If the pool is read only.
-     */
-    public void addResource(Resource resource) throws Exception;
-
-    /**
-     * Check if a resource is contained in the pool.
-     *
-     * @param res The resource to check.
-     * @return true if res is contained, false otherwise.
-     */
-    public boolean contains(Resource res);
-
-    /**
-     * Get all resources contained in this pool instance.
-     *
-     * @return The collection of resources;
-     */
-    public Collection<Resource> getResources();
-
-    /**
-     * Get the resource for the passed path.
-     *
-     * @param path A resource path
-     * @return A Resource instance or null if the resource is not found
-     */
-    public Resource getResource(String path);
-
-    /**
-     * The Image modules. It is computed based on the resources contained by
-     * this ResourcePool instance.
-     *
-     * @return The Image Modules.
-     */
-    public Map<String, Set<String>> getModulePackages();
-
-    /**
-     * Check if this pool contains some resources.
-     *
-     * @return True if contains some resources.
-     */
-    public boolean isEmpty();
-
-    /**
-     * Visit the resources contained in this ResourcePool.
-     *
-     * @param visitor The visitor
-     * @param output The pool to store resources.
-     * @param strings
-     * @throws Exception
-     */
-    public void visit(Visitor visitor, ResourcePool output, StringTable strings)
-            throws Exception;
-
-    public void addTransformedResource(Resource original, ByteBuffer transformed)
-            throws Exception;
-}
--- a/src/java.base/share/classes/jdk/internal/jimage/ResourcePoolImpl.java	Fri Aug 14 14:52:04 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +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.internal.jimage;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Pool of resources. This class contain the content of a jimage file in the
- * matter of Resource.
- */
-public class ResourcePoolImpl implements ResourcePool {
-
-    private final Map<String, Resource> resources = new LinkedHashMap<>();
-
-    private final ByteOrder order;
-    private boolean isReadOnly;
-
-    public ResourcePoolImpl(ByteOrder order) {
-        Objects.requireNonNull(order);
-        this.order = order;
-    }
-
-    /**
-     * 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;
-    }
-
-    /**
-     * The byte order
-     *
-     * @return
-     */
-    @Override
-    public ByteOrder getByteOrder() {
-        return order;
-    }
-
-    /**
-     * Add a resource.
-     *
-     * @param resource The Resource to add.
-     * @throws java.lang.Exception If the pool is read only.
-     */
-    @Override
-    public void addResource(Resource resource) throws Exception {
-        if (isReadOnly()) {
-            throw new Exception("pool is readonly");
-        }
-        Objects.requireNonNull(resource);
-        if (resources.get(resource.getPath()) != null) {
-            throw new Exception("Resource" + resource.getPath() +
-                    " already present");
-        }
-        resources.put(resource.getPath(), resource);
-    }
-
-    /**
-     * Check if a resource is contained in the pool.
-     *
-     * @param res The resource to check.
-     * @return true if res is contained, false otherwise.
-     */
-    @Override
-    public boolean contains(Resource res) {
-        Objects.requireNonNull(res);
-        try {
-            getResource(res.getPath());
-            return true;
-        } catch (Exception ex) {
-            return false;
-        }
-    }
-
-    /**
-     * Get all resources contained in this pool instance.
-     *
-     * @return The collection of resources;
-     */
-    @Override
-    public Collection<Resource> getResources() {
-        return Collections.unmodifiableCollection(resources.values());
-    }
-
-/**
-     * Get the resource for the passed path.
-     *
-     * @param path A resource path
-     * @return A Resource instance or null if the resource is not found
-     */
-    @Override
-    public Resource getResource(String path) {
-        Objects.requireNonNull(path);
-        return resources.get(path);
-    }
-
-    /**
-     * The Image modules. It is computed based on the resources contained by
-     * this ResourcePool instance.
-     *
-     * @return The Image Modules.
-     */
-    @Override
-    public Map<String, Set<String>> getModulePackages() {
-        Map<String, Set<String>> moduleToPackage = new LinkedHashMap<>();
-        retrieveModulesPackages(moduleToPackage);
-        return moduleToPackage;
-    }
-
-    /**
-     * Check if this pool contains some resources.
-     *
-     * @return True if contains some resources.
-     */
-    @Override
-    public boolean isEmpty() {
-        return resources.isEmpty();
-    }
-
-    /**
-     * Visit the resources contained in this ResourcePool.
-     *
-     * @param visitor The visitor
-     * @param strings
-     * @throws Exception
-     */
-    @Override
-    public void visit(Visitor visitor, ResourcePool output, StringTable strings)
-            throws Exception {
-        for (Resource resource : getResources()) {
-            Resource res = visitor.visit(resource, order, strings);
-            if (res != null) {
-                output.addResource(res);
-            }
-        }
-    }
-
-    @Override
-    public void addTransformedResource(Resource original, ByteBuffer transformed)
-            throws Exception {
-        if (isReadOnly()) {
-            throw new Exception("Pool is readonly");
-        }
-        Objects.requireNonNull(original);
-        Objects.requireNonNull(transformed);
-        if (resources.get(original.getPath()) != null) {
-            throw new Exception("Resource already present");
-        }
-        Resource res = new Resource(original.getPath(), transformed);
-        addResource(res);
-    }
-
-    private void retrieveModulesPackages(Map<String, Set<String>> moduleToPackage) {
-        for (Resource res : resources.values()) {
-            Set<String> pkgs = moduleToPackage.get(res.getModule());
-            if (pkgs == null) {
-                pkgs = new HashSet<>();
-                moduleToPackage.put(res.getModule(), pkgs);
-            }
-            // Module metadata only contains packages with resource files
-            if (ImageFileCreator.isResourcePackage(res.getPath())) {
-                String[] split = ImageFileCreator.splitPath(res.getPath());
-                String pkg = split[1];
-                if (pkg != null && !pkg.isEmpty()) {
-                    pkgs.add(pkg);
-                }
-            }
-        }
-    }
-}
--- a/test/jdk/jigsaw/tools/jimage/JImageTest.java	Fri Aug 14 14:52:04 2015 -0700
+++ b/test/jdk/jigsaw/tools/jimage/JImageTest.java	Tue Aug 18 15:07:50 2015 +0200
@@ -28,6 +28,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.ProviderNotFoundException;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -103,9 +104,19 @@
         unexpectedPaths.add(".jcov");
         unexpectedPaths.add("/META-INF/");
         File image = helper.generateImage(module).getImageFile();
-        File extractedDir = helper.extractImageFile(image, "bootmodules.jimage");
+        String imgName = "bootmodules.jimage";
+        File extractedDir = helper.extractImageFile(image, imgName);
         File recreatedImage = helper.recreateImageFile(extractedDir);
         JImageValidator.validate(recreatedImage, bootClasses, Collections.emptyList());
+
+        // Check replacing the boot image by recreated one
+        File destFile = new File(image, "lib" + File.separator + "modules"
+                + File.separator + imgName);
+        Files.copy(recreatedImage.toPath(), destFile.toPath(), REPLACE_EXISTING);
+        JImageValidator validator = new JImageValidator(module, Collections.emptyList(),
+                image, Collections.emptyList(), Collections.emptyList());
+        validator.validate();
+
         File recreatedImage2 = helper.recreateImageFile(extractedDir, "--compress-resources", "on");
         JImageValidator.validate(recreatedImage2, bootClasses, Collections.emptyList());
         File recreatedImage3 = helper.recreateImageFile(extractedDir, "--strip-java-debug", "on");
--- a/test/jdk/jigsaw/tools/jimage/JImageToolTest.java	Fri Aug 14 14:52:04 2015 -0700
+++ b/test/jdk/jigsaw/tools/jimage/JImageToolTest.java	Tue Aug 18 15:07:50 2015 +0200
@@ -64,10 +64,10 @@
             String bootimage = bootimagePath.toAbsolutePath().toString();
             String extractDir = Paths.get(".", "extract").toAbsolutePath().toString();
             String recreateImage = Paths.get(".", "recreate.jimage").toAbsolutePath().toString();
-
+            String relativeRecreateImage = Paths.get(".", "recreate2.jimage").toString();
             jimage("extract", "--dir", extractDir, bootimage);
             jimage("recreate", "--dir", extractDir, recreateImage);
-
+            jimage("recreate", "--dir", extractDir, relativeRecreateImage);
             System.out.println("Test successful");
          } else {
             System.out.println("Test skipped, not an images build");