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