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)
96 */
97 Optional<URI> find(String name) throws IOException;
98
99 /**
100 * Opens a resource, returning an input stream to read the resource in
101 * the module.
102 *
123 Optional<URI> ouri = find(name);
124 if (ouri.isPresent()) {
125 return Optional.of(ouri.get().toURL().openStream());
126 } else {
127 return Optional.empty();
128 }
129 }
130
131 /**
132 * Reads a resource, returning a byte buffer with the contents of the
133 * resource.
134 *
135 * The element at the returned buffer's position is the first byte of the
136 * resource, the element at the buffer's limit is the last byte of the
137 * resource. Once consumed, the {@link #release(ByteBuffer) release} method
138 * must be invoked. Failure to invoke the {@code release} method may result
139 * in a resource leak.
140 *
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
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
184 * therefore not specified.
185 *
186 * @param bb
187 * The byte buffer to release
188 *
189 * @implSpec The default implementation doesn't do anything except check
190 * if the byte buffer is null.
191 */
192 default void release(ByteBuffer bb) {
193 Objects.requireNonNull(bb);
194 }
195
196 /**
197 * Lists the contents of the module, returning a stream of elements that
198 * are the names of all resources in the module.
199 *
200 * <p> In lazy implementations then an {@code IOException} may be thrown
201 * when using the stream to list the module contents. If this occurs then
202 * the {@code IOException} will be wrapped in an {@link
203 * java.io.UncheckedIOException} and thrown from the method that caused the
204 * access to be attempted. {@code SecurityException} may also be thrown
205 * when using the stream to list the module contents and access is denied
206 * by the security manager. </p>
207 *
208 * <p> The behavior of the stream when used after the module reader is
209 * closed is implementation specific and therefore not specified. </p>
210 *
211 * @return A stream of elements that are the names of all resources
212 * in the module
213 *
214 * @throws IOException
215 * If an I/O error occurs or the module reader is closed
216 * @throws SecurityException
217 * If denied by the security manager
218 */
|
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}. A module reader may treat
52 * directories in the module content as resources (whether it does or not is
53 * module reader specific). Where the module content contains a directory
54 * that can be located as a resource then its name ends with a slash ('/'). The
55 * directory can also be located with a name that drops the trailing slash. </p>
56 *
57 * <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
58 * creation and is closed by invoking the {@link #close close} method. Failure
59 * to close a module reader may result in a resource leak. The {@code
60 * try-with-resources} statement provides a useful construct to ensure that
61 * module readers are closed. </p>
62 *
63 * <p> A {@code ModuleReader} implementation may require permissions to access
64 * resources in the module. Consequently the {@link #find find}, {@link #open
65 * open}, {@link #read read}, and {@link #list list} methods may throw {@code
66 * SecurityException} if access is denied by the security manager. </p>
67 *
68 * @implSpec Implementations of {@code ModuleReader} should take great care
69 * when translating an abstract resource name to the location of a resource in
70 * a packaged module or on the file system. Implementations are advised to
71 * treat resource names with elements such as '{@code .}, '{@code ..}',
72 * elements containing file separators, or empty elements as "not found". More
73 * generally, if the resource name is not in the stream of elements that the
74 * {@code list} method returns then the resource should be treated as "not
75 * found" to avoid inconsistencies.
76 *
77 * @see ModuleReference
78 * @since 9
79 * @spec JPMS
80 */
81
82 public interface ModuleReader extends Closeable {
83
84 /**
85 * Finds a resource, returning a URI to the resource in the module.
86 *
87 * <p> If the module reader can determine that the name locates a directory
88 * then the resulting URI will end with a slash ('/'). </p>
89 *
90 * @param name
91 * The name of the resource to open for reading
92 *
93 * @return A URI to the resource; an empty {@code Optional} if the resource
94 * is not found or a URI cannot be constructed to locate the
95 * resource
96 *
97 * @throws IOException
98 * If an I/O error occurs or the module reader is closed
99 * @throws SecurityException
100 * If denied by the security manager
101 *
102 * @see ClassLoader#getResource(String)
103 */
104 Optional<URI> find(String name) throws IOException;
105
106 /**
107 * Opens a resource, returning an input stream to read the resource in
108 * the module.
109 *
130 Optional<URI> ouri = find(name);
131 if (ouri.isPresent()) {
132 return Optional.of(ouri.get().toURL().openStream());
133 } else {
134 return Optional.empty();
135 }
136 }
137
138 /**
139 * Reads a resource, returning a byte buffer with the contents of the
140 * resource.
141 *
142 * The element at the returned buffer's position is the first byte of the
143 * resource, the element at the buffer's limit is the last byte of the
144 * resource. Once consumed, the {@link #release(ByteBuffer) release} method
145 * must be invoked. Failure to invoke the {@code release} method may result
146 * in a resource leak.
147 *
148 * @apiNote This method is intended for high-performance class loading. It
149 * is not capable (or intended) to read arbitrary large resources that
150 * could potentially be 2GB or larger. The rationale for using this method
151 * in conjunction with the {@code release} method is to allow module reader
152 * implementations manage buffers in an efficient manner.
153 *
154 * @implSpec The default implementation invokes the {@link #open(String)
155 * open} method and reads all bytes from the input stream into a byte
156 * buffer.
157 *
158 * @param name
159 * The name of the resource to read
160 *
161 * @return A byte buffer containing the contents of the resource or an
162 * empty {@code Optional} if not found
163 *
164 * @throws IOException
165 * If an I/O error occurs or the module reader is closed
166 * @throws SecurityException
167 * If denied by the security manager
168 * @throws OutOfMemoryError
169 * If the resource is larger than {@code Integer.MAX_VALUE},
170 * the maximum capacity of a byte buffer
185 /**
186 * Release a byte buffer. This method should be invoked after consuming
187 * the contents of the buffer returned by the {@code read} method.
188 * The behavior of this method when invoked to release a buffer that has
189 * already been released, or the behavior when invoked to release a buffer
190 * after a {@code ModuleReader} is closed is implementation specific and
191 * therefore not specified.
192 *
193 * @param bb
194 * The byte buffer to release
195 *
196 * @implSpec The default implementation doesn't do anything except check
197 * if the byte buffer is null.
198 */
199 default void release(ByteBuffer bb) {
200 Objects.requireNonNull(bb);
201 }
202
203 /**
204 * Lists the contents of the module, returning a stream of elements that
205 * are the names of all resources in the module. Whether the stream of
206 * elements includes names corresponding to directories in the module is
207 * module reader specific.
208 *
209 * <p> In lazy implementations then an {@code IOException} may be thrown
210 * when using the stream to list the module contents. If this occurs then
211 * the {@code IOException} will be wrapped in an {@link
212 * java.io.UncheckedIOException} and thrown from the method that caused the
213 * access to be attempted. {@code SecurityException} may also be thrown
214 * when using the stream to list the module contents and access is denied
215 * by the security manager. </p>
216 *
217 * <p> The behavior of the stream when used after the module reader is
218 * closed is implementation specific and therefore not specified. </p>
219 *
220 * @return A stream of elements that are the names of all resources
221 * in the module
222 *
223 * @throws IOException
224 * If an I/O error occurs or the module reader is closed
225 * @throws SecurityException
226 * If denied by the security manager
227 */
|