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