1 /*
   2  * Copyright (c) 2012, 2014, 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 package com.sun.tools.jdeps;
  26 
  27 import com.sun.tools.classfile.ClassFile;
  28 import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.BufferedInputStream;
  32 import java.net.URI;
  33 import java.nio.file.*;
  34 import java.nio.file.attribute.BasicFileAttributes;
  35 import java.util.*;
  36 import java.util.stream.Collectors;
  37 
  38 /**
  39  * ClassPath for Java SE and JDK
  40  */
  41 class PlatformClassPath {
  42     private static List<Archive> modules;
  43     static synchronized List<Archive> getModules(Path mpath) throws IOException {
  44         if (modules == null) {
  45             initPlatformModules(mpath);
  46         }
  47         return modules;
  48     }
  49 
  50     private static void initPlatformModules(Path mpath) throws IOException {
  51         ImageHelper helper = ImageHelper.getInstance(mpath);
  52         String fn = System.getProperty("jdeps.modules.xml");
  53         if (fn != null) {
  54             Path p = Paths.get(fn);
  55             try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
  56                 modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
  57             }
  58         } else {
  59             try (InputStream in = PlatformClassPath.class
  60                     .getResourceAsStream("resources/jdeps-modules.xml")) {
  61                 modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
  62             }
  63         }
  64         if (findModule("java.base") != null) {
  65             Profile.initProfiles(modules);
  66         }
  67     }
  68 
  69     /**
  70      * Finds the module with the given name. Returns null
  71      * if such module doesn't exist.
  72      *
  73      * @param mn module name
  74      */
  75     static Module findModule(String mn) {
  76         for (Archive a : modules) {
  77             if (Module.class.isInstance(a)) {
  78                 Module m = (Module)a;
  79                 if (mn.equals(m.name())) {
  80                     return m;
  81                 }
  82             }
  83         }
  84         return null;
  85     }
  86 
  87     /**
  88      * Returns JAR files in $java.home/lib.  This is for transition until
  89      * all components are linked into jimage.
  90      */
  91     static List<Archive> getJarFiles() throws IOException {
  92         Path home = Paths.get(System.getProperty("java.home"), "lib");
  93         return Files.find(home, 1, (Path p, BasicFileAttributes attr)
  94                 -> p.getFileName().toString().endsWith(".jar"))
  95                 .map(Archive::getInstance)
  96                 .collect(Collectors.toList());
  97     }
  98 
  99     static class ImageHelper {
 100         static ImageHelper getInstance(Path mpath) throws IOException {
 101             if (mpath != null) {
 102                 return new ImageHelper(mpath);
 103             }
 104             Path home = Paths.get(System.getProperty("java.home"));
 105             Path mlib = home.resolve("lib").resolve("modules");
 106             if (Files.isDirectory(mlib)) {
 107                 // jimage
 108                 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
 109                 return new ImageHelper(fs, fs.getPath("/"));
 110             } else {
 111                 // exploded modules
 112                 mlib = home.resolve("modules");
 113                 if (!Files.isDirectory(mlib)) {
 114                     throw new InternalError(home + " not a modular image");
 115                 }
 116                 return new ImageHelper(mlib);
 117             }
 118         }
 119 
 120         private final FileSystem fs;
 121         private final Path mpath;
 122 
 123         ImageHelper(Path path) throws IOException {
 124             this(FileSystems.getDefault(), path);
 125         }
 126 
 127         ImageHelper(FileSystem fs, Path path) throws IOException {
 128             this.fs = fs;
 129             this.mpath = path;
 130         }
 131 
 132         /**
 133          * Returns a ModuleClassReader that only reads classes for the given modulename.
 134          */
 135         public ModuleClassReader getModuleClassReader(String modulename)
 136             throws IOException
 137         {
 138             Path mp = mpath.resolve(modulename);
 139             if (Files.exists(mp) && Files.isDirectory(mp)) {
 140                 return new ModuleClassReader(fs, modulename, mp);
 141             } else {
 142                 // aggregator module or os-specific module in jdeps-modules.xml
 143                 // mdir not exist
 144                 return new NonExistModuleReader(fs, modulename, mp);
 145             }
 146         }
 147 
 148         static class NonExistModuleReader extends ModuleClassReader {
 149             private final List<ClassFile> classes = Collections.emptyList();
 150 
 151             private NonExistModuleReader(FileSystem fs, String mn, Path mpath)
 152                 throws IOException
 153             {
 154                 super(fs, mn, mpath);
 155             }
 156 
 157             public ClassFile getClassFile(String name) throws IOException {
 158                 return null;
 159             }
 160 
 161             public Iterable<ClassFile> getClassFiles() throws IOException {
 162                 return classes;
 163             }
 164 
 165             public Set<String> packages() {
 166                 return Collections.emptySet();
 167             }
 168         }
 169     }
 170 }