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.File;
  27 import java.io.PrintWriter;
  28 import java.io.IOException;
  29 import java.util.*;
  30 
  31 import com.sun.classanalyzer.AnnotatedDependency.*;
  32 import com.sun.classanalyzer.Module.*;
  33 
  34 /**
  35  * ClassListWriter outputs the following files of a given module:
  36  * <module>.classlist,
  37  * <module>.resources,
  38  * <module>.summary,
  39  * <module>.dependencies.
  40  *
  41  * @author Mandy Chung
  42  */
  43 public class ClassListWriter {
  44     private final Module module;
  45     private final File dir;
  46     ClassListWriter(File dir, Module m) {
  47         this.module = m;
  48         this.dir = dir;
  49     }
  50 
  51     void printClassList() throws IOException {
  52         if (module.classes().isEmpty()) {
  53             return;
  54         }
  55 
  56         PrintWriter writer = new PrintWriter(Files.resolve(dir, module.name(), "classlist"));
  57         try {
  58             for (Klass c : module.classes()) {
  59                 writer.format("%s\n", c.getClassFilePathname());
  60             }
  61         } finally {
  62             writer.close();
  63         }
  64 
  65     }
  66 
  67     void printResourceList() throws IOException {
  68         // no file created if the module doesn't have any resource file
  69         if (module.resources().isEmpty()) {
  70             return;
  71         }
  72 
  73         PrintWriter writer = new PrintWriter(Files.resolve(dir, module.name(), "resources"));
  74         try {
  75             for (ResourceFile res : module.resources()) {
  76                 writer.format("%s\n", res.getPathname());
  77             }
  78 
  79         } finally {
  80             writer.close();
  81         }
  82 
  83     }
  84 
  85     void printDependencies() throws IOException {
  86         printDependencies(false);
  87     }
  88 
  89     void printDependencies(boolean showDynamic) throws IOException {
  90         PrintWriter writer = new PrintWriter(Files.resolve(dir, module.name(), "dependencies"));
  91         try {
  92             // classes that this klass may depend on due to the AnnotatedDependency
  93             Map<Reference, Set<AnnotatedDependency>> annotatedDeps =
  94                 AnnotatedDependency.getReferences(module);
  95 
  96             for (Klass klass : module.classes()) {
  97                 Set<Klass> references = klass.getReferencedClasses();
  98                 for (Klass other : references) {
  99                     String classname = klass.getClassName();
 100                     boolean optional = OptionalDependency.isOptional(klass, other);
 101                     if (optional) {
 102                         classname = "[optional] " + classname;
 103                     }
 104 
 105                     Module m = module.getModuleDependence(other);
 106                     if (m != null || other.getModule() == null) {
 107                         writer.format("%-40s -> %s (%s)", classname, other, m);
 108                         Reference ref = new Reference(klass, other);
 109                         if (annotatedDeps.containsKey(ref)) {
 110                             for (AnnotatedDependency ad : annotatedDeps.get(ref)) {
 111                                 writer.format(" %s", ad.getTag());
 112                             }
 113                             // printed; so remove the dependency from the annotated deps list
 114                             annotatedDeps.remove(ref);
 115                         }
 116                         writer.format("\n");
 117                     }
 118                 }
 119             }
 120 
 121             // print remaining dependencies specified in AnnotatedDependency list
 122             if (annotatedDeps.size() > 0) {
 123                 for (Map.Entry<Reference, Set<AnnotatedDependency>> entry : annotatedDeps.entrySet()) {
 124                     Reference ref = entry.getKey();
 125                     Module m = module.getModuleDependence(ref.referree);
 126                     if (m != null || ref.referree.getModule() == null) {
 127                         String classname = ref.referrer.getClassName();
 128                         boolean optional = true;
 129                         boolean dynamic = true;
 130                         String tag = "";
 131                         for (AnnotatedDependency ad : entry.getValue()) {
 132                             if (optional && !ad.isOptional()) {
 133                                 optional = false;
 134                                 tag = ad.getTag();
 135                             }
 136 
 137                             if (!ad.isDynamic()) {
 138                                 dynamic = false;
 139                             }
 140                         }
 141                         if (!showDynamic && optional && dynamic) {
 142                             continue;
 143                         }
 144 
 145                         if (optional) {
 146                             classname = "[optional] " + classname;
 147                         } else if (dynamic) {
 148                             classname = "[dynamic] " + classname;
 149                         }
 150                         writer.format("%-40s -> %s (%s) %s%n", classname, ref.referree, m, tag);
 151                     }
 152                 }
 153             }
 154         } finally {
 155             writer.close();
 156         }
 157     }
 158 }