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

Wed, 13 Apr 2011 16:57:22 -0700

author
ohair
date
Wed, 13 Apr 2011 16:57:22 -0700
changeset 966
53f212bed4f4
parent 959
7916df9c99be
parent 962
0ff2bbd38f10
child 1080
edd7d9bd32dd
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 2009, 2011, 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  */
    26 package com.sun.tools.javac.nio;
    28 import java.io.IOException;
    29 import java.io.InputStream;
    30 import java.io.InputStreamReader;
    31 import java.io.OutputStream;
    32 import java.io.OutputStreamWriter;
    33 import java.io.Reader;
    34 import java.io.Writer;
    35 import java.net.URI;
    36 import java.nio.ByteBuffer;
    37 import java.nio.CharBuffer;
    38 import java.nio.charset.CharsetDecoder;
    39 import java.nio.file.Files;
    40 import java.nio.file.LinkOption;
    41 import java.nio.file.Path;
    42 import java.nio.file.attribute.BasicFileAttributes;
    43 import javax.lang.model.element.Modifier;
    44 import javax.lang.model.element.NestingKind;
    45 import javax.tools.JavaFileObject;
    47 import com.sun.tools.javac.util.BaseFileManager;
    50 /**
    51  *  Implementation of JavaFileObject using java.nio.file API.
    52  *
    53  *  <p>PathFileObjects are, for the most part, straightforward wrappers around
    54  *  Path objects. The primary complexity is the support for "inferBinaryName".
    55  *  This is left as an abstract method, implemented by each of a number of
    56  *  different factory methods, which compute the binary name based on
    57  *  information available at the time the file object is created.
    58  *
    59  *  <p><b>This is NOT part of any supported API.
    60  *  If you write code that depends on this, you do so at your own risk.
    61  *  This code and its internal interfaces are subject to change or
    62  *  deletion without notice.</b>
    63  */
    64 abstract class PathFileObject implements JavaFileObject {
    65     private JavacPathFileManager fileManager;
    66     private Path path;
    68     /**
    69      * Create a PathFileObject within a directory, such that the binary name
    70      * can be inferred from the relationship to the parent directory.
    71      */
    72     static PathFileObject createDirectoryPathFileObject(JavacPathFileManager fileManager,
    73             final Path path, final Path dir) {
    74         return new PathFileObject(fileManager, path) {
    75             @Override
    76             String inferBinaryName(Iterable<? extends Path> paths) {
    77                 return toBinaryName(dir.relativize(path));
    78             }
    79         };
    80     }
    82     /**
    83      * Create a PathFileObject in a file system such as a jar file, such that
    84      * the binary name can be inferred from its position within the filesystem.
    85      */
    86     static PathFileObject createJarPathFileObject(JavacPathFileManager fileManager,
    87             final Path path) {
    88         return new PathFileObject(fileManager, path) {
    89             @Override
    90             String inferBinaryName(Iterable<? extends Path> paths) {
    91                 return toBinaryName(path);
    92             }
    93         };
    94     }
    96     /**
    97      * Create a PathFileObject whose binary name can be inferred from the
    98      * relative path to a sibling.
    99      */
   100     static PathFileObject createSiblingPathFileObject(JavacPathFileManager fileManager,
   101             final Path path, final String relativePath) {
   102         return new PathFileObject(fileManager, path) {
   103             @Override
   104             String inferBinaryName(Iterable<? extends Path> paths) {
   105                 return toBinaryName(relativePath, "/");
   106             }
   107         };
   108     }
   110     /**
   111      * Create a PathFileObject whose binary name might be inferred from its
   112      * position on a search path.
   113      */
   114     static PathFileObject createSimplePathFileObject(JavacPathFileManager fileManager,
   115             final Path path) {
   116         return new PathFileObject(fileManager, path) {
   117             @Override
   118             String inferBinaryName(Iterable<? extends Path> paths) {
   119                 Path absPath = path.toAbsolutePath();
   120                 for (Path p: paths) {
   121                     Path ap = p.toAbsolutePath();
   122                     if (absPath.startsWith(ap)) {
   123                         try {
   124                             Path rp = ap.relativize(absPath);
   125                             if (rp != null) // maybe null if absPath same as ap
   126                                 return toBinaryName(rp);
   127                         } catch (IllegalArgumentException e) {
   128                             // ignore this p if cannot relativize path to p
   129                         }
   130                     }
   131                 }
   132                 return null;
   133             }
   134         };
   135     }
   137     protected PathFileObject(JavacPathFileManager fileManager, Path path) {
   138         fileManager.getClass(); // null check
   139         path.getClass();        // null check
   140         this.fileManager = fileManager;
   141         this.path = path;
   142     }
   144     abstract String inferBinaryName(Iterable<? extends Path> paths);
   146     /**
   147      * Return the Path for this object.
   148      * @return the Path for this object.
   149      */
   150     Path getPath() {
   151         return path;
   152     }
   154     @Override
   155     public Kind getKind() {
   156         return BaseFileManager.getKind(path.getFileName().toString());
   157     }
   159     @Override
   160     public boolean isNameCompatible(String simpleName, Kind kind) {
   161         simpleName.getClass();
   162         // null check
   163         if (kind == Kind.OTHER && getKind() != kind) {
   164             return false;
   165         }
   166         String sn = simpleName + kind.extension;
   167         String pn = path.getFileName().toString();
   168         if (pn.equals(sn)) {
   169             return true;
   170         }
   171         if (pn.equalsIgnoreCase(sn)) {
   172             try {
   173                 // allow for Windows
   174                 return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
   175             } catch (IOException e) {
   176             }
   177         }
   178         return false;
   179     }
   181     @Override
   182     public NestingKind getNestingKind() {
   183         return null;
   184     }
   186     @Override
   187     public Modifier getAccessLevel() {
   188         return null;
   189     }
   191     @Override
   192     public URI toUri() {
   193         return path.toUri();
   194     }
   196     @Override
   197     public String getName() {
   198         return path.toString();
   199     }
   201     @Override
   202     public InputStream openInputStream() throws IOException {
   203         return Files.newInputStream(path);
   204     }
   206     @Override
   207     public OutputStream openOutputStream() throws IOException {
   208         ensureParentDirectoriesExist();
   209         return Files.newOutputStream(path);
   210     }
   212     @Override
   213     public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   214         CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
   215         return new InputStreamReader(openInputStream(), decoder);
   216     }
   218     @Override
   219     public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   220         CharBuffer cb = fileManager.getCachedContent(this);
   221         if (cb == null) {
   222             InputStream in = openInputStream();
   223             try {
   224                 ByteBuffer bb = fileManager.makeByteBuffer(in);
   225                 JavaFileObject prev = fileManager.log.useSource(this);
   226                 try {
   227                     cb = fileManager.decode(bb, ignoreEncodingErrors);
   228                 } finally {
   229                     fileManager.log.useSource(prev);
   230                 }
   231                 fileManager.recycleByteBuffer(bb);
   232                 if (!ignoreEncodingErrors) {
   233                     fileManager.cache(this, cb);
   234                 }
   235             } finally {
   236                 in.close();
   237             }
   238         }
   239         return cb;
   240     }
   242     @Override
   243     public Writer openWriter() throws IOException {
   244         ensureParentDirectoriesExist();
   245         return new OutputStreamWriter(Files.newOutputStream(path), fileManager.getEncodingName());
   246     }
   248     @Override
   249     public long getLastModified() {
   250         try {
   251             return Files.getLastModifiedTime(path).toMillis();
   252         } catch (IOException e) {
   253             return -1;
   254         }
   255     }
   257     @Override
   258     public boolean delete() {
   259         try {
   260             Files.delete(path);
   261             return true;
   262         } catch (IOException e) {
   263             return false;
   264         }
   265     }
   267     public boolean isSameFile(PathFileObject other) {
   268         try {
   269             return Files.isSameFile(path, other.path);
   270         } catch (IOException e) {
   271             return false;
   272         }
   273     }
   275     @Override
   276     public boolean equals(Object other) {
   277         return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
   278     }
   280     @Override
   281     public int hashCode() {
   282         return path.hashCode();
   283     }
   285     @Override
   286     public String toString() {
   287         return getClass().getSimpleName() + "[" + path + "]";
   288     }
   290     private void ensureParentDirectoriesExist() throws IOException {
   291         Path parent = path.getParent();
   292         if (parent != null)
   293             Files.createDirectories(parent);
   294     }
   296     private long size() {
   297         try {
   298             return Files.size(path);
   299         } catch (IOException e) {
   300             return -1;
   301         }
   302     }
   304     protected static String toBinaryName(Path relativePath) {
   305         return toBinaryName(relativePath.toString(),
   306                 relativePath.getFileSystem().getSeparator());
   307     }
   309     protected static String toBinaryName(String relativePath, String sep) {
   310         return removeExtension(relativePath).replace(sep, ".");
   311     }
   313     protected static String removeExtension(String fileName) {
   314         int lastDot = fileName.lastIndexOf(".");
   315         return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
   316     }
   317 }

mercurial