1 /*
   2  * Copyright (c) 2015, 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 
  26 package java.lang.module;
  27 
  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.Optional;
  34 
  35 
  36 /**
  37  * Provides access to the content of a module.
  38  *
  39  * <p> A module reader is intended for cases where access to the resources in a
  40  * module is required, regardless of whether the module has been loaded.
  41  * A framework that scans a collection of packaged modules on the file system,
  42  * for example, may use a module reader to access a specific resource in each
  43  * module. A module reader is also intended to be used by {@code ClassLoader}
  44  * implementations that load classes and resources from modules. </p>
  45  *
  46  * <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
  47  * creation and is closed by invoking the {@link #close close} method.  Failure
  48  * to close a module reader may result in a resource leak.  The {@code
  49  * try-with-resources} statement provides a useful construct to ensure that
  50  * module readers are closed. </p>
  51  *
  52  * <p> A {@code ModuleReader} implementation may require permissions to access
  53  * resources in the module. Consequently the {@link #find find}, {@link #open
  54  * open} and {@link #read read} methods may throw {@code SecurityException} if
  55  * access is denied by the security manager. </p>
  56  *
  57  * @see ModuleReference
  58  * @since 9
  59  */
  60 
  61 public interface ModuleReader extends Closeable {
  62 
  63     /**
  64      * Finds a resource, returning a URI to the resource in the module.
  65      *
  66      * @param  name
  67      *         The name of the resource to open for reading
  68      *
  69      * @return A URI to the resource; an empty {@code Optional} if the resource
  70      *         is not found or a URI cannot be constructed to locate the
  71      *         resource
  72      *
  73      * @throws IOException
  74      *         If an I/O error occurs or the module reader is closed
  75      * @throws SecurityException
  76      *         If denied by the security manager
  77      *
  78      * @see ClassLoader#getResource(String)
  79      */
  80     Optional<URI> find(String name) throws IOException;
  81 
  82     /**
  83      * Opens a resource, returning an input stream to read the resource in
  84      * the module.
  85      *
  86      * @implSpec The default implementation invokes the {@link #find(String)
  87      * find} method to get a URI to the resource. If found, then it attempts
  88      * to construct a {@link java.net.URL URL} and open a connection to the
  89      * resource.
  90      *
  91      * @param  name
  92      *         The name of the resource to open for reading
  93      *
  94      * @return An input stream to read the resource or an empty
  95      *         {@code Optional} if not found
  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     default Optional<InputStream> open(String name) throws IOException {
 103         Optional<URI> ouri = find(name);
 104         if (ouri.isPresent()) {
 105             return Optional.of(ouri.getWhenPresent().toURL().openStream());
 106         } else {
 107             return Optional.empty();
 108         }
 109     }
 110 
 111     /**
 112      * Reads a resource, returning a byte buffer with the contents of the
 113      * resource.
 114      *
 115      * The element at the returned buffer's position is the first byte of the
 116      * resource, the element at the buffer's limit is the last byte of the
 117      * resource. Once consumed, the {@link #release(ByteBuffer) release} method
 118      * must be invoked. Failure to invoke the {@code release} method may result
 119      * in a resource leak.
 120      *
 121      * @apiNote This method is intended for high-performance class loading. It
 122      * is not capable (or intended) to read arbitrary large resources that
 123      * could potentially be 2GB or larger. The rational for using this method
 124      * in conjunction with the {@code release} method is to allow module reader
 125      * implementations manage buffers in an efficient manner.
 126      *
 127      * @implSpec The default implementation invokes the {@link #open(String)
 128      * open} method and reads all bytes from the input stream into a byte
 129      * buffer.
 130      *
 131      * @param  name
 132      *         The name of the resource to read
 133      *
 134      * @return A byte buffer containing the contents of the resource or an
 135      *         empty {@code Optional} if not found
 136      *
 137      * @throws IOException
 138      *         If an I/O error occurs or the module reader is closed
 139      * @throws SecurityException
 140      *         If denied by the security manager
 141      *
 142      * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
 143      */
 144     default Optional<ByteBuffer> read(String name) throws IOException {
 145         Optional<InputStream> in = open(name);
 146         if (in.isPresent()) {
 147             byte[] bytes = in.getWhenPresent().readAllBytes();
 148             return Optional.of(ByteBuffer.wrap(bytes));
 149         } else {
 150             return Optional.empty();
 151         }
 152     }
 153 
 154     /**
 155      * Release a byte buffer. This method should be invoked after consuming
 156      * the contents of the buffer returned by the {@code read} method.
 157      * The behavior of this method when invoked to release a buffer that has
 158      * already been released, or the behavior when invoked to release a buffer
 159      * after a {@code ModuleReader} is closed is implementation specific and
 160      * therefore not specified.
 161      *
 162      * @param  bb
 163      *         The byte buffer to release
 164      *
 165      * @implSpec The default implementation does nothing.
 166      */
 167     default void release(ByteBuffer bb) { }
 168 
 169     /**
 170      * Closes the module reader. Once closed then subsequent calls to locate or
 171      * read a resource will fail by returning {@code Optional.empty()} or
 172      * throwing {@code IOException}.
 173      *
 174      * <p> A module reader is not required to be asynchronously closeable. If a
 175      * thread is reading a resource and another thread invokes the close method,
 176      * then the second thread may block until the read operation is complete.
 177      *
 178      * <p> The behavior of {@code InputStream}s obtained using the {@link
 179      * #open(String) open} method and used after the module reader is closed
 180      * is implementation specific and therefore not specified.
 181      */
 182     @Override
 183     void close() throws IOException;
 184 
 185 }