1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.tools.jlink.internal;
27
28import java.lang.module.Configuration;
29import java.lang.module.ModuleDescriptor;
30import java.lang.module.ModuleFinder;
31import java.lang.module.ModuleReader;
32import java.lang.module.ModuleReference;
33import java.io.IOException;
34import java.io.UncheckedIOException;
35import java.nio.ByteBuffer;
36import java.util.Collection;
37import java.util.HashSet;
38import java.util.Map;
39import java.util.Optional;
40import java.util.Set;
41import java.util.stream.Collectors;
42import jdk.tools.jlink.plugin.PluginException;
43import jdk.tools.jlink.plugin.ResourcePool;
44import jdk.tools.jlink.plugin.ResourcePoolEntry;
45import jdk.tools.jlink.plugin.ResourcePoolModule;
46
47final class ResourcePoolConfiguration {
48    private ResourcePoolConfiguration() {}
49
50    private static ModuleDescriptor descriptorOf(ResourcePoolModule mod) {
51        ModuleDescriptor md = mod.descriptor();
52
53        // drop hashes
54        ModuleDescriptor.Builder builder = ModuleDescriptor.newModule(md.name());
55        md.requires().stream()
56          .forEach(builder::requires);
57        md.exports().stream()
58          .forEach(builder::exports);
59        md.opens().stream()
60          .forEach(builder::opens);
61        md.uses().stream()
62          .forEach(builder::uses);
63        md.provides().stream()
64          .forEach(builder::provides);
65        builder.packages(md.packages());
66
67        md.version().ifPresent(builder::version);
68        md.mainClass().ifPresent(builder::mainClass);
69
70        return builder.build();
71    }
72
73    private static ModuleReference moduleReference(ModuleDescriptor desc) {
74        return new ModuleReference(desc, null) {
75            @Override
76            public ModuleReader open() {
77                throw new UnsupportedOperationException();
78            }
79        };
80    }
81
82    private static Map<String, ModuleReference> allModRefs(ResourcePool pool) {
83        return pool.moduleView().modules().
84            collect(Collectors.toMap(ResourcePoolModule::name,
85                m -> moduleReference(descriptorOf(m))));
86    }
87
88    private static void checkPackages(ResourcePool pool) {
89        // check that each resource pool module's packages()
90        // returns a set that is consistent with the module
91        // descriptor of that module.
92
93        pool.moduleView().modules().forEach(m -> {
94            ModuleDescriptor desc = m.descriptor();
95            if (!desc.packages().equals(m.packages())) {
96                throw new RuntimeException("Module " + m.name() +
97                   "'s descriptor indicates the set of packages is : " +
98                   desc.packages() + ", but module contains packages: " +
99                   m.packages());
100            }
101        });
102    }
103
104    static Configuration validate(ResourcePool pool) {
105        checkPackages(pool);
106        final Map<String, ModuleReference> nameToModRef = allModRefs(pool);
107        final Set<ModuleReference> allRefs = new HashSet<>(nameToModRef.values());
108
109        final ModuleFinder finder = new ModuleFinder() {
110            @Override
111            public Optional<ModuleReference> find(String name) {
112                return Optional.ofNullable(nameToModRef.get(name));
113            }
114
115            @Override
116            public Set<ModuleReference> findAll() {
117                return allRefs;
118            }
119        };
120
121        return Configuration.empty().resolve(
122            finder, ModuleFinder.of(), nameToModRef.keySet());
123    }
124}
125