RelativePath.java revision 2721:f7ce2cfa4cdb
1/* 2 * Copyright (c) 2008, 2014, 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 com.sun.tools.javac.file; 27 28import java.io.File; 29import java.nio.file.FileSystems; 30import java.nio.file.InvalidPathException; 31import java.nio.file.Path; 32import java.nio.file.Paths; 33import java.util.zip.ZipEntry; 34import java.util.zip.ZipFile; 35 36import javax.tools.JavaFileObject; 37 38/** 39 * Used to represent a platform-neutral path within a platform-specific 40 * container, such as a directory or zip file. 41 * Internally, the file separator is always '/'. 42 * 43 * <p><b>This is NOT part of any supported API. 44 * If you write code that depends on this, you do so at your own risk. 45 * This code and its internal interfaces are subject to change or 46 * deletion without notice.</b> 47 */ 48public abstract class RelativePath implements Comparable<RelativePath> { 49 /** 50 * @param p must use '/' as an internal separator 51 */ 52 protected RelativePath(String p) { 53 path = p; 54 } 55 56 public abstract RelativeDirectory dirname(); 57 58 public abstract String basename(); 59 60 public File getFile(File directory) { 61 if (path.length() == 0) 62 return directory; 63 return new File(directory, path.replace('/', File.separatorChar)); 64 } 65 66 public Path getFile(Path directory) throws /*unchecked*/ InvalidPathException { 67 if (directory == null) { 68 String sep = FileSystems.getDefault().getSeparator(); 69 return Paths.get(path.replace("/", sep)); 70 } else { 71 String sep = directory.getFileSystem().getSeparator(); 72 return directory.resolve(path.replace("/", sep)); 73 } 74 } 75 76 public int compareTo(RelativePath other) { 77 return path.compareTo(other.path); 78 } 79 80 @Override 81 public boolean equals(Object other) { 82 if (!(other instanceof RelativePath)) 83 return false; 84 return path.equals(((RelativePath) other).path); 85 } 86 87 @Override 88 public int hashCode() { 89 return path.hashCode(); 90 } 91 92 @Override 93 public String toString() { 94 return "RelPath[" + path + "]"; 95 } 96 97 public String getPath() { 98 return path; 99 } 100 101 protected final String path; 102 103 /** 104 * Used to represent a platform-neutral subdirectory within a platform-specific 105 * container, such as a directory or zip file. 106 * Internally, the file separator is always '/', and if the path is not empty, 107 * it always ends in a '/' as well. 108 */ 109 public static class RelativeDirectory extends RelativePath { 110 111 static RelativeDirectory forPackage(CharSequence packageName) { 112 return new RelativeDirectory(packageName.toString().replace('.', '/')); 113 } 114 115 /** 116 * @param p must use '/' as an internal separator 117 */ 118 public RelativeDirectory(String p) { 119 super(p.length() == 0 || p.endsWith("/") ? p : p + "/"); 120 } 121 122 /** 123 * @param p must use '/' as an internal separator 124 */ 125 public RelativeDirectory(RelativeDirectory d, String p) { 126 this(d.path + p); 127 } 128 129 @Override 130 public RelativeDirectory dirname() { 131 int l = path.length(); 132 if (l == 0) 133 return this; 134 int sep = path.lastIndexOf('/', l - 2); 135 return new RelativeDirectory(path.substring(0, sep + 1)); 136 } 137 138 @Override 139 public String basename() { 140 int l = path.length(); 141 if (l == 0) 142 return path; 143 int sep = path.lastIndexOf('/', l - 2); 144 return path.substring(sep + 1, l - 1); 145 } 146 147 /** 148 * Return true if this subdirectory "contains" the other path. 149 * A subdirectory path does not contain itself. 150 **/ 151 boolean contains(RelativePath other) { 152 return other.path.length() > path.length() && other.path.startsWith(path); 153 } 154 155 @Override 156 public String toString() { 157 return "RelativeDirectory[" + path + "]"; 158 } 159 } 160 161 /** 162 * Used to represent a platform-neutral file within a platform-specific 163 * container, such as a directory or zip file. 164 * Internally, the file separator is always '/'. It never ends in '/'. 165 */ 166 public static class RelativeFile extends RelativePath { 167 static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) { 168 return new RelativeFile(className.toString().replace('.', '/') + kind.extension); 169 } 170 171 public RelativeFile(String p) { 172 super(p); 173 if (p.endsWith("/")) 174 throw new IllegalArgumentException(p); 175 } 176 177 /** 178 * @param p must use '/' as an internal separator 179 */ 180 public RelativeFile(RelativeDirectory d, String p) { 181 this(d.path + p); 182 } 183 184 RelativeFile(RelativeDirectory d, RelativePath p) { 185 this(d, p.path); 186 } 187 188 @Override 189 public RelativeDirectory dirname() { 190 int sep = path.lastIndexOf('/'); 191 return new RelativeDirectory(path.substring(0, sep + 1)); 192 } 193 194 @Override 195 public String basename() { 196 int sep = path.lastIndexOf('/'); 197 return path.substring(sep + 1); 198 } 199 200 ZipEntry getZipEntry(ZipFile zip) { 201 return zip.getEntry(path); 202 } 203 204 @Override 205 public String toString() { 206 return "RelativeFile[" + path + "]"; 207 } 208 209 } 210 211} 212