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