1 /*
   2  * Copyright (c) 1995, 2004, 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 sun.tools.java;
  27 
  28 import java.util.Enumeration;
  29 import java.io.File;
  30 import java.io.IOException;
  31 
  32 /**
  33  * This class is used to represent the classes in a package.
  34  *
  35  * WARNING: The contents of this source file are not part of any
  36  * supported API.  Code that depends on them does so at its own risk:
  37  * they are subject to change or removal without notice.
  38  */
  39 public
  40 class Package {
  41     /**
  42      * The path which we use to locate source files.
  43      */
  44     ClassPath sourcePath;
  45 
  46     /**
  47      * The path which we use to locate class (binary) files.
  48      */
  49     ClassPath binaryPath;
  50 
  51     /**
  52      * The path name of the package.
  53      */
  54     String pkg;
  55 
  56     /**
  57      * Create a package given a class path, and package name.
  58      */
  59     public Package(ClassPath path, Identifier pkg) throws IOException {
  60         this(path, path, pkg);
  61     }
  62 
  63     /**
  64      * Create a package given a source path, binary path, and package
  65      * name.
  66      */
  67     public Package(ClassPath sourcePath,
  68                    ClassPath binaryPath,
  69                    Identifier pkg)
  70     throws IOException {
  71         if (pkg.isInner())
  72             pkg = Identifier.lookup(pkg.getQualifier(), pkg.getFlatName());
  73         this.sourcePath = sourcePath;
  74         this.binaryPath = binaryPath;
  75         this.pkg = pkg.toString().replace('.', File.separatorChar);
  76     }
  77 
  78     /**
  79      * Check if a class is defined in this package.
  80      * (If it is an inner class name, it is assumed to exist
  81      * only if its binary file exists.  This is somewhat pessimistic.)
  82      */
  83     public boolean classExists(Identifier className) {
  84         return getBinaryFile(className) != null ||
  85                 !className.isInner() &&
  86                getSourceFile(className) != null;
  87     }
  88 
  89     /**
  90      * Check if the package exists
  91      */
  92     public boolean exists() {
  93         // Look for the directory on our binary path.
  94         ClassFile dir = binaryPath.getDirectory(pkg);
  95         if (dir != null && dir.isDirectory()) {
  96             return true;
  97         }
  98 
  99         if (sourcePath != binaryPath) {
 100             // Look for the directory on our source path.
 101             dir = sourcePath.getDirectory(pkg);
 102             if (dir != null && dir.isDirectory()) {
 103                 return true;
 104             }
 105         }
 106 
 107         /* Accommodate ZIP files without CEN entries for directories
 108          * (packages): look on class path for at least one binary
 109          * file or one source file with the right package prefix
 110          */
 111         String prefix = pkg + File.separator;
 112 
 113         return binaryPath.getFiles(prefix, ".class").hasMoreElements()
 114             || sourcePath.getFiles(prefix, ".java").hasMoreElements();
 115     }
 116 
 117     private String makeName(String fileName) {
 118         return pkg.equals("") ? fileName : pkg + File.separator + fileName;
 119     }
 120 
 121     /**
 122      * Get the .class file of a class
 123      */
 124     public ClassFile getBinaryFile(Identifier className) {
 125         className = Type.mangleInnerType(className);
 126         String fileName = className.toString() + ".class";
 127         return binaryPath.getFile(makeName(fileName));
 128     }
 129 
 130     /**
 131      * Get the .java file of a class
 132      */
 133     public ClassFile getSourceFile(Identifier className) {
 134         // The source file of an inner class is that of its outer class.
 135         className = className.getTopName();
 136         String fileName = className.toString() + ".java";
 137         return sourcePath.getFile(makeName(fileName));
 138     }
 139 
 140     public ClassFile getSourceFile(String fileName) {
 141         if (fileName.endsWith(".java")) {
 142             return sourcePath.getFile(makeName(fileName));
 143         }
 144         return null;
 145     }
 146 
 147     public Enumeration<ClassFile> getSourceFiles() {
 148         return sourcePath.getFiles(pkg, ".java");
 149     }
 150 
 151     public Enumeration<ClassFile> getBinaryFiles() {
 152         return binaryPath.getFiles(pkg, ".class");
 153     }
 154 
 155     public String toString() {
 156         if (pkg.equals("")) {
 157             return "unnamed package";
 158         }
 159         return "package " + pkg;
 160     }
 161 }