src/share/classes/com/sun/tools/javac/nio/PathFileObject.java

Mon, 11 Jan 2010 14:12:10 -0800

author
jjg
date
Mon, 11 Jan 2010 14:12:10 -0800
changeset 466
ca6bc36b2305
parent 450
4011f49b4af8
child 554
9d9f26857129
permissions
-rw-r--r--

6915476: java.util.regex.PatternSyntaxException in com.sun.tools.javac.nio.PathFileObject
Reviewed-by: darcy

jjg@450 1 /*
jjg@450 2 * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
jjg@450 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@450 4 *
jjg@450 5 * This code is free software; you can redistribute it and/or modify it
jjg@450 6 * under the terms of the GNU General Public License version 2 only, as
jjg@450 7 * published by the Free Software Foundation. Sun designates this
jjg@450 8 * particular file as subject to the "Classpath" exception as provided
jjg@450 9 * by Sun in the LICENSE file that accompanied this code.
jjg@450 10 *
jjg@450 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@450 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@450 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@450 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@450 15 * accompanied this code).
jjg@450 16 *
jjg@450 17 * You should have received a copy of the GNU General Public License version
jjg@450 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@450 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@450 20 *
jjg@450 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
jjg@450 22 * CA 95054 USA or visit www.sun.com if you need additional information or
jjg@450 23 * have any questions.
jjg@450 24 */
jjg@450 25
jjg@450 26 package com.sun.tools.javac.nio;
jjg@450 27
jjg@450 28 import java.io.IOException;
jjg@450 29 import java.io.InputStream;
jjg@450 30 import java.io.InputStreamReader;
jjg@450 31 import java.io.OutputStream;
jjg@450 32 import java.io.OutputStreamWriter;
jjg@450 33 import java.io.Reader;
jjg@450 34 import java.io.Writer;
jjg@450 35 import java.net.URI;
jjg@450 36 import java.nio.ByteBuffer;
jjg@450 37 import java.nio.CharBuffer;
jjg@450 38 import java.nio.charset.CharsetDecoder;
jjg@450 39 import java.nio.file.Files;
jjg@450 40 import java.nio.file.Path;
jjg@450 41 import java.nio.file.attribute.Attributes;
jjg@450 42 import java.nio.file.attribute.BasicFileAttributes;
jjg@450 43 import javax.lang.model.element.Modifier;
jjg@450 44 import javax.lang.model.element.NestingKind;
jjg@450 45 import javax.tools.JavaFileObject;
jjg@450 46
jjg@450 47 import com.sun.tools.javac.util.BaseFileManager;
jjg@450 48
jjg@450 49
jjg@450 50 /**
jjg@450 51 * Implementation of JavaFileObject using java.nio.file API.
jjg@450 52 *
jjg@450 53 * <p>PathFileObjects are, for the most part, straightforward wrappers around
jjg@450 54 * Path objects. The primary complexity is the support for "inferBinaryName".
jjg@450 55 * This is left as an abstract method, implemented by each of a number of
jjg@450 56 * different factory methods, which compute the binary name based on
jjg@450 57 * information available at the time the file object is created.
jjg@450 58 *
jjg@450 59 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
jjg@450 60 * you write code that depends on this, you do so at your own risk.
jjg@450 61 * This code and its internal interfaces are subject to change or
jjg@450 62 * deletion without notice.</b>
jjg@450 63 */
jjg@450 64 abstract class PathFileObject implements JavaFileObject {
jjg@450 65 private JavacPathFileManager fileManager;
jjg@450 66 private Path path;
jjg@450 67
jjg@450 68 /**
jjg@450 69 * Create a PathFileObject within a directory, such that the binary name
jjg@450 70 * can be inferred from the relationship to the parent directory.
jjg@450 71 */
jjg@450 72 static PathFileObject createDirectoryPathFileObject(JavacPathFileManager fileManager,
jjg@450 73 final Path path, final Path dir) {
jjg@450 74 return new PathFileObject(fileManager, path) {
jjg@450 75 @Override
jjg@450 76 String inferBinaryName(Iterable<? extends Path> paths) {
jjg@450 77 return toBinaryName(dir.relativize(path));
jjg@450 78 }
jjg@450 79 };
jjg@450 80 }
jjg@450 81
jjg@450 82 /**
jjg@450 83 * Create a PathFileObject in a file system such as a jar file, such that
jjg@450 84 * the binary name can be inferred from its position within the filesystem.
jjg@450 85 */
jjg@450 86 static PathFileObject createJarPathFileObject(JavacPathFileManager fileManager,
jjg@450 87 final Path path) {
jjg@450 88 return new PathFileObject(fileManager, path) {
jjg@450 89 @Override
jjg@450 90 String inferBinaryName(Iterable<? extends Path> paths) {
jjg@450 91 return toBinaryName(path);
jjg@450 92 }
jjg@450 93 };
jjg@450 94 }
jjg@450 95
jjg@450 96 /**
jjg@450 97 * Create a PathFileObject whose binary name can be inferred from the
jjg@450 98 * relative path to a sibling.
jjg@450 99 */
jjg@450 100 static PathFileObject createSiblingPathFileObject(JavacPathFileManager fileManager,
jjg@450 101 final Path path, final String relativePath) {
jjg@450 102 return new PathFileObject(fileManager, path) {
jjg@450 103 @Override
jjg@450 104 String inferBinaryName(Iterable<? extends Path> paths) {
jjg@450 105 return toBinaryName(relativePath, "/");
jjg@450 106 }
jjg@450 107 };
jjg@450 108 }
jjg@450 109
jjg@450 110 /**
jjg@450 111 * Create a PathFileObject whose binary name might be inferred from its
jjg@450 112 * position on a search path.
jjg@450 113 */
jjg@450 114 static PathFileObject createSimplePathFileObject(JavacPathFileManager fileManager,
jjg@450 115 final Path path) {
jjg@450 116 return new PathFileObject(fileManager, path) {
jjg@450 117 @Override
jjg@450 118 String inferBinaryName(Iterable<? extends Path> paths) {
jjg@450 119 Path absPath = path.toAbsolutePath();
jjg@450 120 for (Path p: paths) {
jjg@450 121 Path ap = p.toAbsolutePath();
jjg@450 122 if (absPath.startsWith(ap)) {
jjg@450 123 try {
jjg@450 124 Path rp = ap.relativize(absPath);
jjg@450 125 if (rp != null) // maybe null if absPath same as ap
jjg@450 126 return toBinaryName(rp);
jjg@450 127 } catch (IllegalArgumentException e) {
jjg@450 128 // ignore this p if cannot relativize path to p
jjg@450 129 }
jjg@450 130 }
jjg@450 131 }
jjg@450 132 return null;
jjg@450 133 }
jjg@450 134 };
jjg@450 135 }
jjg@450 136
jjg@450 137 protected PathFileObject(JavacPathFileManager fileManager, Path path) {
jjg@450 138 fileManager.getClass(); // null check
jjg@450 139 path.getClass(); // null check
jjg@450 140 this.fileManager = fileManager;
jjg@450 141 this.path = path;
jjg@450 142 }
jjg@450 143
jjg@450 144 abstract String inferBinaryName(Iterable<? extends Path> paths);
jjg@450 145
jjg@450 146 /**
jjg@450 147 * Return the Path for this object.
jjg@450 148 * @return the Path for this object.
jjg@450 149 */
jjg@450 150 Path getPath() {
jjg@450 151 return path;
jjg@450 152 }
jjg@450 153
jjg@450 154 @Override
jjg@450 155 public Kind getKind() {
jjg@450 156 return BaseFileManager.getKind(path.getName().toString());
jjg@450 157 }
jjg@450 158
jjg@450 159 @Override
jjg@450 160 public boolean isNameCompatible(String simpleName, Kind kind) {
jjg@450 161 simpleName.getClass();
jjg@450 162 // null check
jjg@450 163 if (kind == Kind.OTHER && getKind() != kind) {
jjg@450 164 return false;
jjg@450 165 }
jjg@450 166 String sn = simpleName + kind.extension;
jjg@450 167 String pn = path.getName().toString();
jjg@450 168 if (pn.equals(sn)) {
jjg@450 169 return true;
jjg@450 170 }
jjg@450 171 if (pn.equalsIgnoreCase(sn)) {
jjg@450 172 try {
jjg@450 173 // allow for Windows
jjg@450 174 return path.toRealPath(false).getName().toString().equals(sn);
jjg@450 175 } catch (IOException e) {
jjg@450 176 }
jjg@450 177 }
jjg@450 178 return false;
jjg@450 179 }
jjg@450 180
jjg@450 181 @Override
jjg@450 182 public NestingKind getNestingKind() {
jjg@450 183 return null;
jjg@450 184 }
jjg@450 185
jjg@450 186 @Override
jjg@450 187 public Modifier getAccessLevel() {
jjg@450 188 return null;
jjg@450 189 }
jjg@450 190
jjg@450 191 @Override
jjg@450 192 public URI toUri() {
jjg@450 193 return path.toUri();
jjg@450 194 }
jjg@450 195
jjg@450 196 @Override
jjg@450 197 public String getName() {
jjg@450 198 return path.toString();
jjg@450 199 }
jjg@450 200
jjg@450 201 @Override
jjg@450 202 public InputStream openInputStream() throws IOException {
jjg@450 203 return path.newInputStream();
jjg@450 204 }
jjg@450 205
jjg@450 206 @Override
jjg@450 207 public OutputStream openOutputStream() throws IOException {
jjg@450 208 ensureParentDirectoriesExist();
jjg@450 209 return path.newOutputStream();
jjg@450 210 }
jjg@450 211
jjg@450 212 @Override
jjg@450 213 public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
jjg@450 214 CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
jjg@450 215 return new InputStreamReader(openInputStream(), decoder);
jjg@450 216 }
jjg@450 217
jjg@450 218 @Override
jjg@450 219 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
jjg@450 220 CharBuffer cb = fileManager.getCachedContent(this);
jjg@450 221 if (cb == null) {
jjg@450 222 InputStream in = openInputStream();
jjg@450 223 try {
jjg@450 224 ByteBuffer bb = fileManager.makeByteBuffer(in);
jjg@450 225 JavaFileObject prev = fileManager.log.useSource(this);
jjg@450 226 try {
jjg@450 227 cb = fileManager.decode(bb, ignoreEncodingErrors);
jjg@450 228 } finally {
jjg@450 229 fileManager.log.useSource(prev);
jjg@450 230 }
jjg@450 231 fileManager.recycleByteBuffer(bb);
jjg@450 232 if (!ignoreEncodingErrors) {
jjg@450 233 fileManager.cache(this, cb);
jjg@450 234 }
jjg@450 235 } finally {
jjg@450 236 in.close();
jjg@450 237 }
jjg@450 238 }
jjg@450 239 return cb;
jjg@450 240 }
jjg@450 241
jjg@450 242 @Override
jjg@450 243 public Writer openWriter() throws IOException {
jjg@450 244 ensureParentDirectoriesExist();
jjg@450 245 return new OutputStreamWriter(path.newOutputStream(), fileManager.getEncodingName());
jjg@450 246 }
jjg@450 247
jjg@450 248 @Override
jjg@450 249 public long getLastModified() {
jjg@450 250 try {
jjg@450 251 BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
jjg@450 252 return attrs.lastModifiedTime().toMillis();
jjg@450 253 } catch (IOException e) {
jjg@450 254 return -1;
jjg@450 255 }
jjg@450 256 }
jjg@450 257
jjg@450 258 @Override
jjg@450 259 public boolean delete() {
jjg@450 260 try {
jjg@450 261 path.delete();
jjg@450 262 return true;
jjg@450 263 } catch (IOException e) {
jjg@450 264 return false;
jjg@450 265 }
jjg@450 266 }
jjg@450 267
jjg@450 268 public boolean isSameFile(PathFileObject other) {
jjg@450 269 try {
jjg@450 270 return path.isSameFile(other.path);
jjg@450 271 } catch (IOException e) {
jjg@450 272 return false;
jjg@450 273 }
jjg@450 274 }
jjg@450 275
jjg@450 276 @Override
jjg@450 277 public boolean equals(Object other) {
jjg@450 278 return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
jjg@450 279 }
jjg@450 280
jjg@450 281 @Override
jjg@450 282 public int hashCode() {
jjg@450 283 return path.hashCode();
jjg@450 284 }
jjg@450 285
jjg@450 286 @Override
jjg@450 287 public String toString() {
jjg@450 288 return getClass().getSimpleName() + "[" + path + "]";
jjg@450 289 }
jjg@450 290
jjg@450 291 private void ensureParentDirectoriesExist() throws IOException {
jjg@450 292 Path parent = path.getParent();
jjg@450 293 if (parent != null)
jjg@450 294 Files.createDirectories(parent);
jjg@450 295 }
jjg@450 296
jjg@450 297 private long size() {
jjg@450 298 try {
jjg@450 299 BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
jjg@450 300 return attrs.size();
jjg@450 301 } catch (IOException e) {
jjg@450 302 return -1;
jjg@450 303 }
jjg@450 304 }
jjg@450 305
jjg@450 306 protected static String toBinaryName(Path relativePath) {
jjg@450 307 return toBinaryName(relativePath.toString(),
jjg@450 308 relativePath.getFileSystem().getSeparator());
jjg@450 309 }
jjg@450 310
jjg@450 311 protected static String toBinaryName(String relativePath, String sep) {
jjg@466 312 return removeExtension(relativePath).replace(sep, ".");
jjg@450 313 }
jjg@450 314
jjg@450 315 protected static String removeExtension(String fileName) {
jjg@450 316 int lastDot = fileName.lastIndexOf(".");
jjg@450 317 return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
jjg@450 318 }
jjg@450 319 }

mercurial