28 import java.io.Closeable;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.net.URI;
32 import java.nio.ByteBuffer;
33 import java.util.Objects;
34 import java.util.Optional;
35 import java.util.stream.Stream;
36
37
38 /**
39 * Provides access to the content of a module.
40 *
41 * <p> A module reader is intended for cases where access to the resources in a
42 * module is required, regardless of whether the module has been loaded.
43 * A framework that scans a collection of packaged modules on the file system,
44 * for example, may use a module reader to access a specific resource in each
45 * module. A module reader is also intended to be used by {@code ClassLoader}
46 * implementations that load classes and resources from modules. </p>
47 *
48 * <p> A resource in a module is identified by a name that is a
49 * '{@code /}'-separated path string. For example, module {@code java.base} may
50 * have a resource "{@code java/lang/Object.class}" that, by convention, is the
51 * class file for {@code java.lang.Object}. </p>
52 *
53 * <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
54 * creation and is closed by invoking the {@link #close close} method. Failure
55 * to close a module reader may result in a resource leak. The {@code
56 * try-with-resources} statement provides a useful construct to ensure that
57 * module readers are closed. </p>
58 *
59 * <p> A {@code ModuleReader} implementation may require permissions to access
60 * resources in the module. Consequently the {@link #find find}, {@link #open
61 * open}, {@link #read read}, and {@link #list list} methods may throw {@code
62 * SecurityException} if access is denied by the security manager. </p>
63 *
64 * @see ModuleReference
65 * @since 9
66 */
67
68 public interface ModuleReader extends Closeable {
69
70 /**
71 * Finds a resource, returning a URI to the resource in the module.
72 *
73 * @param name
74 * The name of the resource to open for reading
75 *
76 * @return A URI to the resource; an empty {@code Optional} if the resource
77 * is not found or a URI cannot be constructed to locate the
78 * resource
79 *
80 * @throws IOException
81 * If an I/O error occurs or the module reader is closed
82 * @throws SecurityException
83 * If denied by the security manager
84 *
85 * @see ClassLoader#getResource(String)
131 * @apiNote This method is intended for high-performance class loading. It
132 * is not capable (or intended) to read arbitrary large resources that
133 * could potentially be 2GB or larger. The rational for using this method
134 * in conjunction with the {@code release} method is to allow module reader
135 * implementations manage buffers in an efficient manner.
136 *
137 * @implSpec The default implementation invokes the {@link #open(String)
138 * open} method and reads all bytes from the input stream into a byte
139 * buffer.
140 *
141 * @param name
142 * The name of the resource to read
143 *
144 * @return A byte buffer containing the contents of the resource or an
145 * empty {@code Optional} if not found
146 *
147 * @throws IOException
148 * If an I/O error occurs or the module reader is closed
149 * @throws SecurityException
150 * If denied by the security manager
151 *
152 * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
153 */
154 default Optional<ByteBuffer> read(String name) throws IOException {
155 Optional<InputStream> oin = open(name);
156 if (oin.isPresent()) {
157 try (InputStream in = oin.get()) {
158 return Optional.of(ByteBuffer.wrap(in.readAllBytes()));
159 }
160 } else {
161 return Optional.empty();
162 }
163 }
164
165 /**
166 * Release a byte buffer. This method should be invoked after consuming
167 * the contents of the buffer returned by the {@code read} method.
168 * The behavior of this method when invoked to release a buffer that has
169 * already been released, or the behavior when invoked to release a buffer
170 * after a {@code ModuleReader} is closed is implementation specific and
|
28 import java.io.Closeable;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.net.URI;
32 import java.nio.ByteBuffer;
33 import java.util.Objects;
34 import java.util.Optional;
35 import java.util.stream.Stream;
36
37
38 /**
39 * Provides access to the content of a module.
40 *
41 * <p> A module reader is intended for cases where access to the resources in a
42 * module is required, regardless of whether the module has been loaded.
43 * A framework that scans a collection of packaged modules on the file system,
44 * for example, may use a module reader to access a specific resource in each
45 * module. A module reader is also intended to be used by {@code ClassLoader}
46 * implementations that load classes and resources from modules. </p>
47 *
48 * <p> A resource in a module is identified by an abstract name that is a
49 * '{@code /}'-separated path string. For example, module {@code java.base} may
50 * have a resource "{@code java/lang/Object.class}" that, by convention, is the
51 * class file for {@code java.lang.Object}. </p>
52 *
53 * <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
54 * creation and is closed by invoking the {@link #close close} method. Failure
55 * to close a module reader may result in a resource leak. The {@code
56 * try-with-resources} statement provides a useful construct to ensure that
57 * module readers are closed. </p>
58 *
59 * <p> A {@code ModuleReader} implementation may require permissions to access
60 * resources in the module. Consequently the {@link #find find}, {@link #open
61 * open}, {@link #read read}, and {@link #list list} methods may throw {@code
62 * SecurityException} if access is denied by the security manager. </p>
63 *
64 * @implSpec Implementations of {@code ModuleReader} should take great care
65 * when translating an abstract resource name to the location of a resource in
66 * a packaged module or on the file system. Implementations are advised to
67 * treat resource names with elements such as '{@code .}, '{@code ..}',
68 * elements containing file separators, or empty elements as "not found". More
69 * generally, if the resource name is not in the stream of elements that the
70 * {@code list} method returns then the resource should be treated as "not
71 * found" to avoid inconsistencies.
72 *
73 * @see ModuleReference
74 * @since 9
75 * @spec JPMS
76 */
77
78 public interface ModuleReader extends Closeable {
79
80 /**
81 * Finds a resource, returning a URI to the resource in the module.
82 *
83 * @param name
84 * The name of the resource to open for reading
85 *
86 * @return A URI to the resource; an empty {@code Optional} if the resource
87 * is not found or a URI cannot be constructed to locate the
88 * resource
89 *
90 * @throws IOException
91 * If an I/O error occurs or the module reader is closed
92 * @throws SecurityException
93 * If denied by the security manager
94 *
95 * @see ClassLoader#getResource(String)
141 * @apiNote This method is intended for high-performance class loading. It
142 * is not capable (or intended) to read arbitrary large resources that
143 * could potentially be 2GB or larger. The rational for using this method
144 * in conjunction with the {@code release} method is to allow module reader
145 * implementations manage buffers in an efficient manner.
146 *
147 * @implSpec The default implementation invokes the {@link #open(String)
148 * open} method and reads all bytes from the input stream into a byte
149 * buffer.
150 *
151 * @param name
152 * The name of the resource to read
153 *
154 * @return A byte buffer containing the contents of the resource or an
155 * empty {@code Optional} if not found
156 *
157 * @throws IOException
158 * If an I/O error occurs or the module reader is closed
159 * @throws SecurityException
160 * If denied by the security manager
161 * @throws OutOfMemoryError
162 * If the resource is larger than {@code Integer.MAX_VALUE},
163 * the maximum capacity of a byte buffer
164 *
165 * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
166 */
167 default Optional<ByteBuffer> read(String name) throws IOException {
168 Optional<InputStream> oin = open(name);
169 if (oin.isPresent()) {
170 try (InputStream in = oin.get()) {
171 return Optional.of(ByteBuffer.wrap(in.readAllBytes()));
172 }
173 } else {
174 return Optional.empty();
175 }
176 }
177
178 /**
179 * Release a byte buffer. This method should be invoked after consuming
180 * the contents of the buffer returned by the {@code read} method.
181 * The behavior of this method when invoked to release a buffer that has
182 * already been released, or the behavior when invoked to release a buffer
183 * after a {@code ModuleReader} is closed is implementation specific and
|