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