1 /*
   2  * Copyright (c) 2009, 2010, 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 org.openjdk.jigsaw;
  27 
  28 import java.lang.module.*;
  29 import java.io.*;
  30 import java.net.URI;
  31 import java.security.CodeSigner;
  32 import java.security.SignatureException;
  33 import java.util.*;
  34 
  35 import static org.openjdk.jigsaw.Trace.*;
  36 
  37 
  38 /**
  39  * The abstract base class for module libraries
  40  *
  41  * @see SimpleLibrary
  42  */
  43 
  44 public abstract class Library
  45     extends LocatableCatalog
  46 {
  47 
  48     // ## Should use new-fangled Paths instead of old-fangled Files
  49 
  50     private static File systemLibraryPath = null;
  51 
  52     /**
  53      * <p> The system module library's path </p>
  54      */
  55     public static synchronized File systemLibraryPath() {
  56         if (systemLibraryPath == null) {
  57             systemLibraryPath
  58                 = new File(new File(System.getProperty("java.home"),
  59                                     "lib"),
  60                            "modules");
  61         }
  62         return systemLibraryPath;
  63     }
  64 
  65     /**
  66      * <p> Open the system module library. </p>
  67      */
  68     public static Library openSystemLibrary()
  69         throws IOException
  70     {
  71         return SimpleLibrary.open(systemLibraryPath());
  72     }
  73 
  74     private static final JigsawModuleSystem jms
  75         = JigsawModuleSystem.instance();
  76 
  77     protected Library() { }
  78 
  79     /**
  80      * <p> Return the major version of this library. </p>
  81      */
  82     public abstract int majorVersion();
  83 
  84     /**
  85      * <p> Return the minor version of this library. </p>
  86      */
  87     public abstract int minorVersion();
  88 
  89     public abstract Library parent();
  90 
  91     /**
  92      * <p> Read the module-info class bytes for the module with the given
  93      * identifier, from this library only. </p>
  94      *
  95      * @param   mid
  96      *          The identifier of the module being sought
  97      *
  98      * @return  A byte array containing the content of the named module's
  99      *          <tt>module-info.class</tt> file, or {@code null} if no such
 100      *          module is present in this library
 101      *
 102      * @throws  IllegalArgumentException
 103      *          If the given module identifier is not a Jigsaw module
 104      *          identifier
 105      */
 106     protected abstract byte[] readLocalModuleInfoBytes(ModuleId mid)
 107         throws IOException;
 108 
 109     /**
 110      * <p> Read the raw module-info class bytes of the specified module, from
 111      * this library or a parent library. </p>
 112      */
 113     public byte[] readModuleInfoBytes(ModuleId mid)
 114         throws IOException
 115     {
 116         Library lib = this;
 117         while (lib != null) {
 118             byte[] bs = lib.readLocalModuleInfoBytes(mid);
 119             if (bs != null)
 120                 return bs;
 121             lib = lib.parent();
 122         }
 123         return null;
 124     }
 125 
 126     public ModuleInfo readLocalModuleInfo(ModuleId mid)
 127         throws IOException
 128     {
 129         byte[] bs = readLocalModuleInfoBytes(mid);
 130         if (bs != null)
 131             return jms.parseModuleInfo(bs);
 132         return null;
 133     }
 134 
 135     /**
 136      * Read the class bytes of the given class within the given module in this
 137      * library.
 138      *
 139      * @param   mid
 140      *          The module's identifier
 141      *
 142      * @param   className
 143      *          The binary name of the requested class
 144      *
 145      * @return  The requested bytes, or {@code null} if the named module does
 146      *          not define such a class
 147      *
 148      * @throws  IllegalArgumentException
 149      *          If the given module identifier is not a Jigsaw module
 150      *          identifier
 151      */
 152     public abstract byte[] readLocalClass(ModuleId mid, String className)
 153         throws IOException;
 154 
 155     /**
 156      * Read the class bytes of the given class within the given module, in this
 157      * library or in a parent library.
 158      *
 159      * @param   mid
 160      *          The module's identifier
 161      *
 162      * @param   className
 163      *          The binary name of the requested class
 164      *
 165      * @return  The requested bytes, or {@code null} if the named module does
 166      *          not define such a class
 167      *
 168      * @throws  IllegalArgumentException
 169      *          If the given module identifier is not a Jigsaw module
 170      *          identifier
 171      */
 172     public byte[] readClass(ModuleId mid, String className)
 173         throws IOException
 174     {
 175         for (Library l = this; l != null; l = l.parent()) {
 176             byte[] bs = l.readLocalClass(mid, className);
 177             if (bs != null)
 178                 return bs;
 179         }
 180         return null;
 181     }
 182 
 183     /**
 184      * Return a list of the public and, optionally, all other classes defined
 185      * by the named module in this library.
 186      *
 187      * @param   mid
 188      *          The module's identifier
 189      *
 190      * @param   all
 191      *          Whether non-public classes should be included
 192      *
 193      * @return  The requested class names, or null if the named module does not
 194      *          exist in this library
 195      *
 196      * @throws  IllegalArgumentException
 197      *          If the given module identifier is not a Jigsaw module
 198      *          identifier
 199      */
 200     public abstract List<String> listLocalClasses(ModuleId mid, boolean all)
 201         throws IOException;
 202 
 203     /**
 204      * Read the stored {@link Configuration} of the named module.
 205      *
 206      * @param   mid
 207      *          The module's identifier
 208      *
 209      * @return  The named module's {@link Configuration}, or null if the named
 210      *          module does not exist in this library
 211      *
 212      * @throws  IllegalArgumentException
 213      *          If the given module identifier is not a Jigsaw module
 214      *          identifier
 215      */
 216     public abstract Configuration<Context> readConfiguration(ModuleId mid)
 217         throws IOException;
 218 
 219     /**
 220      * <p> Install one or more modules into this library. </p>
 221      *
 222      * <p> The modules are first copied from the locations specified in the
 223      * given manifests, and then the configurations of any affected root
 224      * modules in the library are recomputed. </p>
 225      *
 226      * @param   mfs
 227      *          The manifests describing the contents of the modules to be
 228      *          installed
 229      */
 230     public abstract void installFromManifests(Collection<Manifest> mfs)
 231         throws ConfigurationException, IOException;
 232 
 233     /**
 234      * <p> Install one or more module files into this library. </p>
 235      *
 236      * @param   mfs
 237      *          The module files to be installed
 238      *
 239      * @param   verifySignature
 240      *          Perform signature verification of signed module files, if true.
 241      *          Otherwise treat the module files as unsigned.
 242      *
 243      * @throws  ConfigurationException
 244      *          If a valid configuration cannot be computed
 245      *
 246      * @throws  IOException
 247      *          If an I/O error occurs while accessing the module library
 248      *
 249      * @throws  SignatureException
 250      *          If an error occurs while validating the signature
 251      *
 252      * @throws  ModuleFileParserException
 253      *          If there is an error processing one the underlying module files
 254      */
 255     public abstract void install(Collection<File> mfs, boolean verifySignature)
 256         throws ConfigurationException, IOException, SignatureException;
 257 
 258     /**
 259      * <p> Resolve the given collection of {@linkplain
 260      * java.lang.module.ModuleIdQuery module-id queries} against this
 261      * library. </p>
 262      *
 263      * @param   midqs
 264      *          A non-empty collection of {@link java.lang.module.ModuleIdQuery
 265      *          ModuleIdQuery objects}
 266      *
 267      * @throws  ConfigurationException
 268      *          If a valid {@link Resolution} cannot be computed
 269      *
 270      * @throws  IOException
 271      *          If an I/O error occurs while accessing the module library
 272      */
 273     public abstract Resolution resolve(Collection<ModuleIdQuery> midqs)
 274         throws ConfigurationException, IOException;
 275 
 276     /**
 277      * <p> Install any modules required by the given {@linkplain Resolution
 278      * resolution}, and configure all of its root modules. </p>
 279      *
 280      * @param   res
 281      *          A {@link Resolution} previously computed by the
 282      *          {@link Library#resolve resolve} method
 283      *
 284      * @param   verifySignature
 285      *          Perform signature verification, if true
 286      *
 287      * @throws  ConfigurationException
 288      *          If a valid configuration cannot be computed
 289      *
 290      * @throws  IOException
 291      *          If an I/O error occurs while accessing the module library
 292      *
 293      * @throws  SignatureException
 294      *          If an error occurs while validating the signature
 295      *
 296      * @throws  ModuleFileParserException
 297      *          If there is an error processing the underlying module file
 298      *          required by the given resolution
 299      */
 300     public abstract void install(Resolution res, boolean verifySignature)
 301         throws ConfigurationException, IOException, SignatureException;
 302 
 303     /**
 304      * Remove one or more modules from this library.
 305      *
 306      * @param   mids
 307      *          The module identifiers
 308      *
 309      * @param   dry
 310      *          Perform a dry run (no changes to the module library), if true.
 311      *          Otherwise the modules may be removed.
 312      *
 313      * @throws  ConfigurationException
 314      *          If the configuration of any root modules in the library
 315      *          require any of the given modules
 316      *
 317      * @throws  IOException
 318      *          If an I/O error occurs while accessing the module library, or
 319      *          removing any of the module's files. Any such exceptions are
 320      *          caught internally. If only one is caught, then it is re-thrown.
 321      *          If more than one exception is caught, then the second and
 322      *          following exceptions are added as suppressed exceptions of the
 323      *          first one caught, which is then re-thrown.
 324      */
 325     public abstract void remove(List<ModuleId> mids, boolean dry)
 326         throws ConfigurationException, IOException;
 327 
 328     /**
 329      * Forcibly remove one or more modules from this library.
 330      *
 331      * <p> No regard is given to configuration of any root modules in the
 332      * library that may require any of the given modules. </p>
 333      *
 334      * @param   mids
 335      *          The module identifiers
 336      *
 337      * @throws  IOException
 338      *          If an I/O error occurs while accessing the module library, or
 339      *          removing any of the module's files. Any such exceptions are
 340      *          caught internally. If only one is caught, then it is re-thrown.
 341      *          If more than one exception is caught, then the second and
 342      *          following exceptions are added as suppressed exceptions of the
 343      *          first one caught, which is then re-thrown.
 344      */
 345     public abstract void removeForcibly(List<ModuleId> mids)
 346         throws IOException;
 347 
 348     /**
 349      * Find a resource within the given module in this library.
 350      *
 351      * @param   mid
 352      *          The module's identifier
 353      *
 354      * @param   rn
 355      *          The name of the requested resource, in the usual
 356      *          slash-separated form
 357      *
 358      * @return  A {@code File} object naming the location of the resource,
 359      *          or {@code null} if the named module does not define that
 360      *          resource
 361      */
 362     // ## Returning file or jar URIs here is EVIL!
 363     // ## Define a jmod: hierarchical URI scheme?
 364     public abstract URI findLocalResource(ModuleId mid, String rn)
 365         throws IOException;
 366 
 367     /**
 368      * Find a native library within the given module in this library.
 369      *
 370      * @param   mid
 371      *          The module's identifier
 372      *
 373      * @param   name
 374      *          The name of the requested library, in platform-specific
 375      *          form, <i>i.e.</i>, that returned by the {@link
 376      *          java.lang.System#mapLibraryName System.mapLibraryName} method
 377      *
 378      * @return  A {@code File} object naming the location of the native library,
 379      *          or {@code null} if the named module does not contain such a
 380      *          library
 381      */
 382     public abstract File findLocalNativeLibrary(ModuleId mid, String name)
 383         throws IOException;
 384 
 385     /**
 386      * <p> Return a file path to the given module's classes. </p>
 387      *
 388      * @param   mid
 389      *          The module's identifier
 390      *
 391      * @return  A {@code File} object naming the location of the module's
 392      *          classes, or {@code null} if the named module does not exist
 393      */
 394     public abstract File classPath(ModuleId mid)
 395         throws IOException;
 396 
 397 
 398     /**
 399      * <p> Return the list of {@linkplain RemoteRepository remote repositories}
 400      * associated with this library </p>
 401      */
 402     public abstract RemoteRepositoryList repositoryList() throws IOException;
 403 
 404     /**
 405      * <p> Read the code signers of the module with the given identifier, from
 406      * this library only. </p>
 407      *
 408      * @param   mid
 409      *          The identifier of the module being sought
 410      *
 411      * @return  An array of CodeSigners, or {@code null} if the module is not
 412      *          signed
 413      *
 414      * @throws  IllegalArgumentException
 415      *          If the given module identifier is not a Jigsaw module
 416      *          identifier
 417      *
 418      * @throws  IOException
 419      *          If an I/O error occurs while accessing the module library
 420      */
 421     public abstract CodeSigner[] readLocalCodeSigners(ModuleId mid)
 422         throws IOException;
 423 
 424 }