001 /*
002 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.javac.file;
027
028 import java.io.File;
029 import java.util.zip.ZipEntry;
030 import java.util.zip.ZipFile;
031 import javax.tools.JavaFileObject;
032
033 /**
034 * Used to represent a platform-neutral path within a platform-specific
035 * container, such as a directory or zip file.
036 * Internally, the file separator is always '/'.
037 */
038 public abstract class RelativePath implements Comparable<RelativePath> {
039 /**
040 * @param p must use '/' as an internal separator
041 */
042 protected RelativePath(String p) {
043 path = p;
044 }
045
046 public abstract RelativeDirectory dirname();
047
048 public abstract String basename();
049
050 public File getFile(File directory) {
051 if (path.length() == 0)
052 return directory;
053 return new File(directory, path.replace('/', File.separatorChar));
054 }
055
056 public int compareTo(RelativePath other) {
057 return path.compareTo(other.path);
058 }
059
060 @Override
061 public boolean equals(Object other) {
062 if (!(other instanceof RelativePath))
063 return false;
064 return path.equals(((RelativePath) other).path);
065 }
066
067 @Override
068 public int hashCode() {
069 return path.hashCode();
070 }
071
072 @Override
073 public String toString() {
074 return "RelPath[" + path + "]";
075 }
076
077 public String getPath() {
078 return path;
079 }
080
081 protected final String path;
082
083 /**
084 * Used to represent a platform-neutral subdirectory within a platform-specific
085 * container, such as a directory or zip file.
086 * Internally, the file separator is always '/', and if the path is not empty,
087 * it always ends in a '/' as well.
088 */
089 public static class RelativeDirectory extends RelativePath {
090
091 static RelativeDirectory forPackage(CharSequence packageName) {
092 return new RelativeDirectory(packageName.toString().replace('.', '/'));
093 }
094
095 /**
096 * @param p must use '/' as an internal separator
097 */
098 public RelativeDirectory(String p) {
099 super(p.length() == 0 || p.endsWith("/") ? p : p + "/");
100 }
101
102 /**
103 * @param p must use '/' as an internal separator
104 */
105 public RelativeDirectory(RelativeDirectory d, String p) {
106 this(d.path + p);
107 }
108
109 @Override
110 public RelativeDirectory dirname() {
111 int l = path.length();
112 if (l == 0)
113 return this;
114 int sep = path.lastIndexOf('/', l - 2);
115 return new RelativeDirectory(path.substring(0, sep + 1));
116 }
117
118 @Override
119 public String basename() {
120 int l = path.length();
121 if (l == 0)
122 return path;
123 int sep = path.lastIndexOf('/', l - 2);
124 return path.substring(sep + 1, l - 1);
125 }
126
127 /**
128 * Return true if this subdirectory "contains" the other path.
129 * A subdirectory path does not contain itself.
130 **/
131 boolean contains(RelativePath other) {
132 return other.path.length() > path.length() && other.path.startsWith(path);
133 }
134
135 @Override
136 public String toString() {
137 return "RelativeDirectory[" + path + "]";
138 }
139 }
140
141 /**
142 * Used to represent a platform-neutral file within a platform-specific
143 * container, such as a directory or zip file.
144 * Internally, the file separator is always '/'. It never ends in '/'.
145 */
146 public static class RelativeFile extends RelativePath {
147 static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) {
148 return new RelativeFile(className.toString().replace('.', '/') + kind.extension);
149 }
150
151 public RelativeFile(String p) {
152 super(p);
153 if (p.endsWith("/"))
154 throw new IllegalArgumentException(p);
155 }
156
157 /**
158 * @param p must use '/' as an internal separator
159 */
160 public RelativeFile(RelativeDirectory d, String p) {
161 this(d.path + p);
162 }
163
164 RelativeFile(RelativeDirectory d, RelativePath p) {
165 this(d, p.path);
166 }
167
168 @Override
169 public RelativeDirectory dirname() {
170 int sep = path.lastIndexOf('/');
171 return new RelativeDirectory(path.substring(0, sep + 1));
172 }
173
174 @Override
175 public String basename() {
176 int sep = path.lastIndexOf('/');
177 return path.substring(sep + 1);
178 }
179
180 ZipEntry getZipEntry(ZipFile zip) {
181 return zip.getEntry(path);
182 }
183
184 @Override
185 public String toString() {
186 return "RelativeFile[" + path + "]";
187 }
188
189 }
190
191 }