1 /*
   2  * Copyright (c) 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 package com.sun.classanalyzer;
  25 
  26 import java.io.*;
  27 import java.util.*;
  28 
  29 /**
  30  * ClassListReader constructs modules from the .classlist and
  31  * .resources files
  32  *
  33  * @author Mandy Chung
  34  *
  35  * @see ClassListWriter
  36  */
  37 public class ClassListReader {
  38     private final ModuleBuilder builder;
  39     ClassListReader() {
  40         ModuleBuilder mb = null;
  41         try {
  42             mb = new ModuleBuilder(null, ""); // use default module builder
  43         } catch (IOException e) {
  44             // should not reach here
  45         }
  46         this.builder = mb;
  47     }
  48     ClassListReader(ModuleBuilder builder) {
  49         this.builder = builder;
  50     }
  51 
  52     Module loadModule(String name, Set<String> classes, Set<String> resources)
  53             throws IOException {
  54         Module module = Module.findModule(name);
  55         if (module == null) {
  56             module = builder.newModule(name);
  57         }
  58 
  59         for (String pathname : classes) {
  60             String cn = pathname.substring(0, pathname.length() - ".class".length())
  61                             .replace(File.separatorChar, '.');
  62             Klass k = Klass.getKlass(cn);
  63             module.addKlass(k);
  64         }
  65         for (String pathname : resources) {
  66             if (!ResourceFile.isResource(pathname)) {
  67                 throw new RuntimeException("\"" + pathname + "\" not a resource file");
  68             }
  69             ResourceFile res = new ResourceFile(pathname);
  70             module.addResource(res);
  71         }
  72         return module;
  73     }
  74 
  75     /**
  76      * Returns the list of modules constructed from the classlist
  77      * and resources list in the given directory.
  78      */
  79     public Set<Module> loadModulesFrom(File dir) throws IOException {
  80         String[] summaryFiles = dir.list(new FilenameFilter() {
  81             public boolean accept(File f, String fname) {
  82                 if (fname.endsWith(".summary")) {
  83                     return true;
  84                 }
  85                 return false;
  86             }
  87         });
  88 
  89         Set<Module> modules = new LinkedHashSet<Module>();
  90         for (String fn : summaryFiles) {
  91             String name = fn.substring(0, fn.length() - ".summary".length());
  92             Module m = loadModuleFrom(dir, name);
  93             if (m != null) {
  94                 modules.add(m);
  95             }
  96         }
  97 
  98         return modules;
  99     }
 100 
 101     private Module loadModuleFrom(File dir, String name) throws IOException {
 102         File clist = new File(dir, name + ".classlist");
 103         File rlist = new File(dir, name + ".resources");
 104         assert clist.exists() || rlist.exists();
 105 
 106         Module module = loadModule(name, readFile(clist), readFile(rlist));
 107 
 108         // read dependencies
 109         addDependencies(new File(dir, name + ".dependencies"));
 110 
 111         return module;
 112     }
 113 
 114     private static Set<String> readFile(File f) throws IOException {
 115         if (!f.exists()) {
 116             return Collections.emptySet();
 117         }
 118 
 119         // parse configuration file
 120         FileInputStream in = new FileInputStream(f);
 121         Set<String> fnames = new TreeSet<String>();
 122         try {
 123             BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 124             String line;
 125             while ((line = reader.readLine()) != null) {
 126                 line = line.trim();
 127                 if (line.isEmpty()) {
 128                     continue;
 129                 }
 130                 fnames.add(line);
 131             }
 132             return fnames;
 133         } finally {
 134             in.close();
 135         }
 136     }
 137 
 138     private static void addDependencies(File f) throws IOException {
 139         if (!f.exists()) {
 140             return;
 141         }
 142 
 143         // parse configuration file
 144         FileInputStream in = new FileInputStream(f);
 145         Set<String> fnames = new TreeSet<String>();
 146         try {
 147             BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 148             String line;
 149             while ((line = reader.readLine()) != null) {
 150                 line = line.trim();
 151                 if (line.isEmpty()) {
 152                     continue;
 153                 }
 154 
 155                 String[] ss = line.split("\\s+");
 156                 // skip [optional] if exists
 157                 int i = ss[0].startsWith("[") ? 1 : 0;
 158                 if (ss.length < (i+2) || !ss[i+1].equals("->")) {
 159                     throw new RuntimeException("Invalid dependency: " + line);
 160                 }
 161 
 162                 Klass from = Klass.getKlass(ss[i]);
 163                 Klass to = Klass.getKlass(ss[i+2]);
 164                 ResolutionInfo ri = ResolutionInfo.resolved(from, to);
 165                 from.addDep(to, ri);
 166                 to.addReferrer(from, ri);
 167             }
 168         } finally {
 169             in.close();
 170         }
 171     }
 172 }