-
Notifications
You must be signed in to change notification settings - Fork 668
/
ModuleReader.java
226 lines (217 loc) · 10.2 KB
/
ModuleReader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
* Copyright (c) 2015, 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 java.lang.module;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
/**
* Provides access to the content of a module.
*
* <p> A module reader is intended for cases where access to the resources in a
* module is required, regardless of whether the module has been loaded.
* A framework that scans a collection of packaged modules on the file system,
* for example, may use a module reader to access a specific resource in each
* module. A module reader is also intended to be used by {@code ClassLoader}
* implementations that load classes and resources from modules. </p>
*
* <p> A resource in a module is identified by an abstract name that is a
* '{@code /}'-separated path string. For example, module {@code java.base} may
* have a resource "{@code java/lang/Object.class}" that, by convention, is the
* class file for {@code java.lang.Object}. A module reader may treat
* directories in the module content as resources (whether it does or not is
* module reader specific). Where the module content contains a directory
* that can be located as a resource then its name ends with a slash ('/'). The
* directory can also be located with a name that drops the trailing slash. </p>
*
* <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
* creation and is closed by invoking the {@link #close close} method. Failure
* to close a module reader may result in a resource leak. The {@code
* try-with-resources} statement provides a useful construct to ensure that
* module readers are closed. </p>
*
* <p> A {@code ModuleReader} implementation may require permissions to access
* resources in the module. Consequently the {@link #find find}, {@link #open
* open}, {@link #read read}, and {@link #list list} methods may throw {@code
* SecurityException} if access is denied by the security manager. </p>
*
* @implSpec Implementations of {@code ModuleReader} should take great care
* when translating an abstract resource name to the location of a resource in
* a packaged module or on the file system. Implementations are advised to
* treat resource names with elements such as '{@code .}, '{@code ..}',
* elements containing file separators, or empty elements as "not found". More
* generally, if the resource name is not in the stream of elements that the
* {@code list} method returns then the resource should be treated as "not
* found" to avoid inconsistencies.
* @spec JPMS
* @see ModuleReference
* @since 9
*/
// 模块阅读器,用来读取模块及模块内的资源
public interface ModuleReader extends Closeable {
/**
* Finds a resource, returning a URI to the resource in the module.
*
* <p> If the module reader can determine that the name locates a directory
* then the resulting URI will end with a slash ('/'). </p>
*
* @param name The name of the resource to open for reading
*
* @return A URI to the resource; an empty {@code Optional} if the resource
* is not found or a URI cannot be constructed to locate the
* resource
*
* @throws IOException If an I/O error occurs or the module reader is closed
* @throws SecurityException If denied by the security manager
* @see ClassLoader#getResource(String)
*/
// 返回指定资源在模块中的位置
Optional<URI> find(String name) throws IOException;
/**
* Lists the contents of the module, returning a stream of elements that
* are the names of all resources in the module. Whether the stream of
* elements includes names corresponding to directories in the module is
* module reader specific.
*
* <p> In lazy implementations then an {@code IOException} may be thrown
* when using the stream to list the module contents. If this occurs then
* the {@code IOException} will be wrapped in an {@link
* java.io.UncheckedIOException} and thrown from the method that caused the
* access to be attempted. {@code SecurityException} may also be thrown
* when using the stream to list the module contents and access is denied
* by the security manager. </p>
*
* <p> The behavior of the stream when used after the module reader is
* closed is implementation specific and therefore not specified. </p>
*
* @return A stream of elements that are the names of all resources
* in the module
*
* @throws IOException If an I/O error occurs or the module reader is closed
* @throws SecurityException If denied by the security manager
*/
// 列出当前模块内的资源
Stream<String> list() throws IOException;
/**
* Closes the module reader. Once closed then subsequent calls to locate or
* read a resource will fail by throwing {@code IOException}.
*
* <p> A module reader is not required to be asynchronously closeable. If a
* thread is reading a resource and another thread invokes the close method,
* then the second thread may block until the read operation is complete. </p>
*/
// 关闭模块阅读器
@Override
void close() throws IOException;
/**
* Opens a resource, returning an input stream to read the resource in
* the module.
*
* <p> The behavior of the input stream when used after the module reader
* is closed is implementation specific and therefore not specified. </p>
*
* @param name The name of the resource to open for reading
*
* @return An input stream to read the resource or an empty
* {@code Optional} if not found
*
* @throws IOException If an I/O error occurs or the module reader is closed
* @throws SecurityException If denied by the security manager
* @implSpec The default implementation invokes the {@link #find(String)
* find} method to get a URI to the resource. If found, then it attempts
* to construct a {@link java.net.URL URL} and open a connection to the
* resource.
*/
// 打开模块中指定资源的输入流以便外界读取
default Optional<InputStream> open(String name) throws IOException {
Optional<URI> ouri = find(name);
if(ouri.isPresent()) {
return Optional.of(ouri.get().toURL().openStream());
} else {
return Optional.empty();
}
}
/**
* Reads a resource, returning a byte buffer with the contents of the
* resource.
*
* The element at the returned buffer's position is the first byte of the
* resource, the element at the buffer's limit is the last byte of the
* resource. Once consumed, the {@link #release(ByteBuffer) release} method
* must be invoked. Failure to invoke the {@code release} method may result
* in a resource leak.
*
* @param name The name of the resource to read
*
* @return A byte buffer containing the contents of the resource or an
* empty {@code Optional} if not found
*
* @throws IOException If an I/O error occurs or the module reader is closed
* @throws SecurityException If denied by the security manager
* @throws OutOfMemoryError If the resource is larger than {@code Integer.MAX_VALUE},
* the maximum capacity of a byte buffer
* @apiNote This method is intended for high-performance class loading. It
* is not capable (or intended) to read arbitrary large resources that
* could potentially be 2GB or larger. The rationale for using this method
* in conjunction with the {@code release} method is to allow module reader
* implementations manage buffers in an efficient manner.
* @implSpec The default implementation invokes the {@link #open(String)
* open} method and reads all bytes from the input stream into a byte
* buffer.
* 参见 ClassLoader#defineClass(String, ByteBuffer, ProtectionDomain)
*/
// 将模块中的指定资源存入缓冲区以便外界读取
default Optional<ByteBuffer> read(String name) throws IOException {
Optional<InputStream> oin = open(name);
if(oin.isPresent()) {
try(InputStream in = oin.get()) {
return Optional.of(ByteBuffer.wrap(in.readAllBytes()));
}
} else {
return Optional.empty();
}
}
/**
* Release a byte buffer. This method should be invoked after consuming
* the contents of the buffer returned by the {@code read} method.
* The behavior of this method when invoked to release a buffer that has
* already been released, or the behavior when invoked to release a buffer
* after a {@code ModuleReader} is closed is implementation specific and
* therefore not specified.
*
* @param bb The byte buffer to release
*
* @implSpec The default implementation doesn't do anything except check
* if the byte buffer is null.
*/
// 释放缓冲区
default void release(ByteBuffer bb) {
Objects.requireNonNull(bb);
}
}