ModuleReferenceImpl.java revision 16909:085c764a3e5b
1193323Sed/*
2193323Sed * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3193323Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4193323Sed *
5193323Sed * This code is free software; you can redistribute it and/or modify it
6193323Sed * under the terms of the GNU General Public License version 2 only, as
7193323Sed * published by the Free Software Foundation.  Oracle designates this
8193323Sed * particular file as subject to the "Classpath" exception as provided
9193323Sed * by Oracle in the LICENSE file that accompanied this code.
10193323Sed *
11193323Sed * This code is distributed in the hope that it will be useful, but WITHOUT
12193323Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13193323Sed * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14193323Sed * version 2 for more details (a copy is included in the LICENSE file that
15193323Sed * accompanied this code).
16234353Sdim *
17249423Sdim * You should have received a copy of the GNU General Public License version
18249423Sdim * 2 along with this work; if not, write to the Free Software Foundation,
19249423Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20263508Sdim *
21193323Sed * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22249423Sdim * or visit www.oracle.com if you need additional information or have any
23193323Sed * questions.
24193323Sed */
25193323Sed
26206274Srdivackypackage jdk.internal.module;
27193323Sed
28193323Sedimport java.io.IOException;
29249423Sdimimport java.io.UncheckedIOException;
30249423Sdimimport java.lang.module.ModuleDescriptor;
31249423Sdimimport java.lang.module.ModuleReader;
32203954Srdivackyimport java.lang.module.ModuleReference;
33203954Srdivackyimport java.net.URI;
34202375Srdivackyimport java.util.Objects;
35249423Sdimimport java.util.function.Supplier;
36249423Sdim
37249423Sdim/**
38195340Sed * A ModuleReference implementation that supports referencing a module that
39193323Sed * is patched and/or can be tied to other modules by means of hashes.
40193323Sed */
41193323Sed
42203954Srdivackypublic class ModuleReferenceImpl extends ModuleReference {
43193323Sed
44203954Srdivacky    private final Supplier<ModuleReader> readerSupplier;
45193323Sed
46198090Srdivacky    // non-null if the module is patched
47198090Srdivacky    private final ModulePatcher patcher;
48198090Srdivacky
49193323Sed    // ModuleTarget if the module is OS/architecture specific
50193323Sed    private final ModuleTarget target;
51193323Sed
52193323Sed    // the hashes of other modules recorded in this module
53207618Srdivacky    private final ModuleHashes recordedHashes;
54218893Sdim
55218893Sdim    // the function that computes the hash of this module
56218893Sdim    private final ModuleHashes.HashSupplier hasher;
57193323Sed
58263508Sdim    // ModuleResolution flags
59193323Sed    private final ModuleResolution moduleResolution;
60193323Sed
61263508Sdim    // cached hash of this module to avoid needing to compute it many times
62193323Sed    private byte[] cachedHash;
63263508Sdim
64263508Sdim    /**
65263508Sdim     * Constructs a new instance of this class.
66249423Sdim     */
67249423Sdim    ModuleReferenceImpl(ModuleDescriptor descriptor,
68243830Sdim                        URI location,
69249423Sdim                        Supplier<ModuleReader> readerSupplier,
70263508Sdim                        ModulePatcher patcher,
71263508Sdim                        ModuleTarget target,
72223017Sdim                        ModuleHashes recordedHashes,
73263508Sdim                        ModuleHashes.HashSupplier hasher,
74223017Sdim                        ModuleResolution moduleResolution)
75249423Sdim    {
76249423Sdim        super(descriptor, Objects.requireNonNull(location));
77223017Sdim        this.readerSupplier = readerSupplier;
78223017Sdim        this.patcher = patcher;
79263508Sdim        this.target = target;
80203954Srdivacky        this.recordedHashes = recordedHashes;
81203954Srdivacky        this.hasher = hasher;
82193323Sed        this.moduleResolution = moduleResolution;
83193323Sed    }
84193323Sed
85249423Sdim    @Override
86249423Sdim    public ModuleReader open() throws IOException {
87249423Sdim        try {
88249423Sdim            return readerSupplier.get();
89249423Sdim        } catch (UncheckedIOException e) {
90249423Sdim            throw e.getCause();
91249423Sdim        }
92193323Sed    }
93249423Sdim
94193323Sed    /**
95195098Sed     * Returns {@code true} if this module has been patched via --patch-module.
96195098Sed     */
97195098Sed    public boolean isPatched() {
98195098Sed        return (patcher != null);
99193323Sed    }
100195098Sed
101195098Sed    /**
102193323Sed     * Returns the ModuleTarget or {@code null} if the no target platform.
103239462Sdim     */
104239462Sdim    public ModuleTarget moduleTarget() {
105239462Sdim        return target;
106239462Sdim    }
107239462Sdim
108239462Sdim    /**
109239462Sdim     * Returns the hashes recorded in this module or {@code null} if there
110203954Srdivacky     * are no hashes recorded.
111203954Srdivacky     */
112203954Srdivacky    public ModuleHashes recordedHashes() {
113203954Srdivacky        return recordedHashes;
114193323Sed    }
115193323Sed
116203954Srdivacky    /**
117203954Srdivacky     * Returns the supplier that computes the hash of this module.
118203954Srdivacky     */
119203954Srdivacky    ModuleHashes.HashSupplier hasher() {
120203954Srdivacky        return hasher;
121239462Sdim    }
122205407Srdivacky
123203954Srdivacky    /**
124203954Srdivacky     * Returns the ModuleResolution flags.
125203954Srdivacky     */
126193323Sed    public ModuleResolution moduleResolution() {
127193323Sed        return moduleResolution;
128193323Sed    }
129193323Sed
130193323Sed    /**
131193323Sed     * Computes the hash of this module. Returns {@code null} if the hash
132193323Sed     * cannot be computed.
133193323Sed     *
134193323Sed     * @throws java.io.UncheckedIOException if an I/O error occurs
135193323Sed     */
136193323Sed    public byte[] computeHash(String algorithm) {
137193323Sed        byte[] result = cachedHash;
138193323Sed        if (result != null)
139239462Sdim            return result;
140193323Sed        if (hasher == null)
141193323Sed            return null;
142193323Sed        cachedHash = result = hasher.generate(algorithm);
143193323Sed        return result;
144239462Sdim    }
145193323Sed
146193323Sed    @Override
147193323Sed    public int hashCode() {
148193323Sed        int hc = hash;
149193323Sed        if (hc == 0) {
150193323Sed            hc = descriptor().hashCode();
151193323Sed            hc = 43 * hc + Objects.hashCode(location());
152193323Sed            hc = 43 * hc + Objects.hashCode(patcher);
153239462Sdim            if (hc == 0)
154193323Sed                hc = -1;
155193323Sed            hash = hc;
156193323Sed        }
157193323Sed        return hc;
158193323Sed    }
159193323Sed
160193323Sed    private int hash;
161239462Sdim
162193323Sed    @Override
163193323Sed    public boolean equals(Object ob) {
164193323Sed        if (!(ob instanceof ModuleReferenceImpl))
165193323Sed            return false;
166193323Sed        ModuleReferenceImpl that = (ModuleReferenceImpl)ob;
167193323Sed
168193323Sed        // assume module content, recorded hashes, etc. are the same
169193323Sed        // when the modules have equal module descriptors, are at the
170193323Sed        // same location, and are patched by the same patcher.
171193323Sed        return Objects.equals(this.descriptor(), that.descriptor())
172193323Sed                && Objects.equals(this.location(), that.location())
173224145Sdim                && Objects.equals(this.patcher, that.patcher);
174193323Sed    }
175193323Sed
176249423Sdim    @Override
177193323Sed    public String toString() {
178193323Sed        StringBuilder sb = new StringBuilder();
179193323Sed        sb.append("[module ");
180203954Srdivacky        sb.append(descriptor().name());
181193323Sed        sb.append(", location=");
182193323Sed        sb.append(location().orElseThrow(() -> new InternalError()));
183193323Sed        if (isPatched()) sb.append(" (patched)");
184193323Sed        sb.append("]");
185193323Sed        return sb.toString();
186193323Sed    }
187193323Sed
188193323Sed}
189193323Sed