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
26package sun.tools.java;
27
28import java.util.Enumeration;
29import java.io.File;
30import 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 */
39public
40class 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}
162